ich habe die Aufgabe bekommen in Lazarus ein Binärzahlen-Tester zu programmieren.
Dabei benutze ich das erste mal Funktionen.
So wie es gerade aussieht ist da wohl einiges Schief gelaufen... Kann mich vielleicht einer von euch verbessern?
procedure TForm1.Button1Click(Sender: TObject);
var binzahl: string;
begin
binzahl := Edit1.Text;
function binzahltest(bz:string):string;
var bz, ergebnis: string; i, erg: integer;
begin
anzahl := length(bz);
ergebnis := true;
for i := 1 to anzahl do
begin
if bz[i] = '0' or bz[i] = '1' then
begin
binzahltest := true;
erg := bz[i];
end
else
begin
binzahltest := false;
end;
end;
end;
if binzahltest(binzahl) = true then
begin
function umrechnen(bin:string):integer;
var i, anz, stelle, s, zweierpotenz, umrechnen: integer;
begin
anz := length(bin);
i := anz;
zweierpotenz := 1;
s := 0;
while i > 0 do
begin
stelle := bin[i];
s := s + stelle * zweierpotenz;
zweierpotenz := zweierpotenz * 2;
i := i - 1;
end;
umrechnen := s;
end;
end;
end;
Bei der Überprüfung des Strings klapperst Du den ganzen String ab - auch wenn schon ein Fehler passiert ist. Bei Deiner Routine flutscht ein String wie '01X01' ducrh, weil am Ende ein korrekter Wert steht.
Das wäre schon Richtig, aber in der Aufgabenstellung soll das mit "if ... then" gelöst werden.
Die haben den "in" Operator sicherlich noch nicht gehabt.
Wird der Code überhaupt vom Compiler akzeptiert? Meines Wissens ist es nicht möglich innerhalb eines begin-end Blocks eine Funktion zu implementieren. Solcher Unsinn wird zwar immer wieder gefordert, hat aber noch nicht Einzug in Free Pascal gefunden.
procedure TForm1.ButtonClick(Sender: TObject);
begin
function binzahltest(bz: String): String; // Implementierung *IM* begin-end Block
begin
...
end;
if binzahltest(...).... then begin
...
end;
end;
procedure TForm1.ButtonClick(Sender: TObject);
function binzahltest(bz: String): String; // Implementierung *VOR* dem "begin" der Prozedur, vor oder nach der Deklaration lokaler Variablen
begin
...
end;
begin
if binzahltest(...) then begin
...
end;
end;
oder, falls nichts aus der Klasse TForm1 und keine lokale Variale von ButtonClick benutzt wird
function binzahltest(bz: String): String; // Implementierung *AUßERHALB* der Prozedur
begin
...
end;
procedure TForm1.ButtonClick(Sender: TObject);
begin
if binzahltest(...) then begin
...
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
function binzahltest(bz:string):string;
var ergebnis: string; i, anzahl, erg: integer;
begin
anzahl := length(bz);
ergebnis := true;
for i := 1 to anzahl do
begin
if bz[i] = '0' or bz[i] = '1' then
begin
binzahltest := true;
erg := bz[i];
end
else
begin
binzahltest := false;
end;
end;
end;
function umrechnen(bin:string):integer;
var i, anz, stelle, s, zweierpotenz, umrechnen: integer;
begin
anz := length(bin);
i := anz;
zweierpotenz := 1;
s := 0;
while i > 0 do
begin
stelle := bin[i];
s := s + stelle * zweierpotenz;
zweierpotenz := zweierpotenz * 2;
i := i - 1;
end;
umrechnen := s;
end;
var binzahl: string;
begin
binzahl := Edit1.Text;
if binzahltest(binzahl) = true then
begin
Label1.Caption := 'Yes';
Label1.Visible := true;
end;
end;
Nachdem das ganze überschaubar ist, habe ich mir die Mühe gemacht, deinen Code in ein kleines Projekt einzufügen und den Compiler um Hilfe gebeten.
Nachdem das Projekt fertig zusammengeklickt war, habe ich versucht es zu kompilieren und der Compiler hat eine Vielzahl von Fehlern bemerkt. Diese sind alle im Nachrichtenfenster aufgelistet. Klicke die Meldungen Zeile für Zeile an, und der Editor springt an die entsprechende, bemängelte Quelltest-Stelle.
1. Fehler in "binzahltest", Zeile "ergebnis := true": Im Nachrichtenfenster steht: "Incompatible types: got 'boolean', expected 'AnsiString'". Der cursor steht auf "true" - also mag der Compiler hier das "true" nicht. Und das ist klar, denn du hast zwei Zeilen höher die Variable "ergebnis" als String deklariert - ein String kann nicht true oder false werden, das ist reserviert für den Datentyp boolean. Also: geh' in dich, und überleg dir, was "ergebnis" sein soll. Und übrigens wird "ergebnis" in der ganzen "binzahltest" Routine nicht verwendet; daher habe ich die Zeile auskommentiert, um weiterzukommen.
2. Fehler: "if bz[ i] = '0' or bz[ i] = '1' then". Hier ist die Fehlermeldung wahrscheinlich verwirrend: "Operator not overloaded "Char" or "Char"". Dazu musst du wissen, dass der Operator "or" stärker ist als der Vergleichsoperator ("="). Die "or"-Verknüpfung zwischen die beiden Char-Größen "0" und bz[ i] ist aber gar nicht definiert. (Und wenn sie es wäre, käme das nächste Problem, dass da ein drei-gliedriger Vergleich stehen würde, wie "if a = b =c", den gibt es auch nicht). Solche Problem kannst du vermeiden, wenn du die mit "or" oder "and" verknüpften Ausdrücke immer in Klammern setzt. Damit wird das "o" eine verknüpfung von zwei boolschen Ausdrücken und macht kein Problem mehr. Also: "if (bz[ i] = '0') or (bz[ i] = '1') then".
3. Problem: "binzahltest := true" - wie oben unter 1: Die Funktion "binzahltest" ist so deklariert, dass sie einen String zurückliefern soll, du gibst dem Ergebnis aber einen booleschen Wert, dasselbe passiert auch ein paar Zeilen tiefer. Ich habe deinen Algorithmus nicht studiert, aber möglicherweise ist einfach die Funktion falsch deklariert und soll einen booleschen Wert zurückgeben.
4. Problem: "erg := bz[ i]" - "incompatible types: got "char" expected "longint"": "erg" ist deklariert als integer, bz ist ein String, also ist bz[ i] ein Char. Das passt nicht zusammen (übrigens wird auch "erg" nicht weiterverwendet)
5. Problem: "Duplicate Identifier "UMRECHNEN"". Das ist in der nächsten Funktion "Umrechnen(bin:string): integer". Hier hast du im "var"-Abschnitt eine lokale Variable deklariert, die denselben Namen trägt wie die Funktion. Das geht nicht. Nenne eins von den beiden anders.
usw.
Also: Jede Fehlermeldung des Compilers ist ein Hinweis, dass etwas falsch ist, und im Nachrichtenfenster steht, was falsch ist (leider ist die Meldung nicht immer klar zu verstehen...)
wp_xyz hat geschrieben: Di 12. Mai 2020, 23:50
Also: Jede Fehlermeldung des Compilers ist ein Hinweis, dass etwas falsch ist, und im Nachrichtenfenster steht, was falsch ist (leider ist die Meldung nicht immer klar zu verstehen...)
Da gebe ich dir Recht. Wobei die Fehlerausgaben des Free Pascal Compilers gar nicht so schlecht sind. Ich hatte mal das Pech ein größeres Perl Projekt betreuen zu müssen. Da hat man das Gefühl, dass der beim kleinsten typo ein chinesisches Buch ausspuckt.
ich habe dein kleines Programm einmal in eine funktionierende Form gebracht. Solltest du das Ganze im Rahmen einer Schulaufgabe verwenden, solltest du vorher versuchen, den Code auch zu verstehen. Nicht, dass du rote Ohren bekommst.
Da der Judas schon eine "fertige" Lösung gepostet hat,
kann ich meinen Versuch von gestern ja nun auch posten,
Ich hatte es bewusst zurück gehalten um die Kreativität des Posters nicht zu beeinfussen...
function Check(s:string):Integer;
var i:Integer;
begin
for i:=1 to length(s) do
if (s[i] <> '0') and (s[i] <> '1') then begin
result:=i; // Fehlerposition zurück geben
exit; // fertig
end;
result:=0; // kein Fehler
end;
function Calculate(s:string):Integer;
var n,i:integer;
begin
result:=0;
n:=1;
for i:=length(s) downto 1 do begin // von rechts nach links
if s[i] = '1' then
result:=result+n;
n := n shl 1;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var value:String; Fehler:Integer;
begin
value:='10011010010'; // sollte 1234 ergeben
Fehler:=Check(value);
if Fehler = 0 then caption:=IntToStr(Calculate(value))
else caption:='Fehler an Position: ' + IntToStr(Fehler);
end;
Grüße von Siro Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...