2016-07-21 15 views
2

Ich habe ein kleines Beispielprogramm, um mein Problem unten zu illustrieren: Ich habe eine einfache Textdatei mit drei Wörtern (jeweils in einer neuen Zeile) die fscanf liest, weist eine temporäre Variable zu und dann wird in ein String-Array übertragen. Die Werte scheinen jedoch nicht auf das Array zu übertragen. Auch wenn ich den Kommentar // aus dem zweiten printf in der while-Schleife entferne, bekomme ich einen seg-Fehler.fscanf Verwendung in c - Werte werden nicht richtig gespeichert

Ich bin ziemlich neu in C, also erst jetzt lernen die Verwendung dieser Funktionen! Danke im Voraus für Hilfe!

#include <stdio.h> 
#include <string.h> 

int main (int argc, char* argv[]) 
{ 
char* words[15]; 
char tmp[45]; 
int i = 0; 

FILE* fp = fopen("small", "r"); 

while (fscanf(fp, "%s", tmp) == 1) 
{ 
    printf("%s\n", tmp); 
    words[i] = tmp; 
    i++; 
    //printf("%s ", words[i]); 
}    
printf("\n"); 
printf("Words 0 = %s\n", words[0]); 
printf("Words 2 = %s\n", words[1]); 
printf("Words 3 = %s\n", words[2]); 

fclose(fp); 
} 

Ausgabe

pears 
apples 
zipper 

Words 0 = zipper 
Words 2 = zipper 
Words 3 = zipper 
+1

Es muss eine Reihe von Fragen sein, die dies ist ein Duplikat - es ist ein häufiges Problem. –

+0

Hier sind zwei Duplikate: http://StackOverflow.com/Questions/29335910/having-trouble-with-array-being-overwritten http://StackOverflow.com/questions/16268520/c-value-being-change-overwritten –

Antwort

4

in Ihrem Code words[i] = tmp; ist nicht der Weg zu Speicher jede Eingabe in die words Array. Diese speichert nur die Basisadresse des Arrays tmp in jedem words[i] und später, während des Druckens, druckt es tatsächlich den neuesten Inhalt des tmp bei jeder Iteration.

Wenn Sie die Inhalt des tmp Array in jedem words[i] erhalten möchten, müssen Sie entweder

  • Speicher zuweisen zu jedem words[i] und verwenden strcpy()
  • Verwenden strdup() und weisen das zu words[i].

In beiden Fällen müssen Sie free() die zugewiesenen Speicher vor dem Beenden.

+0

Sehr hilfreich, danke! – Leon

1

Ich hatte das gleiche Problem in der Vergangenheit.

Das Problem ist, dass wenn Sie aus der Datei lesen, das Wort im Puffer gehalten wird, und Sie es dann in der Variablen temp speichern.

Die Sache ist, dass wenn Sie das nächste Wort lesen, der Inhalt des Puffers ändern. Und dies betrifft auch den vorherigen Anruf!

So lesen Sie "Birnen", Sie "Birnen" und Worte [0] = "Birnen" drucken

Dann lesen Sie "Äpfel", Sie drucken Äpfel und Worte [1] = "Äpfel". ABER AUCH Wörter [0] = "Äpfel" jetzt !!

Und so weiter ...

Was Sie tun müssen, ist, bevor die Datei zu lesen, zuzuteilen Speicher mit malloc für alle Worte [i] und bekommen es gleich „“.

z.B. words[0] = "" etc.

Wenn Sie dann mit dem Lesen der Datei beginnen, sollten Sie die Funktion strcpy() für temp und words [i] verwenden. Dies wird dein Problem lösen.

Ich habe versucht, so einfach zu antworten, wie ich könnte, weil in der Vergangenheit dieses Problem mich beunruhigte und mich sehr verwirrte.

0

Das erste wichtige Problem mit Ihrem Code ist diese Linie

char* words[15]; 

Es Ihnen ein Array von 15 char Zeigern gibt (char*). Das ist nicht das gleiche wie ein Array von 15 Saiten. Es gibt keinen Speicher zum Speichern der Zeichenfolgen.

Um Speicher zum Speichern der Zeichenkette zu erhalten, die Sie tun können:

char words[15][45]; 
//^  ^^ 
// no *  memory for each of the 15 strings 

Jetzt haben Sie Speicher für 15 Saiten. Jeder String kann bis zu 44 Zeichen lang sein.

Mit dieser Änderung brauchen Sie nicht die tmp Variable - lesen Sie einfach direkt in words. Etwas wie:

#include <stdio.h> 
#include <string.h> 

int main (int argc, char* argv[]) 
{ 
    char words[15][45]; 
    int i = 0; 

    FILE* fp = fopen("small", "r"); 
    if (!fp) 
    { 
    printf("no such file\n"); 
    return 0; 
    } 

    while ((i < 15) && (fscanf(fp, "%44s", words[i]) == 1)) 
    {         // ^^^^^^^^ is the same as &words[i][0] 
    i++; 
    } 
    printf("\n"); 

    int t; 
    for (t = 0; t < i; ++t) 
    { 
    printf("Words %d = %s\n", t, words[t]); 
    } 

    fclose(fp); 

    return 0; 
} 

Einige andere wichtige Änderungen hinzugefügt:

1) Nach fopen Sie NULL überprüfen müssen

2) Für scanf mit% s geben immer eine maximale Größe (dh% 44s) so kann es nicht Pufferüberlauf sein

3) Achten Sie auf die while zu stoppen, wenn Sie 15 Strings gelesen haben (Pufferüberlauf zu verhindern)

4) nur so viele Strings drucken, wie Sie in

Schließlich habe ich hinzugefügt return 0 bis Ende main

+0

Hilfreiche Tipps, vielen Dank! – Leon