Verwenden fgets Anstatt von fgetc. Sie lesen Zeichen für Zeichen statt Zeile für Zeile.
– Scheib
17. März 2017 um 4:00 Uhr
Beachten Sie, dass getline() ist ein Teil von POSIX 2008. Es kann POSIX-ähnliche Plattformen ohne sie geben, insbesondere wenn sie den Rest von POSIX 2008 nicht unterstützen, aber innerhalb der Welt der POSIX-Systeme, getline() ist heutzutage ziemlich tragbar.
– Jonathan Leffler
8. Mai 2017 um 21:20 Uhr
Linie[count+1] ist eine automatische Stapelvariable und Sie verwenden einen Zeiger darauf als Rückgabewert. Das ist U.B.
– ulix
13. September um 3:48
mbaitoff
Wenn Ihre Aufgabe nicht darin besteht, die zeilenweise Lesefunktion zu erfinden, sondern nur die Datei zeilenweise zu lesen, können Sie ein typisches Code-Snippet mit verwenden getline() Funktion (siehe Handbuchseite hier):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/etc/motd", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu:\n", read);
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
exit(EXIT_SUCCESS);
}
Genauer gesagt diese getline ist spezifisch für GNU libc, dh für Linux. Wenn jedoch die Absicht besteht, eine Zeilenlesefunktion zu haben (im Gegensatz zum Erlernen von C), gibt es mehrere gemeinfreie Zeilenlesefunktionen, die im Internet verfügbar sind.
– Gilles ‘SO- hör auf, böse zu sein’
17. August 2010 um 11:55 Uhr
Warum sollte ich das tun? Lesen Sie das Handbuch, Puffer wird bei jedem Aufruf neu zugewiesen, dann sollte er am Ende freigegeben werden.
– mbaitoff
30. November 2012 um 12:43 Uhr
Das if(line) Prüfung ist überflüssig. Berufung free(NULL) ist im Wesentlichen ein No-Op.
– aroth
28. Januar 2014 um 7:25 Uhr
@PhilipAdler Wenn du dich wirklich streiten willst free(NULL) nicht spezifiziert ist (obwohl ich mir ziemlich sicher bin, dass es nirgendwo so geschrieben steht), dann sollten Sie das sogar wissen ls Anrufe free(NULL). Nach Überprüfung sagt die Manpage das free(ptr); free(ptr); ist undefiniert, und das free(NULL) tut nichts. @mbaitoff Warum machst du dir dann die Mühe zu befreien line dann ? Dennoch dreht sich auf dieser Website alles um das Unterrichten oder Helfen bei der Beste Lösung möglich, und das Freigeben von jedem zugewiesenen Speicher, der nicht mehr verwendet wird, ist eigentlich die gute Praxis.
– Jerska
13. Juni 2014 um 18:59 Uhr
Für diejenigen, die sagten, dass diese getline spezifisch für GNU libc ist: „Sowohl getline() als auch getdelim() waren ursprünglich GNU-Erweiterungen. Sie wurden in POSIX.1-2008 standardisiert.“
– willkill07
21. April 2015 um 21:01 Uhr
rauben
FILE* filePointer;
int bufferLength = 255;
char buffer[bufferLength]; /* not ISO 90 compatible */
filePointer = fopen("file.txt", "r");
while(fgets(buffer, bufferLength, filePointer)) {
printf("%s\n", buffer);
}
fclose(filePointer);
Bei mir führt das dazu, dass jede Zeile mit der nächsten überschrieben wird. Siehe diese Frage basierend auf der obigen Antwort.
– Cézar Cobuz
8. Januar 2019 um 3:09 Uhr
Warum die Besetzung (FILE*) fp ? Ist nicht fp ist schon ein FILE * und auch fopen() gibt a zurück FILE * ?
– Buchhalter م
4. April 2019 um 23:25 Uhr
Wenn Sie damit einverstanden sind, dass die Zeilen auf eine bestimmte Länge begrenzt sind, ist dies die beste Antwort. Ansonsten verwenden getline ist eine gute Alternative. Ich stimme dem zu FILE * Besetzung ist unnötig.
– das Feuer
17. Oktober 2019 um 2:18 Uhr
Ich habe den unnötigen Cast entfernt, eine Variable für die Pufferlänge hinzugefügt und geändert fp zu filePointer für mehr Klarheit.
– Rauben
6. Januar 2020 um 11:13 Uhr
Es sollte const int bufferLength sein, wenn es umständlich ist 🙂
– baz
12. November 2021 um 20:34 Uhr
Gilles ‘SO- hör auf, böse zu sein’
In deiner readLine Funktion geben Sie einen Zeiger auf die zurück line array (Genau genommen ein Zeiger auf sein erstes Zeichen, aber der Unterschied ist hier irrelevant). Da es sich um eine automatische Variable handelt (dh „auf dem Stack“), wird der Speicher zurückgefordert, wenn die Funktion zurückkehrt. Sie sehen Kauderwelsch, weil printf hat seine eigenen Sachen auf den Stapel gelegt.
Sie müssen einen dynamisch zugewiesenen Puffer von der Funktion zurückgeben. Sie haben bereits eine, es ist lineBuffer; Alles, was Sie tun müssen, ist es auf die gewünschte Länge zu kürzen.
HINZUGEFÜGT (Antwort auf die Folgefrage im Kommentar): readLine gibt einen Zeiger auf die Zeichen zurück, aus denen die Zeile besteht. Diesen Zeiger benötigen Sie, um mit dem Inhalt der Zeile zu arbeiten. Es ist auch das, wozu Sie übergehen müssen free wenn Sie den von diesen Charakteren belegten Speicher verbraucht haben. So können Sie die verwenden readLine Funktion:
char *line = readLine(file);
printf("LOG: read a line: %s\n", line);
if (strchr(line, 'a')) { puts("The line contains an a"); }
/* etc. */
free(line);
/* After this point, the memory allocated for the line has been reclaimed.
You can't use the value of `line` again (though you can assign a new value
to the `line` variable if you want). */
@Iron: Ich habe meiner Antwort etwas hinzugefügt, aber ich bin mir nicht sicher, was Ihre Schwierigkeit ist, also könnte es daneben liegen.
– Gilles ‘SO- hör auf, böse zu sein’
17. August 2010 um 11:53 Uhr
@Iron: Die Antwort ist, dass Sie es nicht befreien. Sie dokumentieren (in der API-Dokumentation) die Tatsache, dass der zurückgegebene Puffer malloc’d ist und vom Aufrufer freigegeben werden muss. Dann werden Leute, die Ihre readLine-Funktion verwenden, (hoffentlich!) Code schreiben, der dem Snippet ähnelt, das Gilles seiner Antwort hinzugefügt hat.
– JeremyP
17. August 2010 um 12:27 Uhr
RevoLab
//open and get the file handle
FILE* fh;
fopen_s(&fh, filename, "r");
//check if file exists
if (fh == NULL){
printf("file does not exists %s", filename);
return 0;
}
//read line by line
const size_t line_size = 300;
char* line = malloc(line_size);
while (fgets(line, line_size, fh) != NULL) {
printf(line);
}
free(line); // dont forget to free heap memory
First line of file
Second line of file
Third (and also last) line of file
Denken Sie daran, wenn Sie aus der Standardeingabe lesen möchten (und nicht wie in diesem Fall aus einer Datei), müssen Sie nur übergeben stdin als dritter Parameter von fgets() Methode, wie folgt:
while(fgets(buffer, MAX_LEN, stdin))
Anhang
Entfernen des nachgestellten Newline-Zeichens aus der fgets()-Eingabe
wie man erkennt, dass eine Datei geöffnet ist oder nicht in c
Hallo, @gsamaras Ich denke, wir können direkt passieren MAX_LEN zu fgets. Diese Beschreibung habe ich gefunden in: linux.die.net/man/3/fgets “` “`
– Benutzer10277898
17. November 2020 um 10:23 Uhr
Hey @juancortez, ich gehe vorbei MAX_LEN - 1 beim 2. Argument der Methode in der Tat!
– Gsamaras
17. November 2020 um 19:36 Uhr
Es besteht keine Notwendigkeit für die -1 in MAX_LEN - 1fgets(buffer, n, fp) liest bereits bis zu n-1 Zeichen und reserviert Platz für die Nullterminierung.
readLine() gibt Zeiger auf lokale Variable zurück, was zu undefiniertem Verhalten führt.
Um herumzukommen, können Sie:
Erstellen Sie eine Variable in der Aufruferfunktion und übergeben Sie ihre Adresse an readLine()
Speicher zuweisen für line verwenden malloc() – in diesem Fall line wird hartnäckig sein
Verwenden Sie globale Variablen, obwohl dies im Allgemeinen eine schlechte Praxis ist
Hallo, @gsamaras Ich denke, wir können direkt passieren MAX_LEN zu fgets. Diese Beschreibung habe ich gefunden in: linux.die.net/man/3/fgets “` “`
– Benutzer10277898
17. November 2020 um 10:23 Uhr
Hey @juancortez, ich gehe vorbei MAX_LEN - 1 beim 2. Argument der Methode in der Tat!
– Gsamaras
17. November 2020 um 19:36 Uhr
Es besteht keine Notwendigkeit für die -1 in MAX_LEN - 1fgets(buffer, n, fp) liest bereits bis zu n-1 Zeichen und reserviert Platz für die Nullterminierung.
Verwenden
fgets
Anstatt vonfgetc
. Sie lesen Zeichen für Zeichen statt Zeile für Zeile.– Scheib
17. März 2017 um 4:00 Uhr
Beachten Sie, dass
getline()
ist ein Teil von POSIX 2008. Es kann POSIX-ähnliche Plattformen ohne sie geben, insbesondere wenn sie den Rest von POSIX 2008 nicht unterstützen, aber innerhalb der Welt der POSIX-Systeme,getline()
ist heutzutage ziemlich tragbar.– Jonathan Leffler
8. Mai 2017 um 21:20 Uhr
Linie[count+1] ist eine automatische Stapelvariable und Sie verwenden einen Zeiger darauf als Rückgabewert. Das ist U.B.
– ulix
13. September um 3:48