Hallo,
ungetc() funktioniert auch mit Files, die im read-only-Modus geöffnet
wurden. Sehe ich das richtig?
Und man kann sogar Buchstaben zurückschieben, die gar nicht da waren?
Bei einem read-only-File?
1
FILE*fp=fopen("text.txt","r");
2
3
intch;
4
5
for(inti=0;i<5;i++){
6
if((ch=getc(fp))!=EOF){
7
putchar(ch);
8
}
9
10
ungetc(ch,fp);
11
}
12
13
for(inti=0;i<5;i++){
14
if((ch=getc(fp))!=EOF){
15
putchar(ch);
16
}
17
18
ungetc('5',fp);//was anderes zurückschreiben
19
}
Irgendwie ist das komisch und unlogisch. Das "funktioniert" so, weil da
alles gepuffert ist oder?
komisch schrieb:> ungetc (ch, fp);
ungetc pushes the char back into the file buffer.
ungetc does not change the file on disk.
Es hilft also, das Handbuch zu lesen.
Nick M. schrieb:> ungetc pushes the char back into the file buffer.> ungetc does not change the file on disk.>> Es hilft also, das Handbuch zu lesen.
Ja, aber das ist doch unlogisch. Warum kann ich etwas zurückschieben,
was in diesem read-only-File gar nicht da war.
Wäre es nicht besser so ein Puffer auch als read-only zu definieren? Und
die gelesene Variable intern zu speichern?
So dass der Aufruf von ungetc() diese Variable zurückschiebt (und nicht
was Beliebiges).
Warum ist es schlecht eine interne Variable zu haben, die dann per
ungetc()-Aufruf zurückgesetzt werden kann? Und dadurch verbieten, dass
der User alles Mögliche zurückschiebt? (quase als read-only definieren)
Wenn ich alles richtig verstanden habe, dann wird vom C-Standard nur ein
ungetc()-Aufruf unterstützt. Aber eben nicht zwanzig Aufrufe
hintereinander. Also reicht eine interne Variable.
Welchen Sinn macht es dem User zu urlauben alles Mögliche auf den Stream
zu legen? Er soll nur das drauf legen können, was auch vorher ausgelesen
wurde.
immer noch komisch schrieb:> Warum kann ich etwas zurückschieben,> was in diesem read-only-File gar nicht da war.
Weil es nützlich ist. Stark vereinfachtes Beispiel: Ein Parser für
Rechenausdrücke. Du liest "5+3" und schiebst 8 zurück in den Puffer.
Dieses Verfahren wird wiederholt angewendet, bis der ganze Puffer
ausgewertet ist.
immer noch komisch schrieb:> Wäre es nicht besser so ein Puffer auch als read-only zu definieren? Und> die gelesene Variable intern zu speichern?
Wenn es nur darum geht, ein paar Zeichen "in die Zukunft zu sehen",
könnte man das so machen, aber warum sollte man das auf diese Art fest
verdrahten? Wenn du die Gewissheit brauchst, dass im Puffer jederzeit
nur das enthalten ist, was auch in der Datei enthalten war, benutzt du
diese Funktion einfach nicht oder nur in der von dir beschriebenen Art -
Problem gelöst.
Du hast einfach nicht verstanden, wozu ungetc da ist. Mit Schreiben in
eine Datei hat es gar nichts zu tun, es geht um look-ahead.
Probier doch einfach mal, eine Routine zu schreiben, die ein Zahl (nicht
eine einzelne Ziffer) einliest (wie es z.B. scanf-%d macht). Du merkst
dann ganz schnell, dass du sowas wie ungetc brauchst.
foobar schrieb:> Du hast einfach nicht verstanden, wozu ungetc da ist. Mit Schreiben in> eine Datei hat es gar nichts zu tun, es geht um look-ahead.>> Probier doch einfach mal, eine Routine zu schreiben, die ein Zahl (nicht> eine einzelne Ziffer) einliest (wie es z.B. scanf-%d macht). Du merkst> dann ganz schnell, dass du sowas wie ungetc brauchst.
Ich programmiere jetzt 30 Jahre in C/C++. Aber das ungetc() habe ich
noch nie gebraucht, und in anderen Sourcecodes auch nie gesehen.
Das lässt sich meist eleganter lösen.
PittyJ schrieb:> Ich programmiere jetzt 30 Jahre in C/C++. Aber das ungetc() habe ich> noch nie gebraucht, und in anderen Sourcecodes auch nie gesehen.> Das lässt sich meist eleganter lösen.
Und wie? Du kannst natürlich fseek verwenden... aber die Performance
ist dann im Eimer.
Ja, man kann ungetc() immer vermeiden. Kommt auf die Architektur des
Parsers an.
Aber ungetc() kann durchaus nützlich sein, nämlich dann, wenn eine
Subroutine im Parser "zu weit" liest und dann feststellt: "Upps, das
Zeichen geht mich nichts mehr an, also schiebe ich das zurück. Meine
Unteraufgabe ist damit erledigt!"
Wenn dabei direkt noch eine Ersetzung erfolgen soll, wie zum Beispiel
das Standardisieren von Whitespaces (TAB <-> SPACE), um es dem Parser
einfacher zu machen, dann kann auch das Zurückschieben eines anderen
Zeichens nützlich sein.
Fazit:
ungetc() ist nicht jedermans Freund - auch nicht meiner. Aber ihm
deshalb eine Nützlichkeit generell abzusprechen, wäre falsch.
PittyJ schrieb:> Ich programmiere jetzt 30 Jahre in C/C++. Aber das ungetc() habe ich> noch nie gebraucht, und in anderen Sourcecodes auch nie gesehen.> Das lässt sich meist eleganter lösen.
Ja. Ich gehe mal davon aus, dass du mehrfach einen eigenen Puffer
implementiert hast, natürlich einen besonders eleganten, statt einfach
ungetc() zu nehmen.
Jeder wie er mag. Aber weißt du was? Ich fühle mich nicht schlecht wenn
ich ungetc() verwende. Spart etwas Arbeit.