8

構造体の配列に最大 100 のエントリを持つ CSV ファイルから値を読み取る単純なコードを作成しようとしています。

CSV ファイルの行の例:

1,Mr,James,Quigley,Director,200000,0

次のコードを使用して値を読み取りますが、値を出力すると値が正しくありません

for(i = 0; i < 3; i++) /*just assuming number of entries here to demonstrate problem*/
    {
    fscanf(f, "%d,%s,%s,%s,%s,%d,%d", &inArray[i].ID, inArray[i].salutation, inArray[i].firstName, inArray[i].surName, inArray[i].position, &inArray[i].sal, &inArray[i].deleted);
    } 

次に、名を出力すると、値はすべて名に割り当てられます。

for(j = 0; j < 3; j++) /* test by printing values*/
    {
    printf("Employee name is %s\n", inArray[j].firstName);
    } 

ames,Quigley,Director,200000,0そのように与えるなど。fscanf 行をフォーマットする方法だと確信していますが、動作させることができません。

ここに私が読んでいる私の構造体があります:

typedef struct Employee
    {
    int ID;
    char salutation[4];
    char firstName[21];
    char surName[31];
    char position[16];
    int sal;
    int deleted;
    } Employee;
4

2 に答える 2

17

これは、文字列%sにコンマを含めることができるため、最初の文字列にスキャンされるためです。フォーマット指定子には「先読み」はありません。フォーマット指定文字列で の後にコンマが続くscanf()という事実は、何の意味もありません。%s

文字グループを使用します (マニュアルで を検索してください[)。

const int got = fscanf(f, "%d,%[^,],%[^,],%[^,],%[^,],%d,%d", &inArray[i].ID,
                       inArray[i].salutation, inArray[i].firstName,
                       inArray[i].surName, inArray[i].position, &inArray[i].sal, 
                       &inArray[i].deleted);

また、I/O 呼び出しが失敗する可能性があるため、戻り値を確認することを学びましょう! gotが 7でない限り、有効なデータに依存しないでください。

プログラムにファイル全体 (複数のレコード、つまり行) を読み取らせるには、行全体を で (大きな) 固定サイズのバッファーにロードし、そのバッファーfgets()で を使用sscanf()して列の値を解析することをお勧めします。それははるかに簡単で、実際に別々の行をスキャンすることを保証します.改行は単なる空白であるfscanf()ため、ループで呼び出すことはできません.fscanf()

于 2013-09-11T09:22:21.180 に答える
2

私のコメントを答えとして投稿することもできます:

%sデフォルトで完全な単語を読み取ります。

、整数%d部分、次に 、,そして文字列を読み取る必要があります。,は単語で有効と見なされるため (空白ではありません)、最初のコンマまでではなく、行末まで読み取ります (それまで空白はありません)。残りは空のままです。(この回答から)

正規表現を指定してセパレーターを変更する必要があります。

fscanf(f, "%d,%[^,],%[^,],%[^,],%[^,],%d,%d", &inArray[i].ID, inArray[i].salutation, inArray[i].firstName, inArray[i].surName, inArray[i].position, &inArray[i].sal, &inArray[i].deleted);

の代わりに%sを使用します%[^,]。これは、「すべての文字を取得し、見つかったら停止する」ことを意味し,ます。

編集

%[^,]s悪いです、スキャンセットの終了後にリテラルが必要にsなります...ありがとう@MichaelPotter

( scanf() 区切り文字の変更およびCSV ファイルから変数への値の読み取りから)

于 2013-09-11T09:25:25.293 に答える