Fragen zur Ein- und Ausgabe von Dateien



  • Die erste Frage bezieht sich auf diesen Quelltext:

    #include <stdio.h>
    
    int main()
    {
    	int c = getchar();
    	while(c != EOF)
    	{
    		putchar(c);
    		c = getchar();
    		printf("\n");
    	}
    }
    

    Was mich wundert: Wenn der Befehl getchar erstmalig aufgerufen wird, wird die Tastatur abgefragt. Wenn dieser Befehl allerdings in diesem Programm nach dem ersten Aufruf nochmal aufgerufen wird, wird die Tastatur nicht erneut abgefragt.
    Abgesehen davon: Es wird ja augenscheinlich der Stream eingelesen, der von der Tastatur entgegengenommen wurde. Wo ist dieser Stream konkret gespeichert?

    In meinem Lernbuch "The C Programming Language" findet sich außerdem folgende Erklärung, warum "int" statt "char" hier gentzt werden sollte:

    "The problem is distinguishing the end of input from valid data. The solution is that getchar returns a distinctive
    value when there is no more input, a value that cannot be confused with any real character. This value is called
    EOF, for ``end of file''. We must declare c to be a type big enough to hold any value that getchar returns. We
    can't use char since c must be big enough to hold EOF in addition to any possible char. Therefore we use int."

    Ich verstehe das nicht. So dumm das klingt. Kann mir das einer vielleicht nochmal genauer erklären? Ich muß dazusagen, daß ich nicht über tiefgehendes Wissen über Zeichensätze usw. verfüge. Mangelnde Sprachkentnisse sind nicht das Problem.

    Ich dnake für alle liebevollen Antworten!


  • Mod

    Dexter1997 schrieb:

    Was mich wundert: Wenn der Befehl getchar erstmalig aufgerufen wird, wird die Tastatur abgefragt. Wenn dieser Befehl allerdings in diesem Programm nach dem ersten Aufruf nochmal aufgerufen wird, wird die Tastatur nicht erneut abgefragt.

    Wie kommst du darauf? getchar liest ein Zeichen aus der Standardeingabe (welches die Tastatur sein kann, aber nicht muss). Wenn dort keine Zeichen sind, dann wird blockiert, bis Zeichen kommen. Falls die Standardeingabe die Tastatur ist, wird also auf eine Tastatureingabe gewartet. Werden mehr als ein Zeichen eingegeben, dann stehen naürlich auch mehrere Zeichenn für wiederholte getchar-Aufrufe zur Verügung, die entsprechend nicht blockieren werden.

    Abgesehen davon: Es wird ja augenscheinlich der Stream eingelesen, der von der Tastatur entgegengenommen wurde. Wo ist dieser Stream konkret gespeichert?

    Die Standardeingabe ist über den global definierten Stream stdin erreichbar, deklariert unter anderem in stdio.h .

    In meinem Lernbuch "The C Programming Language" findet sich außerdem folgende Erklärung, warum "int" statt "char" hier gentzt werden sollte:

    "The problem is distinguishing the end of input from valid data. The solution is that getchar returns a distinctive
    value when there is no more input, a value that cannot be confused with any real character. This value is called
    EOF, for ``end of file''. We must declare c to be a type big enough to hold any value that getchar returns. We
    can't use char since c must be big enough to hold EOF in addition to any possible char. Therefore we use int."

    Ich verstehe das nicht. So dumm das klingt. Kann mir das einer vielleicht nochmal genauer erklären? Ich muß dazusagen, daß ich nicht über tiefgehendes Wissen über Zeichensätze usw. verfüge. Mangelnde Sprachkentnisse sind nicht das Problem.

    Das kommt davon, wenn man Rückgabewert und Signalisierung in einem macht. getchar signalisiert Fehler dadurch, dass der Rückgabewert einen Sonderwert annimmt. getchar soll aber auch in der Lage sein, alle möglichen Zeichen (also alle möglichen Werte eines char) zu lesen und zurück zu geben. Die Sonderwerte für den Fehlerfall dürfen also keine Werte sein, die ein char annehmen kann, denn sonst wüsste man ja nicht, ob ein Fehler auftrat, oder ob dies eine normale Rückgabe ist¹. Wenn du nun aber den Rückgabewert in einem char speichern würdest, dann werden die Sonderwerte zwangsläufig irgenwie so verbogen, dass sie in einen char passen. Danach kannst du also nicht mehr sauber unterscheiden, ob ein Fehler auftrat oder nicht.

    ¹: Ein ganz schlechtes Vorbild ist die Funktion atoi aus stdlib.h, welche Zeichenketten in Zahlen umwandelt. Sie signalisiert Fehler durch eine Rückgabe des Wertes 0. Aber woher weiß man nun, ob es einen Fehler gab, oder ob eine 0 in der Zeichenkette stand?



  • Dexter1997 schrieb:

    Was mich wundert: Wenn der Befehl getchar erstmalig aufgerufen wird, wird die Tastatur abgefragt. Wenn dieser Befehl allerdings in diesem Programm nach dem ersten Aufruf nochmal aufgerufen wird, wird die Tastatur nicht erneut abgefragt.

    Wie kommst du darauf?

    Dexter1997 schrieb:

    Wo ist dieser Stream konkret gespeichert?

    Nirgends oder in einer Datei oder in einer Pipe oder ...

    getchar liest von stdin (STandarD INput) und das kann mit verschiedenen Streams verknüpft sein.
    Wo und wie, das interrsiert C nicht.



  • Dexter1997 schrieb:

    Was mich wundert: Wenn der Befehl getchar erstmalig aufgerufen wird, wird die Tastatur abgefragt. Wenn dieser Befehl allerdings in diesem Programm nach dem ersten Aufruf nochmal aufgerufen wird, wird die Tastatur nicht erneut abgefragt.

    Was soll das heißen?

    Dexter1997 schrieb:

    Abgesehen davon: Es wird ja augenscheinlich der Stream eingelesen, der von der Tastatur entgegengenommen wurde.

    Vor allem in Hinblick auf diese Aussage. Wenn du damit meinst, dass getchar Zeichen einliest, die du nicht eingegeben hast ... doch, hast du. Zeilenumbruch und so. Auch das ist ein Zeichen.

    Dexter1997 schrieb:

    Wo ist dieser Stream konkret gespeichert?

    Hängt von der Plattform ab. ANSI C macht deswegen keine Angaben, wie das Ding konkret gespeichert wird. Da musst du dann in die Dokumentation oder die Header oder den Quellcode schauen.

    Dexter1997 schrieb:

    Ich verstehe das nicht. So dumm das klingt. Kann mir das einer vielleicht nochmal genauer erklären? Ich muß dazusagen, daß ich nicht über tiefgehendes Wissen über Zeichensätze usw. verfüge. Mangelnde Sprachkentnisse sind nicht das Problem.

    C definiert eine Konstante, EOF . Die kann größer sein als das, was char so anbietet. Weil sie gesagt haben, dass EOF in einen int passen muss.

    Jetzt kann getchar auch EOF zurückgeben. Deswegen gibt es einen int zurück. Und wenn du versuchst, einen int in einen char zu packen, hast du eventuell Informationsverlust. Weil EOF 0x12345678 sein kann, und in deinem char wird dann nur 0x78 gespeichert. Und wenn du dann 0x12345678 == 0x78 prüfst, läuft der Check durch, und du hast keine Ahnung, dass du EOF erreicht hast.

    Dexter1997 schrieb:

    Ich dnake für alle liebevollen Antworten!

    Ich hätte ja lieber informative denn liebevolle Antworten, aber sei's drum ...



  • Wie kommst du darauf?

    Das Programm hat sich während der Ausführung genau so verhalten wie beschrieben, weswegen ich entsprechend diese Schlüsse gezogen habe.

    Ich hätte ja lieber informative denn liebevolle Antworten, aber sei's drum ...

    Ich bin ein gefühlvoller Mensch ❤

    Ich danke für Antworten, damit wäre alles soweit geklärt!



  • Dexter1997 schrieb:

    Ich danke für Antworten, damit wäre alles soweit geklärt!

    Das glaubt dir mit Sicherheit niemand 😉


Log in to reply