2016-08-22 2 views
0

ich folgende Textdatei lesen, müssen zu lesen:wie sowohl scanf und fgets verwenden, um eine Datei

2 2 
Kauri tree 
Waterfall 
0 0 W S 
0 1 E N 

ich die scanf bekommen die erste Zeile und die fgets für die zweite verwenden verwenden wollte und die dritte Linie verwenden Sie dann wieder die scanf für den Rest der Zeilen.

#include <stdio.h> 

#define NUM_OF_CHAR 2 

int main() 
{ 
    int node, edge; 
    scanf("%d %d", &node, &edge); 

    FILE* fp; 
    fp = stdin; 

    char* str[NUM_OF_CHAR]; //should be char str[NUM_OF_CHAR]; 

    for (int i = 0; i < node; i++) { 
     fgets(str[i], 2, fp);  //should be fgets(str, 2, fp); 
    } 
    printf("%s", str[0]);   //printf("%s", str); 
} 

der Eingang I eingegeben wurde:

ich den Code wie folgt geschrieben

2 2 
hello 

I Segmentation fault

ich hier eine ähnliche Frage sah bekam, erwähnt eine Person, dass ich kann fgets einmal anrufen, um die erste Zeile zu bekommen, aber ignorieren Sie es und dann wieder fgets, um die zweite Zeile zu bekommen. Aber ich weiß nicht, wie ich es machen soll.

+0

Verwenden Sie fgets() und dann strtok(), um die Zeichenfolge aufzuteilen. –

+0

Was Ihr * aktuelles * Problem betrifft, den Absturz, den Sie bekommen, denken Sie jetzt ein wenig nach. Du deklarierst ein Array von Zeigern auf 'char', aber du machst diese Zeiger niemals * irgendwo *. –

+0

Hallo Matt. Danke für Ihre Antwort. Ich bin neu in c. Ich weiß nicht, wie man strtok() benutzt. Ich werde es jetzt nachschlagen. – chrisgjh

Antwort

2

Lokale Variablen in Funktionen definiert w Wenn nicht explizit initialisiert, haben sie einen unbestimmten Wert. Für Zeiger bedeutet das, dass sie auf einen scheinbar zufälligen Ort zeigen. Die Verwendung einer nicht initialisierten Variablen außer der Initialisierung führt zu undefined behavior.

Was hier passiert, ist, dass fgets den (nicht initialisierten und scheinbar zufälligen) Zeiger verwendet und ihn zum Schreiben in den Speicher verwendet, auf den er zeigt. Dieser Speicher gehört in den meisten Fällen nicht zu Ihnen oder Ihrem Programm und kann sogar andere wichtige Daten überschreiben. Dies kann zu Abstürzen oder anderen seltsamen Verhalten oder Ergebnissen führen.

Die einfachste Lösung ist str ein Array von Arrays von Zeichen zu machen, wie

#define NUM_OF_STRINGS 2 
#define STRING_LENGTH 64 
... 
char str[NUM_OF_STRINGS][STRING_LENGTH]; 
... 
fgets(str[i], sizeof str[i], stdin); 

Sie müssen sicherstellen, dass STRING_LENGTH oben genug ist, jede Saite einschließlich der Newline und dem String-Terminator zu passen. Im Fall dessen, was ich oben zeige, ist es 64 das bedeutet, dass Sie Zeilen von höchstens 62 Zeichen haben können.


Jetzt wie für das andere Problem, wies ich darauf hin, mit dem ersten Aufruf von fgets eine leere Zeile zu lesen.

Wenn Sie den Eingang haben

2 2 
hello 

Der Eingang in einem Puffer im Speicher gespeichert ist, und dann scanf und fgets aus diesem Puffer liest.Der Puffer wird mit dem oben Eingang, in etwa so aussehen

 
+----+----+----+----+----+----+----+----+----+ 
| 2 | 2 | \n | h | e | l | l | o | \n | 
+----+----+----+----+----+----+----+----+----+ 

Nach dem scanf Aufruf die beiden Zahlen der Eingangspuffer sieht aus wie

 
+----+----+----+----+----+----+----+ 
| \n | h | e | l | l | o | \n | 
+----+----+----+----+----+----+----+ 

So lesen, was der erste Aufruf an fgets in der Schleife wird sehen, ist der Newline. So liest es, dass Newline und dann ist es fertig, die Zeichenfolge "hello\n" im Puffer für die zweiten Anruf an fgets verlassen.

Es gibt einige Möglichkeiten, dieses Problem zu lösen. Dasjenige, das ich persönlich bevorzuge, ist, fgets universell zu verwenden, um Linien zu lesen, und wenn Sie eine einfache Analyse der Linie benötigen, dann verwenden Sie sscanf (beachten Sie die führende s, auch bitte see here for a good reference of all scanf variants), um dies zu tun.

Eine andere Möglichkeit besteht darin, einfach Zeichen von der Eingabe zu lesen und sie zu verwerfen. Wenn Sie einen Zeilenumbruch lesen, stoppen Sie die Schleife und fahren Sie mit dem Rest des Programms fort.

+0

danke. Du hast es für mich wirklich leicht verständlich gemacht. – chrisgjh

1

Betrachten Sie das folgende Beispiel, in dem Kommentare einige wichtige Punkte erläutern:

#include <stdio.h> 

#define NUM_OF_CHAR 2 
#define LEN_OF_STR 20 

int main() 
{ 
    int node, edge; 
    FILE* fp; 
    fp = stdin; 
    char strbuf[LEN_OF_STR]; 
    // stream is available after that 
    // reading numbers 
    fscanf(fp, "%d %d", &node, &edge); 
    // reading strings 
    for (int i = 0; i < node; i++) { 
     // reading line from input stream 
     fgets(strbuf, LEN_OF_STR, fp); 
    } 
    // cleaning input buffer 
    while (getchar() != '\n'); 
    // reading lines with data 
    char str[NUM_OF_CHAR]; 
    int a, b; 
    for (int i = 0; i < node; i++) { 
     // reading two numbers and two characters 
     fscanf(fp, "%d %d %c %c", &a, &b, &str[0], &str[1]); 
     // do something with dada, e.g. output 
     printf("%d %d %c %c\n", a, b, str[0], str[1]); 
    } 
    return 0; 
} 

Wenn Sie Daten mit scanf Lesen oder fscanf Sie die Ergebnisse überprüfen, zB:

if (4 == fscanf(fp, "%d %d %c %c", &a, &b, &str[0], &str[1])) 
    { 
     // actions for correct data 
    } 
    else 
    { 
     // actions for wrong input 
    } 

hier Format Linie 4 hat Spezifizierer - "% d% d% c% c", also prüfen wir als "Vergleichswert mit 4"

+2

Überprüfen des Rückgabewerts von 'scanf' ist ein * muss * – 4386427

+0

das funktioniert eigentlich für mich. danke – chrisgjh

1

Ich habe mein Problem gelöst. Ich sollte keinen char* Zeiger verwenden und es auf ein Array zeigen lassen. Der erste Parameter, der an die fgets-Funktion übergeben wird, sollte ein char* sein, also sollte ich nur ein Array verwendet haben.

auch, seit scanf gescannt aus der ersten Zeile bereits, wenn ich fgets nächsten verwenden, wird es automatisch die nächste Zeile.

#include <stdio.h> 

#define NUM_OF_CHAR 100 

int main() 
{ 
    int node, edge; 
    scanf("%d %d", &node, &edge); 

    FILE* fp; 
    fp = stdin; 

    char str[NUM_OF_CHAR] = {'\0'}; 

    for (int i = 0; i < node; i++) { 
     fgets(str, NUM_OF_CHAR, fp); 
    } 
    printf("%s", str); 
}