2016-08-22 3 views
2

私はstackoverflowの新しいユーザーです。私はこのコードをcで書いたが、問題はなく出力は正しい。c(セグメンテーションフォルト)でファイルを読み取るためにfscanfを使用するにはどうすればよいですか?

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    char *str[10]; 
    FILE * fp; 

    fp = fopen ("file.txt", "w+"); 
    fputs("We\nare\nin\n2016", fp); 

    rewind(fp); 

    fscanf(fp, "%s", str[0]); 
    fscanf(fp, "%s", str[1]);    

    printf("Read String1 |%s|\n", str[0]); 
    printf("Read String2 |%s|\n", str[1]); 

    fclose(fp); 

    return(0); 
} 

しかし、char * str [10]の代わりにchar * str [15]を使用すると、結果はセグメンテーションフォルトになります。なにが問題ですか?

+1

'str'配列の各ポインタはどこにポイントしていますか?プログラムが*未定義の動作*をしていると思われるからといって正しいとは限りません。 –

+0

そしてなぜこれはstr [10]に対して正しいのですか?私もstr [15]を初期化しましたが、動作しません。 –

+1

'char * str [10]'、それは動作するように見える純粋な運です(良いか悪いのかは遠近法の問題です)。ちょうど*うまくいくように見えますが、メモリは一見無作為に上書きされます。覚えておいて、定義されていない動作の可能性のある症状の1つは、残念ながら実際に動作することです。 –

答えて

1

ポインタstr[0]str[1]は初期化されていません。したがって、あなたのプログラムはの未定義の動作を持っています。

malloc()を使用して割り当てるか、ファイルから読み込んだ文字列に十分な固定長の配列(たとえばstr[2][256];)にする必要があります。 いずれにしても、私は個人的にfscanf()の代わりにfgets()を使用し、必要に応じて行を解析します。

また、すべての関数(fopen()、fscanf()など)のエラーチェックに役立ちます。

+0

そして、これがなぜstr [10]に対して正しいのですか?私もstr [15]を初期化しましたが、動作しません。 –

+1

'char * str [10]'はポインタの配列であり、それらのポインタは初期化されていません。彼らはあなたが書き込むことのできる記憶を指さない。したがって、次のようなもので初期化する必要があります: 'str [0] = malloc(256); str [1] = malloc(256); '(または、答えの中で述べたように配列を使う)。 – usr

0

char * str [10]を宣言しているときは、10個のポインタ用にメモリを予約していますが、mallocを呼び出してこれらのポインタの内容のメモリを予約していないことに注意してください。

あなたの例は、fscanf関数http://www.tutorialspoint.com/c_standard_library/c_function_fscanf.htmのこのチュートリアルと似ています。

しかし、文字列部分はchar * [10]ではなくchar [10]として宣言されています。つまり、すでに10文字分のメモリが予約されています。この同じ例では、長さが10より大きい文字列を読み取ると問題が発生します。

関連する問題