Was ist der einfachste Weg, eine vollständige Zeile in einem C-Konsolenprogramm zu lesen? Der eingegebene Text hat möglicherweise eine variable Länge und wir können keine Annahme über den Inhalt treffen.
Könnten Sie bitte klarstellen? Wie @ Tim unten sagte, ist es verwirrend, wonach Sie fragen :)
Warren
Antworten:
81
Sie benötigen eine dynamische Speicherverwaltung und verwenden die fgetsFunktion zum Lesen Ihrer Zeile. Es scheint jedoch keine Möglichkeit zu geben, zu sehen, wie viele Zeichen es liest. Sie verwenden also fgetc:
char* getline(void){char* line = malloc(100),* linep = line;size_t lenmax =100, len = lenmax;int c;if(line == NULL)return NULL;for(;;){
c = fgetc(stdin);if(c == EOF)break;if(--len ==0){
len = lenmax;char* linen = realloc(linep, lenmax *=2);if(linen == NULL){
free(linep);return NULL;}
line = linen +(line - linep);
linep = linen;}if((*line++= c)=='\n')break;}*line ='\0';return linep;}
Hinweis : Niemals verwenden bekommt! Es überprüft keine Grenzen und kann Ihren Puffer überlaufen lassen
Vorsichtsmaßnahme - muss das Ergebnis der Neuzuweisung dort überprüfen. Wenn dies jedoch fehlschlägt, gibt es höchstwahrscheinlich schlimmere Probleme.
Tim
4
Sie könnten die Effizienz wahrscheinlich ein wenig verbessern, indem Sie Fgets mit Puffer ausführen und prüfen, ob Sie am Ende das Zeilenumbruchzeichen haben. Wenn Sie dies nicht tun, ordnen Sie Ihren Akkumulationspuffer neu zu, kopieren Sie ihn und fgets erneut.
Paul Tomblin
3
Diese Funktion muss korrigiert werden: die Zeile "len = lenmax;" nach dem Realloc sollte entweder vor dem Realloc stehen oder "len = lenmax >> 1;" - oder ein anderes Äquivalent, das die Tatsache berücksichtigt, dass bereits die Hälfte der Länge verwendet wird.
Matt Gallagher
1
@Johannes, als Antwort auf Ihre Frage, @ Pauls Ansatz KÖNNTE bei den meisten (dh wiedereintretenden) libc-Implementierungen schneller sein, da Ihr Ansatz implizit stdin für jedes Zeichen sperrt, während er es einmal pro Puffer sperrt. Sie können das weniger tragbare Gerät verwenden, fgetc_unlockedwenn die Thread-Sicherheit kein Problem darstellt, die Leistung jedoch.
Vladr
3
Beachten Sie, dass sich dies getline()von der POSIX-Standardfunktion unterscheidet getline().
Jonathan Leffler
28
Wenn Sie die GNU C-Bibliothek oder eine andere POSIX-kompatible Bibliothek verwenden, können Sie sie für den Dateistream verwenden getline()und stdinan sie übergeben.
Eine sehr einfache, aber unsichere Implementierung zum Lesen der Zeile für die statische Zuordnung:
char line[1024];
scanf("%[^\n]", line);
Eine sicherere Implementierung ohne die Möglichkeit eines Pufferüberlaufs, aber mit der Möglichkeit, nicht die gesamte Zeile zu lesen, ist:
char line[1024];
scanf("%1023[^\n]", line);
Nicht die 'Differenz um eins' zwischen der angegebenen Länge, die die Variable deklariert, und der in der Formatzeichenfolge angegebenen Länge. Es ist ein historisches Artefakt.
Wenn Sie also nach Befehlsargumenten suchen, werfen Sie einen Blick auf Tims Antwort. Wenn Sie nur eine Zeile von der Konsole lesen möchten:
#include<stdio.h>int main(){char string [256];
printf ("Insert your full address: ");
gets (string);
printf ("Your address is: %s\n",string);return0;}
Ja, es ist nicht sicher, Sie können einen Pufferüberlauf durchführen, es wird nicht nach Dateiende gesucht, es werden keine Codierungen und viele andere Dinge unterstützt. Eigentlich habe ich nicht einmal darüber nachgedacht, ob es irgendetwas davon getan hat. Ich bin damit einverstanden, dass ich es irgendwie vermasselt habe :) Aber ... wenn ich eine Frage wie "Wie lese ich eine Zeile von der Konsole in C?" Sehe, gehe ich davon aus, dass eine Person etwas Einfaches braucht, wie get () und nicht 100 Codezeilen wie oben. Eigentlich denke ich, wenn Sie versuchen, diese 100 Codezeilen in der Realität zu schreiben, würden Sie viel mehr Fehler machen, als Sie getan hätten, wenn Sie sich dafür entschieden hätten;)
Dies erlaubt keine langen Saiten ... - was meiner Meinung nach der Kern seiner Frage ist.
Tim
2
-1, get () sollte nicht verwendet werden, da keine Grenzüberprüfung durchgeführt wird.
Entspannen Sie sich
7
Wenn Sie jedoch ein Programm für sich selbst schreiben und nur eine Eingabe lesen müssen, ist dies vollkommen in Ordnung. Wie viel Sicherheit ein Programm benötigt, hängt von der Spezifikation ab - Sie MÜSSEN es nicht jedes Mal als Priorität festlegen.
Martin Beckett
4
@ Tim - Ich möchte die ganze Geschichte behalten :)
Paul Kapustin
4
Abgestimmt. getsexistiert nicht mehr, daher funktioniert dies in C11 nicht.
Antti Haapala
11
Möglicherweise müssen Sie eine zeichenweise (getc ()) - Schleife verwenden, um sicherzustellen, dass keine Pufferüberläufe auftreten und die Eingabe nicht abgeschnitten wird.
Was ist der Zweck von lenhier, wenn das Lesen auch die Länge liefert
Abdul
@Abdul sehen man getline. lenist die Länge des vorhandenen Puffers, 0ist magisch und weist ihn an, zuzuweisen. Lesen ist die Anzahl der gelesenen Zeichen. Die Puffergröße könnte größer sein als read.
Ciro Santilli 31 冠状 病 六四 事件 31
6
Viele Leute, wie ich, kommen zu diesem Beitrag mit dem Titel, der dem entspricht, wonach gesucht wird, obwohl die Beschreibung über variable Länge sagt. In den meisten Fällen kennen wir die Länge im Voraus.
Wenn Sie die Länge vorher kennen, versuchen Sie es unten:
char str1[1001]={0};
fgets(str1,1001, stdin);// 1000 chars may be read
Wie vorgeschlagen, können Sie mit getchar () von der Konsole lesen, bis ein Zeilenende oder ein EOF zurückgegeben wird, und Ihren eigenen Puffer erstellen. Das dynamische Wachsen des Puffers kann auftreten, wenn Sie keine angemessene maximale Zeilengröße festlegen können.
Sie können auch fgets verwenden, um eine Zeile als C-nullterminierte Zeichenfolge auf sichere Weise abzurufen:
#include<stdio.h>char line[1024];/* Generously large value for most situations */char*eof;
line[0]='\0';/* Ensure empty line if no input delivered */
line[sizeof(line)-1]=~'\0';/* Ensure no false-null at end of buffer */
eof = fgets(line,sizeof(line), stdin);
Wenn Sie die Konsoleneingabe erschöpft haben oder der Vorgang aus irgendeinem Grund fehlgeschlagen ist, wird eof == NULL zurückgegeben und der Zeilenpuffer bleibt möglicherweise unverändert (weshalb es praktisch ist, das erste Zeichen auf '\ 0' zu setzen).
fgets überfüllt die Zeile [] nicht und stellt sicher, dass bei einer erfolgreichen Rückgabe nach dem zuletzt akzeptierten Zeichen eine Null steht.
Wenn das Zeilenende erreicht wurde, ist das Zeichen vor dem abschließenden '\ 0' ein '\ n'.
Wenn vor dem Ende von '\ 0' kein '\ n' beendet wird, kann es sein, dass mehr Daten vorhanden sind oder dass die nächste Anforderung das Dateiende meldet. Sie müssen weitere Fgets ausführen, um festzustellen, welches welches ist. (In dieser Hinsicht ist das Schleifen mit getchar () einfacher.)
Im obigen (aktualisierten) Beispielcode wissen Sie, dass der Puffer vollständig gefüllt wurde, wenn Zeile [sizeof (Zeile) -1] == '\ 0' nach erfolgreichen Fgets ist. Wenn diese Position von einem '\ n' besetzt wird, wissen Sie, dass Sie Glück hatten. Andernfalls liegen in stdin entweder mehr Daten oder ein Dateiende vor uns. (Wenn der Puffer nicht vollständig gefüllt ist, befindet sich möglicherweise immer noch ein Dateiende und am Ende der aktuellen Zeile befindet sich möglicherweise kein '\ n'. Da Sie die Zeichenfolge scannen müssen, um und / oder zu finden oder ein '\ n' vor dem Ende des Strings entfernen (das erste '\ 0' im Puffer), ich bin geneigt, getchar () überhaupt zu verwenden.)
Tun Sie, was Sie tun müssen, um damit umzugehen, dass immer noch mehr Zeilen als der Betrag vorhanden sind, den Sie als ersten Block gelesen haben. Die Beispiele für das dynamische Wachsen eines Puffers können entweder mit getchar oder fgets verwendet werden. Es gibt einige knifflige Randfälle, auf die Sie achten müssen (z. B. das Erinnern daran, dass der nächste Eingang an der Position '\ 0' gespeichert wird, die den vorherigen Eingang beendet hat, bevor der Puffer erweitert wurde).
Wenn wir den zugewiesenen Speicher erschöpfen wollen, versuchen wir, die Größe des Speichers zu verdoppeln
Und hier bin ich mit einer Schleife jedes Zeichen der Zeichenfolge ein scannen , indem man mit der getchar()Funktion , bis der Benutzer eingibt '\n'oder EOFZeichen
Schließlich entfernen wir den zusätzlich zugewiesenen Speicher, bevor wir die Zeile zurückgeben
//the function to read lines of variable lengthchar* scan_line(char*line){int ch;// as getchar() returns `int`long capacity =0;// capacity of the bufferlong length =0;// maintains the length of the stringchar*temp = NULL;// use additional pointer to perform allocations in order to avoid memory leakswhile(((ch = getchar())!='\n')&&(ch != EOF)){if((length +1)>= capacity){// resetting capacityif(capacity ==0)
capacity =2;// some initial fixed length else
capacity *=2;// double the size// try reallocating the memoryif((temp = realloc(line, capacity *sizeof(char)))== NULL )//allocating memory{
printf("ERROR: unsuccessful allocation");// return line; or you can exit
exit(1);}
line = temp;}
line[length]=(char) ch;//type casting `int` to `char`}
line[length +1]='\0';//inserting null character at the end// remove additionally allocated memoryif((temp = realloc(line,(length +1)*sizeof(char)))== NULL ){
printf("ERROR: unsuccessful allocation");// return line; or you can exit
exit(1);}
line = temp;return line;}
Jetzt können Sie eine vollständige Zeile folgendermaßen lesen:
char*line = NULL;
line = scan_line(line);
Hier ist ein Beispielprogramm mit der scan_line()Funktion:
#include<stdio.h>#include<stdlib.h>//for dynamic allocation functionschar* scan_line(char*line){..........}int main(void){char*a = NULL;
a = scan_line(a);//function call to scan the line
printf("%s\n",a);//printing the scanned line
free(a);//don't forget to free the malloc'd pointer}
Ich bin vor einiger Zeit auf dasselbe Problem gestoßen, dies war meine Lösung, ich hoffe, es hilft.
/*
* Initial size of the read buffer
*/#define DEFAULT_BUFFER 1024/*
* Standard boolean type definition
*/typedefenum{false=0,true=1}bool;/*
* Flags errors in pointer returning functions
*/bool has_err =false;/*
* Reads the next line of text from file and returns it.
* The line must be free()d afterwards.
*
* This function will segfault on binary data.
*/char*readLine(FILE*file){char*buffer = NULL;char*tmp_buf = NULL;bool line_read =false;int iteration =0;int offset =0;if(file == NULL){
fprintf(stderr,"readLine: NULL file pointer passed!\n");
has_err =true;return NULL;}while(!line_read){if((tmp_buf = malloc(DEFAULT_BUFFER))== NULL){
fprintf(stderr,"readLine: Unable to allocate temporary buffer!\n");if(buffer != NULL)
free(buffer);
has_err =true;return NULL;}if(fgets(tmp_buf, DEFAULT_BUFFER, file)== NULL){
free(tmp_buf);break;}if(tmp_buf[strlen(tmp_buf)-1]=='\n')/* we have an end of line */
line_read =true;
offset = DEFAULT_BUFFER *(iteration +1);if((buffer = realloc(buffer, offset))== NULL){
fprintf(stderr,"readLine: Unable to reallocate buffer!\n");
free(tmp_buf);
has_err =true;return NULL;}
offset = DEFAULT_BUFFER * iteration - iteration;if(memcpy(buffer + offset, tmp_buf, DEFAULT_BUFFER)== NULL){
fprintf(stderr,"readLine: Cannot copy to buffer\n");
free(tmp_buf);if(buffer != NULL)
free(buffer);
has_err =true;return NULL;}
free(tmp_buf);
iteration++;}return buffer;}
Ihr Code würde VIEL einfacher, wenn Sie gotoden Fehlerfall behandeln. Glauben Sie trotzdem nicht, dass Sie es wiederverwenden könnten tmp_buf, anstatt malloces immer wieder mit der gleichen Größe in der Schleife zu verwenden?
Shahbaz
Die Verwendung einer einzelnen globalen Variablen has_errzum Melden von Fehlern macht diese Funktion threadsicher und weniger benutzerfreundlich. Mach es nicht so. Sie geben bereits einen Fehler an, indem Sie NULL zurückgeben. Es gibt auch Raum zu der Annahme, dass die gedruckten Fehlermeldungen in einer universellen Bibliotheksfunktion keine gute Idee sind.
Jonathan Leffler
0
Auf BSD-Systemen und Android können Sie außerdem Folgendes verwenden fgetln:
Das lineist nicht nullterminiert und enthält \n(oder was auch immer Ihre Plattform verwendet) am Ende. Sie wird nach der nächsten E / A-Operation im Stream ungültig.
Ja, die Funktion ist vorhanden. Die Einschränkung, dass keine nullterminierte Zeichenfolge bereitgestellt wird, ist ausreichend groß und problematisch, sodass es wahrscheinlich besser ist, sie nicht zu verwenden - sie ist gefährlich.
Jonathan Leffler
0
Etwas wie das:
unsignedint getConsoleInput(char**pStrBfr)//pass in pointer to char pointer, returns size of buffer{char* strbfr;int c;unsignedint i;
i =0;
strbfr =(char*)malloc(sizeof(char));if(strbfr==NULL)goto error;while((c = getchar())!='\n'&& c != EOF ){
strbfr[i]=(char)c;
i++;
strbfr =(void*)realloc((void*)strbfr,sizeof(char)*(i+1));//on realloc error, NULL is returned but original buffer is unchanged//NOTE: the buffer WILL NOT be NULL terminated since last//chracter came from consoleif(strbfr==NULL)goto error;}
strbfr[i]='\0';*pStrBfr = strbfr;//successfully returns pointer to NULL terminated bufferreturn i +1;
error:*pStrBfr = strbfr;return i +1;}
Der beste und einfachste Weg, eine Zeile von einer Konsole zu lesen, ist die Funktion getchar (), mit der Sie jeweils ein Zeichen in einem Array speichern.
{char message[N];/* character array for the message, you can always change the character length */int i =0;/* loop counter */
printf("Enter a message: ");
message[i]= getchar();/* get the first character */while( message[i]!='\n'){
message[++i]= getchar();/* gets the next character */}
printf("Entered message is:");for( i =0; i < N; i++)
printf("%c", message[i]);return(0);
Antworten:
Sie benötigen eine dynamische Speicherverwaltung und verwenden die
fgets
Funktion zum Lesen Ihrer Zeile. Es scheint jedoch keine Möglichkeit zu geben, zu sehen, wie viele Zeichen es liest. Sie verwenden also fgetc:Hinweis : Niemals verwenden bekommt! Es überprüft keine Grenzen und kann Ihren Puffer überlaufen lassen
quelle
fgetc_unlocked
wenn die Thread-Sicherheit kein Problem darstellt, die Leistung jedoch.getline()
von der POSIX-Standardfunktion unterscheidetgetline()
.Wenn Sie die GNU C-Bibliothek oder eine andere POSIX-kompatible Bibliothek verwenden, können Sie sie für den Dateistream verwenden
getline()
undstdin
an sie übergeben.quelle
Eine sehr einfache, aber unsichere Implementierung zum Lesen der Zeile für die statische Zuordnung:
Eine sicherere Implementierung ohne die Möglichkeit eines Pufferüberlaufs, aber mit der Möglichkeit, nicht die gesamte Zeile zu lesen, ist:
Nicht die 'Differenz um eins' zwischen der angegebenen Länge, die die Variable deklariert, und der in der Formatzeichenfolge angegebenen Länge. Es ist ein historisches Artefakt.
quelle
gets
insgesamt aus dem Standard entfernt wurdeWenn Sie also nach Befehlsargumenten suchen, werfen Sie einen Blick auf Tims Antwort. Wenn Sie nur eine Zeile von der Konsole lesen möchten:
Ja, es ist nicht sicher, Sie können einen Pufferüberlauf durchführen, es wird nicht nach Dateiende gesucht, es werden keine Codierungen und viele andere Dinge unterstützt. Eigentlich habe ich nicht einmal darüber nachgedacht, ob es irgendetwas davon getan hat. Ich bin damit einverstanden, dass ich es irgendwie vermasselt habe :) Aber ... wenn ich eine Frage wie "Wie lese ich eine Zeile von der Konsole in C?" Sehe, gehe ich davon aus, dass eine Person etwas Einfaches braucht, wie get () und nicht 100 Codezeilen wie oben. Eigentlich denke ich, wenn Sie versuchen, diese 100 Codezeilen in der Realität zu schreiben, würden Sie viel mehr Fehler machen, als Sie getan hätten, wenn Sie sich dafür entschieden hätten;)
quelle
gets
existiert nicht mehr, daher funktioniert dies in C11 nicht.Möglicherweise müssen Sie eine zeichenweise (getc ()) - Schleife verwenden, um sicherzustellen, dass keine Pufferüberläufe auftreten und die Eingabe nicht abgeschnitten wird.
quelle
getline
lauffähiges BeispielErwähnt zu dieser Antwort, aber hier ist ein Beispiel.
Es ist POSIX 7, weist uns Speicher zu und verwendet den zugewiesenen Puffer in einer Schleife gut wieder.
Zeiger newbs, lesen Sie Folgendes: Warum ist das erste Argument von getline ein Zeiger auf den Zeiger "char **" anstelle von "char *"?
glibc Implementierung
Kein POSIX? Vielleicht möchten Sie sich die Implementierung von glibc 2.23 ansehen .
Es wird aufgelöst in
getdelim
, was eine einfache POSIX-Obermenge vongetline
mit einem beliebigen Zeilenabschluss ist.Es verdoppelt den zugewiesenen Speicher, wenn eine Erhöhung erforderlich ist, und sieht threadsicher aus.
Es erfordert eine gewisse Makroerweiterung, aber es ist unwahrscheinlich, dass Sie es besser machen.
quelle
len
hier, wenn das Lesen auch die Länge liefertman getline
.len
ist die Länge des vorhandenen Puffers,0
ist magisch und weist ihn an, zuzuweisen. Lesen ist die Anzahl der gelesenen Zeichen. Die Puffergröße könnte größer sein alsread
.Viele Leute, wie ich, kommen zu diesem Beitrag mit dem Titel, der dem entspricht, wonach gesucht wird, obwohl die Beschreibung über variable Länge sagt. In den meisten Fällen kennen wir die Länge im Voraus.
Wenn Sie die Länge vorher kennen, versuchen Sie es unten:
Quelle: https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm
quelle
Wie vorgeschlagen, können Sie mit getchar () von der Konsole lesen, bis ein Zeilenende oder ein EOF zurückgegeben wird, und Ihren eigenen Puffer erstellen. Das dynamische Wachsen des Puffers kann auftreten, wenn Sie keine angemessene maximale Zeilengröße festlegen können.
Sie können auch fgets verwenden, um eine Zeile als C-nullterminierte Zeichenfolge auf sichere Weise abzurufen:
Wenn Sie die Konsoleneingabe erschöpft haben oder der Vorgang aus irgendeinem Grund fehlgeschlagen ist, wird eof == NULL zurückgegeben und der Zeilenpuffer bleibt möglicherweise unverändert (weshalb es praktisch ist, das erste Zeichen auf '\ 0' zu setzen).
fgets überfüllt die Zeile [] nicht und stellt sicher, dass bei einer erfolgreichen Rückgabe nach dem zuletzt akzeptierten Zeichen eine Null steht.
Wenn das Zeilenende erreicht wurde, ist das Zeichen vor dem abschließenden '\ 0' ein '\ n'.
Wenn vor dem Ende von '\ 0' kein '\ n' beendet wird, kann es sein, dass mehr Daten vorhanden sind oder dass die nächste Anforderung das Dateiende meldet. Sie müssen weitere Fgets ausführen, um festzustellen, welches welches ist. (In dieser Hinsicht ist das Schleifen mit getchar () einfacher.)
Im obigen (aktualisierten) Beispielcode wissen Sie, dass der Puffer vollständig gefüllt wurde, wenn Zeile [sizeof (Zeile) -1] == '\ 0' nach erfolgreichen Fgets ist. Wenn diese Position von einem '\ n' besetzt wird, wissen Sie, dass Sie Glück hatten. Andernfalls liegen in stdin entweder mehr Daten oder ein Dateiende vor uns. (Wenn der Puffer nicht vollständig gefüllt ist, befindet sich möglicherweise immer noch ein Dateiende und am Ende der aktuellen Zeile befindet sich möglicherweise kein '\ n'. Da Sie die Zeichenfolge scannen müssen, um und / oder zu finden oder ein '\ n' vor dem Ende des Strings entfernen (das erste '\ 0' im Puffer), ich bin geneigt, getchar () überhaupt zu verwenden.)
Tun Sie, was Sie tun müssen, um damit umzugehen, dass immer noch mehr Zeilen als der Betrag vorhanden sind, den Sie als ersten Block gelesen haben. Die Beispiele für das dynamische Wachsen eines Puffers können entweder mit getchar oder fgets verwendet werden. Es gibt einige knifflige Randfälle, auf die Sie achten müssen (z. B. das Erinnern daran, dass der nächste Eingang an der Position '\ 0' gespeichert wird, die den vorherigen Eingang beendet hat, bevor der Puffer erweitert wurde).
quelle
Das Erstellen einer eigenen Funktion ist eine der Möglichkeiten, mit denen Sie eine Zeile von der Konsole aus lesen können
Ich verwende die dynamische Speicherzuweisung , um die erforderliche Speichermenge zuzuweisen
Wenn wir den zugewiesenen Speicher erschöpfen wollen, versuchen wir, die Größe des Speichers zu verdoppeln
Und hier bin ich mit einer Schleife jedes Zeichen der Zeichenfolge ein scannen , indem man mit der
getchar()
Funktion , bis der Benutzer eingibt'\n'
oderEOF
ZeichenSchließlich entfernen wir den zusätzlich zugewiesenen Speicher, bevor wir die Zeile zurückgeben
Jetzt können Sie eine vollständige Zeile folgendermaßen lesen:
Hier ist ein Beispielprogramm mit der
scan_line()
Funktion:Beispieleingabe:
Beispielausgabe:
quelle
Ich bin vor einiger Zeit auf dasselbe Problem gestoßen, dies war meine Lösung, ich hoffe, es hilft.
quelle
goto
den Fehlerfall behandeln. Glauben Sie trotzdem nicht, dass Sie es wiederverwenden könntentmp_buf
, anstattmalloc
es immer wieder mit der gleichen Größe in der Schleife zu verwenden?has_err
zum Melden von Fehlern macht diese Funktion threadsicher und weniger benutzerfreundlich. Mach es nicht so. Sie geben bereits einen Fehler an, indem Sie NULL zurückgeben. Es gibt auch Raum zu der Annahme, dass die gedruckten Fehlermeldungen in einer universellen Bibliotheksfunktion keine gute Idee sind.Auf BSD-Systemen und Android können Sie außerdem Folgendes verwenden
fgetln
:Wie so:
Das
line
ist nicht nullterminiert und enthält\n
(oder was auch immer Ihre Plattform verwendet) am Ende. Sie wird nach der nächsten E / A-Operation im Stream ungültig.quelle
Etwas wie das:
quelle
Der beste und einfachste Weg, eine Zeile von einer Konsole zu lesen, ist die Funktion getchar (), mit der Sie jeweils ein Zeichen in einem Array speichern.
}}
quelle
Diese Funktion sollte tun, was Sie wollen:
Ich hoffe das hilft.
quelle
fgets( buffer, sizeof(buffer), file );
nichtsizeof(buffer)-1
.fgets
lässt Platz für die abschließende Null.while (!feof(file))
immer falsch ist und dies nur ein weiteres Beispiel für eine fehlerhafte Verwendung ist.