?
Remi schrieb:
Bei der while-Schleife wird ja zuerst geschaut, ob ein /n als letztes Zeichen eingelesen wurde und danach noch, ob fgets 0 zurückgegeben hat. Wenn also das letzte Zeichen ein /n ist, wird die Schleife sofort abgebrochen, ohne noch die zweite Bedingung zu prüfen.
Gehe ich recht in der Annahme, dass wenn ich bei der while-Schleife die Bedingungen vertausche, das Programm deswegen Unsinn ausgibt, weil durch das Prüfen der Bedingung ja schon der Nächste String eingelesen wird und dann beim nächsten durchlauf der for-Schleife wird wieder der nächste eingelesen und man überspringt quasi jeden zweiten?
Es wird auf '\n' (Zeilenumbruch) geprüft. Du kannst die Schleifenbedingung als "solange, wie nicht die ganze Zeile eingelesen wurde und noch etwas eingelesen werden kann" lesen.
Ansonsten ist das, was du schreibst, richtig, wobei sich weniger offensichtliche Muster ergeben, wenn eine Zeile länger als der Puffer ist, in den eingelesen wird.
Remi schrieb:
Was mir des weiteren noch aufgefallen ist, dass sie das Schreiben in die Datei auch anders realisiert haben. Sind diese beiden Möglichkeiten wirklich exakt gleichwertig (weil laut meinen Tests arbeiten sie gleich), oder sollte man eine von beiden bevorzugen? Es geht um:
fprintf(out, "%d %s",lnum , line);
oder
fprintf(out, "%d ", lnum);
fputs(line, out);
Kein wesentlicher Unterschied, und bei genauerer Betrachtung ist die fprintf-Variante in diesem Fall auch eleganter. Das hab ich davon, Code eben kurz hinzukladden.
Wenn es allerdings nur um die Ausgabe eines Strings geht, halte ich fputs bzw. ggf. puts für eine bessere Wahl als printf. Es ist ein kleiner Performancegewinn zu erwarten, aber vor allem finde ich es in solchen Fällen klarer, und man kann nicht auf Ideen wie
char line[1024];
fgets(line, sizeof(line), stdin);
printf(line); /* BUG! */
kommen, was dann böse Probleme macht, wenn jemand ein Prozentzeichen eingibt.
Remi schrieb:
Als letztes gibt es noch wieder das kleine Problem mit der letzten Zeile, denn falls diese kein Zeichen enthält, liest gets ja nur noch das EOF und gibt damit 0 zurück. Das hat dann aber zur Folge, dass in die letzte Zeile auch keine Zahl mehr geschrieben wird obwohl diese ja auch als Zeile gilt und somit auch noch eine erhalten müsste. Das Problem ist ja, dass die Zahl auf jeden Fall innerhalb der Schleife der entsprechenden Zeile vorangestellt werden muss. Und da die Schleife immer abbrechen muss, sobald fgets 0 zurückliefert, sehe ich keine Möglichkeit da in die letzte Zeile noch die Zahl reinzubekommen. Im nachhinein lässt sich ja auch nicht mehr prüfen, ob beim letzten Durchlauf die letzte Zeile leer war.
Wenn ich richtig verstehe, worauf du hinaus willst ("Zeile" interpretiert nach Cursorblinken im Texteditor), kannst du nach Ablauf der Schleife etwa
if(line[strlen(line) - 1] == '\n') {
fprintf(out, "%6d", lnum);
}
schreiben, aber ein solches Verfahren wäre ziemlich unüblich. Es läuft im Grunde darauf hinaus, einen Zeilenumbruch am Ende der letzten Zeile in der Datei so zu interpretieren, dass danach noch eine leere Zeile folgt; wozu das gut sein soll, ist mir nicht sofort ersichtlich.
Remi schrieb:
Zu allerletzt nochmal eine generelle Frage. Sollte man eigentlich immer wenn es möglich ist for-Schleifen benutzen? Weil man könnte ja in dem Beispiel auch einfach eine while-Schleife mit der gleichen Bedingung nutzen und am Ende lnum++.
Das ist Geschmackssache. Benutz das, was dir übersichtlicher scheint.