sheel
I love Asm
Waaa...ich hab diesen Thread komplett vergessen, tschuldigung :-(.
Kommt in Kürze...
Kennst du dich Dateien aus? fopen, fclose?
Wenn nicht, ist auch egal.
Jedenfalls kann man mit fopen eine Datei öffnen und bekommt eine FILE-Variable.
(fclose "schließt" diese Variable/Datei wieder).
Wenn man so eine FILE-Variable hat, kann man mit fgets aus der dazugehörenden Datei eine Zeile einlesen.
fgets kann aber nicht wie scanf mit %i, %d, %f etc umgehen, sondern liest die gesamte Zeile einfach Buchstabenweise ein.
(deswegen später das sscanf, um die Ziffern zu einer kompletten Zahl im int zu machen)
Wenn also fgets aus einer Datei etwas einliest, warum steht das dann da? Welche Datei?
Der Witz daran ist: In der Konsole werden die Tastatur und die Bildschirmausgabe auch als FILE-Variablen behandelt.
Die muss man nicht mit fopen/fclose öffnen oder schließen, die gibts einfach immer.
stdin (STanDard INput) ist dabei die Tastatur.
Das Gegenteil stdout gibt beim reinschreiben Buchstaben in die Konsole aus.
fgets will als ersten Parameter ein char-Array, zum Speichern der eingelesenen Zeile. Mein 24 Buchstaben langes str.
Der zweite Parameter ist die Maximallänge, die da reingespeichert werden darf. 24.
Wenn die Zeile länger als 24 Buchstaben ist, werden die restlichen ignoriert.
Der dritte Parameter ist die Datei bzw. FILE-Variable, aus der gelesen werden soll. stdin, damit die Eingabe von der Tastatur kommt.
Eine Eigenheit von fgets muss man noch erwähnen: Die Entertaste / der Zeilenwechsel am Schluss der Zeile wird beim Einlesen mit abgespeichert.
Und genau wie printf, bei dem man mit \n einen Zeilenwechsel machen kann, kann ich diesen auch als \n behandeln.
Wenn die Zeile jetzt aber länger als 24 war, bekomme ich nur die ersten 24 Zeichen in str.
Der Zeilenwechsel vom Ende der Zeile ist dann nicht mit in str dabei.
Ein weiteres "Problem": Wenn die Zeile länger als 24 war und ich nach diesem fgets wieder was von der Tastatur einlesen will, wird beim 25. Zeichen weitergemacht und nicht auf neue Tastendrucke gewartet. Der eventuell vorhandene abgeschnittene Zeilenrest muss also entfernt werden.
Das ist auch genau das Problem, das du mit dem normalen scanf am Anfang gehabt hast.
Es lässt einfach einen Teil der Eingabe "hinten"; das getchar danach hat sich dann dort bedient, statt auf eine neue Benutzereingabe zu warten.
Wegen diesem Problem ist diese ganze Funktion erst nötig geworden.
Ich lasse fgets einlesen, entferne mit den drei noch nicht erklärten Zeilen alles Übriggebliebene und lasse sscanf aus meiner Buchstaben/Ziffern-Sammlung von fgets ein int rauslesen.
So, wie wird jetzt etwas Übriggebliebenes entfernt?
erg=strlen(str)-1;
Zuerst finde ich heraus, wieviel Buchstaben/Ziffern eingegeben wurden.
strlen(str) macht das automatisch.
Aber wie das in C/C++ so ist: Wenn 4 Buchstaben im str sind, sind sie in str[0], str[1], str[2] und str[3].
Bei strlen=4 ist der letzte Buchstabe also auf 3.
strlen(...)-1 also. Diese Nummer brauche ich,
Ich speichere das in erg, damit ich kein zweites int brauche. Die eingelesene Zahl (die mit return erg zurückgegeben wird) wird dadurch nicht geändert, weil das sscanf, das erg mit der richtigen Zahl füllt, ja erst danach kommt.
if(erg>=0&&str[erg]=='\n')str[erg]='\0';
Wenn überhaupt irgendwas eingegeben wurde (erg>=0 -> strlen-1 >=0 ->Min. 1 Buchstabe eingegeben) und der letzte "Buchstabe" der Zeilenwechsel von fgets ist: Das bedeutet, der Benutzer hat nicht mehr wie 24 Buchstaben eingegeben.
Der Zeilenwechsel ist noch in str, dh die komplette Zeile und nichts wurde von fgets abgeschnitten.
Dann markiere ich den jetztigen letzen Buchstaben als Stringende (und entferne somit den Zeilenwechsel, den braucht keiner).
Dann ist alles in Ordnung.
else{while(fgetc(stdin) != '\n');}
Wenn der letzte Buchstabe aber kein Zeilenwechsel war, ist noch irgendwo ein abgeschnittener Rest der Zeile, der das nächste scanf/getchar/was auch immer stören würde.
fgetc liest aus der angegeben Datei genau einen Buchstaben ein, nichts weiter.
Nicht ganz so wie getchar() bei der Tastatur, das liest einen Buchstaben und wartet danach aber noch auf ein Enter.
fgetc liest wirklich nur einen Buchstaben.
Und wenn man es mit stdin als FILE verwendet, genau einen Tastendruck von der Tastatur.
Wenn also noch ein Zeilenrest vorhanden ist, liest die whle-Schleife solange Einzelbuchstaben ein, bis ein Zeilenwechsel dabei ist.
Sonst tut die Schleife nichts mehr, deshalb der Strichpunkt statt {...} dahinter.
fgetc liest jetzt trotz stdin nicht wirklich Tasten ein, sondern hat das gleiche "Problem" wie alles andere: Es bedient sich bei dem übriggebliebenen Zeilenrest.
(In dem Fall ist das sogar gut, genau das soll es ja auch machen).
Es liest jetzt jeden übriggebliebenen Buchstaben ein, bis der Zeilenwechsel kommt. Wenn der auch noch weg ist, kann es aufhören, da die Zeile jetzt aus ist.
Damit wären alle Spuren des fgets beseitigt, alles perfekt. Den Rest der Geschichte kennst du.
...Wieder einmal ein Roman, den ich hier geschrieben habe. Lässt du mir eine Bewertung da?
Gruß
Kommt in Kürze...
Kennst du dich Dateien aus? fopen, fclose?
Wenn nicht, ist auch egal.
Jedenfalls kann man mit fopen eine Datei öffnen und bekommt eine FILE-Variable.
(fclose "schließt" diese Variable/Datei wieder).
Wenn man so eine FILE-Variable hat, kann man mit fgets aus der dazugehörenden Datei eine Zeile einlesen.
fgets kann aber nicht wie scanf mit %i, %d, %f etc umgehen, sondern liest die gesamte Zeile einfach Buchstabenweise ein.
(deswegen später das sscanf, um die Ziffern zu einer kompletten Zahl im int zu machen)
Wenn also fgets aus einer Datei etwas einliest, warum steht das dann da? Welche Datei?
Der Witz daran ist: In der Konsole werden die Tastatur und die Bildschirmausgabe auch als FILE-Variablen behandelt.
Die muss man nicht mit fopen/fclose öffnen oder schließen, die gibts einfach immer.
stdin (STanDard INput) ist dabei die Tastatur.
Das Gegenteil stdout gibt beim reinschreiben Buchstaben in die Konsole aus.
fgets will als ersten Parameter ein char-Array, zum Speichern der eingelesenen Zeile. Mein 24 Buchstaben langes str.
Der zweite Parameter ist die Maximallänge, die da reingespeichert werden darf. 24.
Wenn die Zeile länger als 24 Buchstaben ist, werden die restlichen ignoriert.
Der dritte Parameter ist die Datei bzw. FILE-Variable, aus der gelesen werden soll. stdin, damit die Eingabe von der Tastatur kommt.
Eine Eigenheit von fgets muss man noch erwähnen: Die Entertaste / der Zeilenwechsel am Schluss der Zeile wird beim Einlesen mit abgespeichert.
Und genau wie printf, bei dem man mit \n einen Zeilenwechsel machen kann, kann ich diesen auch als \n behandeln.
Wenn die Zeile jetzt aber länger als 24 war, bekomme ich nur die ersten 24 Zeichen in str.
Der Zeilenwechsel vom Ende der Zeile ist dann nicht mit in str dabei.
Ein weiteres "Problem": Wenn die Zeile länger als 24 war und ich nach diesem fgets wieder was von der Tastatur einlesen will, wird beim 25. Zeichen weitergemacht und nicht auf neue Tastendrucke gewartet. Der eventuell vorhandene abgeschnittene Zeilenrest muss also entfernt werden.
Das ist auch genau das Problem, das du mit dem normalen scanf am Anfang gehabt hast.
Es lässt einfach einen Teil der Eingabe "hinten"; das getchar danach hat sich dann dort bedient, statt auf eine neue Benutzereingabe zu warten.
Wegen diesem Problem ist diese ganze Funktion erst nötig geworden.
Ich lasse fgets einlesen, entferne mit den drei noch nicht erklärten Zeilen alles Übriggebliebene und lasse sscanf aus meiner Buchstaben/Ziffern-Sammlung von fgets ein int rauslesen.
So, wie wird jetzt etwas Übriggebliebenes entfernt?
erg=strlen(str)-1;
Zuerst finde ich heraus, wieviel Buchstaben/Ziffern eingegeben wurden.
strlen(str) macht das automatisch.
Aber wie das in C/C++ so ist: Wenn 4 Buchstaben im str sind, sind sie in str[0], str[1], str[2] und str[3].
Bei strlen=4 ist der letzte Buchstabe also auf 3.
strlen(...)-1 also. Diese Nummer brauche ich,
Ich speichere das in erg, damit ich kein zweites int brauche. Die eingelesene Zahl (die mit return erg zurückgegeben wird) wird dadurch nicht geändert, weil das sscanf, das erg mit der richtigen Zahl füllt, ja erst danach kommt.
if(erg>=0&&str[erg]=='\n')str[erg]='\0';
Wenn überhaupt irgendwas eingegeben wurde (erg>=0 -> strlen-1 >=0 ->Min. 1 Buchstabe eingegeben) und der letzte "Buchstabe" der Zeilenwechsel von fgets ist: Das bedeutet, der Benutzer hat nicht mehr wie 24 Buchstaben eingegeben.
Der Zeilenwechsel ist noch in str, dh die komplette Zeile und nichts wurde von fgets abgeschnitten.
Dann markiere ich den jetztigen letzen Buchstaben als Stringende (und entferne somit den Zeilenwechsel, den braucht keiner).
Dann ist alles in Ordnung.
else{while(fgetc(stdin) != '\n');}
Wenn der letzte Buchstabe aber kein Zeilenwechsel war, ist noch irgendwo ein abgeschnittener Rest der Zeile, der das nächste scanf/getchar/was auch immer stören würde.
fgetc liest aus der angegeben Datei genau einen Buchstaben ein, nichts weiter.
Nicht ganz so wie getchar() bei der Tastatur, das liest einen Buchstaben und wartet danach aber noch auf ein Enter.
fgetc liest wirklich nur einen Buchstaben.
Und wenn man es mit stdin als FILE verwendet, genau einen Tastendruck von der Tastatur.
Wenn also noch ein Zeilenrest vorhanden ist, liest die whle-Schleife solange Einzelbuchstaben ein, bis ein Zeilenwechsel dabei ist.
Sonst tut die Schleife nichts mehr, deshalb der Strichpunkt statt {...} dahinter.
fgetc liest jetzt trotz stdin nicht wirklich Tasten ein, sondern hat das gleiche "Problem" wie alles andere: Es bedient sich bei dem übriggebliebenen Zeilenrest.
(In dem Fall ist das sogar gut, genau das soll es ja auch machen).
Es liest jetzt jeden übriggebliebenen Buchstaben ein, bis der Zeilenwechsel kommt. Wenn der auch noch weg ist, kann es aufhören, da die Zeile jetzt aus ist.
Damit wären alle Spuren des fgets beseitigt, alles perfekt. Den Rest der Geschichte kennst du.
...Wieder einmal ein Roman, den ich hier geschrieben habe. Lässt du mir eine Bewertung da?
Gruß
Zuletzt bearbeitet: