2012-01-14 2 views
2

更新:文字列をchar string[sizeof buffer - 1]と正しく初期化するとクラッシュする問題は解決しましたが、句読点が複数あるそれ!Cでsscanfを使用して文字列を読み取るときに句読点にエラーが発生する

"some text"の形式でファイルから文字列を読み取ろうとしています。パターン\"%[^\"]\"sscanfを使用すると、これまでのところ完全に機能しましたが、文字列に句読点を追加するとすぐに、プログラムがクラッシュし始めました。

エラーは、句読記号が何であっても、マークの位置に関係なく、複数の句読記号が使用されている場合にのみ発生します。また、ファイル内に句読点がある行の位置に関係なく発生します(最後の行に句読点がない場合でもエラーが発生します)。

char* func(char* f_name); 
    FILE* file = get_file(f_name,"r"); // a short function I wrote to get the 
             // file pointer from the current 
             // directory. The error is almost 
             // certainly not here. 
    if (file == 0) { 
     print("Unable to load file\nExiting..."); 
     exit(-1); 
    } 

    char* pattern = "\"%[^\"]\""; 
    int read_args = -1; 
    char* string; // string size is unknown until read 
    char buffer[1200]; // i expect very long line of data in the file 

    while (fgets(buffer, sizeof(buffer), file) != NULL) { 
     printf("found line: %s\n",buffer); 
     read_args = sscanf(buffer, pattern, string); 
     printf("num args: %d\n",read_args); 
     printf("read value: %s\n", string); 
    } 

    fclose(file); 
    return string; 
} 

私が試してみましたいくつかのデータ、次のとおりです

とにかく、以下の私がこれまで持っているコードです。 「失敗」とマークされた場所では、プログラムはコンパイルされ、すべて実行され、終了する直前にクラッシュします。

"test test test" // successful 
"test, test test" // successful 
"test test; test" // successful 

"test, test, test" // unsuccessful 
"test; test. test," // unsuccessful 

私は、この問題が解決された場合に、より複雑なパターンを使用することを計画しており、このエラーが発生する前のパターンに成功%d \"%[^\"]\" \"%[^\"]\"でデータを読んでいました。すべての回答に事前に感謝します。

答えて

3

あなたのコードは、ランダムなメモリをスキャンしているので、未定義の動作を呼び出します。

string変数は決して初期化されないので、sscanf()で書かれた文字列の宛先は未定義です。

char string[sizeof buffer - 1]; 

常にクラッシュするとは限りませんが、コードは常に未定義の動作を呼び出しています。あなたの例に基づいて、句読点付きであったかもしれませんが、スキャンされたテキストは長くなり、メモリを上書きしてしまい、最終的には何か重要なものにヒットしました。

+0

ありがとう、これは問題を解決したようです。私はまだ句読点がそれと何をしなければならないのか不思議です... –

+0

未定義の振舞いを呼び出すと、何かが起こり、それは標準に従ってOKです。関数は振る舞いをすることができます。振る舞いは定義されていないので、すべてOKです。したがって、すべてのコストで未定義の動作を避けてください。そして、あなたが未定義の振る舞いをしているのを見つけたら、振る舞いを誤動作させてしまったときに、時間を費やしてはいけません。しかし、あなたが本当に好奇心が強いならば、処理しているかもしれないと思っていたものではなく、実際に処理していたものを見るために '古いバージョンの文字列 'を印刷してみてください。しかし、それはおそらく努力に値するものではありません。 –

関連する問題