0

私は、C を使用してファイルから行をスキャンし、それらを構造体に格納する必要があるプログラムに取り組んできました。

私の .txt ファイルは次の形式です。

NAME 0.2 0.3
NAME2 0.8 0.1

または、一般に、文字列の後に 2 つの double が続く

私の構造体は次のとおりです。

struct device {
char* name;
double interruptProbability, interruptTime, startTime, endTime;
} myDevice;

今、私は行をうまくスキャンできますが、それらを私の構造体に入れる時が来ると、何かが台無しになります。スキャンを行う方法は次のとおりです。

    char line[BUFSIZ];
    while(fgets (line, BUFSIZ, devicesFile) != NULL){
        struct device *d = &myDevice;
        if(!isspace(*line)){
            printf("String: %s \n", &line);
            d->name = "success"; // for testing purposes
            printf("device name before: %s \n", d[0]);
            sscanf(line, "%s %f %f",&d->name, &d->interruptProbability, &d->interruptTime);
            printf("device name after: %s \n", d[0]);
        }
    }

これを実行すると、次のように出力されます。

String: Disk 0.2 0.00005


device name before: success 

私にセグフォルトを与える前に。

スキャンで何が起こっているかをテストするために GDB を実行しましたが、何らかの理由で d->name に (アドレス範囲外) が横にある巨大な 16 進数を入力しました。

何か案は?

4

4 に答える 4

1

sscanfこれは、呼び出しでリテラル文字列を上書きしているためです。d->nameリテラル文字列を指し、それらは読み取り専用で固定長です (したがって、取得しようとする文字列が 7 文字よりも長い場合は、末尾を超えて書き込もうとします)。

配列を使用するかd->name、ヒープにメモリを割り当てる必要があります。

于 2013-02-07T03:26:16.587 に答える
0

あなたはあなたのそれぞれにスペースを割り当てていませんchar *named->name = (char *)malloc(<length of the token>*sizeof(char)+1)sscanf呼び出しの前に追加する必要があります。

于 2013-02-07T03:29:48.843 に答える
0

文字列をスキャンしてポインタに入れることはできませんd->name

定数値を割り当てた後でも、次のようになります。

d->name = "success"; // for testing purposes

そのためにメモリを割り当てるか、配列にする必要があります。sscanf文字列の読み取りには、非常に注意して使用する必要があります。strtokを使用するかstrchr、最初のスペースを見つけてから、。を使用してバイトをコピーする方がよい場合がありますstrdup

char *next = strchr(line, ' ');
if( next != NULL ) {
    *next++ = 0;             // Terminate string and move to next token.
    d->name = strdup(line);  // Make a copy of tokenised string

    // Read the floats - note you should check that the result is equal to 2.
    count = sscanf(next, "%f %f", d->interruptProbability, d->interruptTime);
}
于 2013-02-07T03:30:22.857 に答える
0

文字列リテラルをスキャンしています。文字列リテラルはCおよびC++ではconstchar*であり、読み取り専用であるため、文字列リテラル「success」に書き込もうとするとsscanfがクラッシュします。

于 2013-02-07T03:30:28.890 に答える