Hallo Liste, hallo Frank,
Du schriebst:
Da liegen wohl ein paar Missverständnisse vor. Der Rückgabewert ist der Wert, den die Funktion liefert. In diesem Fall ist der Rückgabewert eben ein Boolean (der angibt, ob die Umwandlung erfolgreich war oder nicht) und eben nicht das Ergebnis der Umwandlung. Dieses wird in dem 3. Parameter zurückgeliefert. Deshalb muss als 3. Parameter eben das Ziel (in deinem Fall "Leistung[eins]") übergeben werden -- nicht auch, sondern nur dort, während der Rückgabewert abgefragt werden kann, um Fehler zu erkennen. Wie gesagt, s. das Beispiel in dem Kommentar, dort werden die Zielvariablen ("Size", "Name", ...) ja auch nur an einer Stelle verwendet und die Rückgabewerte im "if" abgefragt.
Nun kann ich die Funktion korrekt aufrufen. Das hat zwar lange gedauert, aber ich glaube, daß ich es jetzt zum großen Teil verstanden habe: Also, die Funktion liefert NUR den Wert FALSE zurück, wenn keine Zahl aus dem String gelesen werden kann, anderenfalls aber TRUE UND das Ergebnis der Umwandlung.
Um das verstehen zu können, habe ich lange an einem kleinen Programm gebastelt, welches für mich deutlicher aufzeigt, wie es sich verhält:
8---------------------------------------------------------------------------------- Program String_nach_Int;
Uses gpc, stringutils;
Const Letzte_Zahl=5;
Var Zahl, I, J: Integer; Leistung: Array [1 .. Letzte_Zahl] of Integer = ( 7, 14, 34, 44, 77); Leistungs_String: Array [1 .. Letzte_Zahl] of String (20) = ('248', ' 54 b', '5 4b', 'b 54', 'bw lwz');
Zahl_String: String (20);
Begin (* String_nach_Int *) For J := 1 to Letzte_Zahl do Begin I := 1; Write ('Die Zahl ', Leistung [J]); If StrReadInt (Leistungs_String [J], I, Leistung [J]) Then WriteLn (' wird durch ', Leistung [J], ' aus der String-Variablen "', Leistungs_String [J], '" ersetzt.') Else WriteLn (' kann durch keine Zahl aus der String-Variablen "', Leistungs_String [J], '" ersetzt werden.'); End; End (* String_nach_Int *). 8----------------------------------------------------------------------------------
Das Ergebnis: Die Zahl 7 wird durch 248 aus der String-Variablen "248" ersetzt. Die Zahl 14 wird durch 54 aus der String-Variablen " 54 b" ersetzt. Die Zahl 34 wird durch 5 aus der String-Variablen "5 4b" ersetzt. Die Zahl 44 kann durch keine Zahl aus der String-Variablen "b 54" ersetzt werden. Die Zahl 77 kann durch keine Zahl aus der String-Variablen "bw lwz" ersetzt werden.
Daraus schließe ich, daß er solange nach Integer verwandelt, als er von anfang an oder nach führenden Leerzeichen eine Ziffer vorfindet. Sobald dann das erste Nicht-Ziffer-Zeichen auftaucht, bricht er die Verwandlung ab, die aber erfolgreich war, falls überhaupt etwas nach obigen Regeln verwandelt werden konnte.
Was ich aber noch nicht verstehe: Wieso schützt mich das besser vor Fehlern, als mein a-priori-Wissen um den reinen Zifferngehalt des zu verwandelnden Strings?
Schließlich wird in meinem Programm diese Zahl zusammen mit zwei anderen String-Bestandteilen nur in einer Datei abgelegt, um an anderer Stelle wieder ausgelesen und mit einem eigenen Parser (Trennzeichen hatte ich beim Speichern schon gesetzt) in die ursprünglichen Bestandteile zurückverwandelt zu werden.
Woher sollen da, wenn der Parser genau arbeitet (und das tut er), noch irgendwelche mysteriösen Nicht-Ziffer-Zeichen herkommen?
Außerdem: Falls in der 16-stelligen Unix-Zeit doch irgendwo irgendein anderes Zeichen als eine Ziffer auftauchen sollte, würde mir doch StrReadInt keine Warnung geben können, solange am Anfang noch mindestens eine Ziffer steht, oder?
Der Sinn ist, dass man auf diese Weise mehrere Werte aus einem String auslesen kann (was ja, wie gesagt der Hauptzweck dieser Funktionen ist) und die Fehlerabfrage einfach mit "and" kombinieren kann, damit man nicht für jeden einzelnen Wert eine Fehlerbehandlung schreiben muss (solange es einen nur interessiert, ob die Umwandlungen komplett erfolgreich sind oder nicht).
Wenn ich das richtig verstanden habe, nützt mir StrReadInt für meine Zwecke wohl doch nichts, weil ich ja nicht mehrere Werte aus dem betreffenden String auslesen möchte.
Weil Du aber so die Wichtigkeit einer Fehlerbehandlung hervorhebst, habe ich mir nun zum ersten Mal bewußt Gedanken darüber gemacht:
Bisher habe ich beim Programmieren immer all das akribisch auf genaues Funktionieren überprüft, was schon vorhanden war, bevor ich dem Programm weitere Bestandteile hinzugefügt habe.
Zu diesem Zweck habe ich auch immer so wie in dem kleinen Programm "String_nach_Int" Ausgabeanweisungen geschrieben (auch wesentlich komplexere), mit deren Hilfe Fehler schnell gefunden werden konnten.
So ist meine bisherige Erfahrung die, daß all das, was einmal funktioniert, auch in Zukunft immer funktioniert, und wenn es das scheinbar nicht tut, ist der Fehler IMMER in dem neuen Programmbestandteil zu finden, der ja noch nicht so genau geprüft wurde.
Die alten Kontrollen habe ich nach erwiesener Funktionsreinheit immer auch irgendwann, wenn sie wirklich nicht mehr gebraucht wurden, wieder entfernt.
Nun ist allerdings meine "Erfahrung" noch recht klein, und ich lasse mich da gerne eines besseren belehren, falls es gegen diese Vorgehensweise massive Bedenken geben sollte.
Nein, es stürzt nicht ab. Nur wird die html-Ausgabe nicht mehr vollständig aufgebaut, d.h. ich bekomme nicht das, was ich wollte, sondern er schreibt ab einem gewissen Punkt den html-Code nicht mehr weiter.
OK, das passiert, wenn er schon in mitten in der HTML-Ausgabe ist. Trotzdem steht die Fehlermeldung im Apache-Log (/var/log/apache/www.roland-goretzki.de-error_log -- habe mir mal erlaubt nachzusehen :-).
Natürlich, gerne. Dabei fällt mir auf, daß ich nicht einmal Leserechte daran besitze. Muß ich Peter mal fragen, wie ich daran komme.
[ ... ] Ja, so kann man die Fehlerstelle einkreisen, wenn auch umständlich. Mit der Fehlermeldung aus dem Log (oder bei nicht-CGI-Programmen direkt in der Fehlerausgabe) ist oft sofort klar, was los ist. Ansonsten enthält sie auch noch eine Positionsangabe wie "(error #452 at 806407f)". Diese kann man mit folgendem Programm einer Programmzeile zuordnen:
addr2line -e program 806407f
"program" ist dabei das compilierte Programm. Wichtig ist dabei, dass es mit "-g" (Debug-Info) compiliert wurde und seit dem Auftreten des Fehlers nicht verändert wurde (sonst verschieben sich die Positionen).
Das ist gut. Kannte ich noch nicht. Dazu brauch ich natürlich Lesezugriff auf das Log.
Danke für die große Geduld, dadurch lerne ich wirklich sehr viel. :-)
Fröhliche Grüße Roland