1

以下のコードは、文字列 s からデータを取得し、区切り文字として空白を使用して double 配列データに分割することになっています。関数を終了するためにインクリメントする必要があるときに、j カウンターが予期せずリセットされる

関数に渡される char *s は

0.0000000E00     0.0000000E00       -1.9311798E+03       8.0321814E+02       8.0294336E+02  

以下の診断 printf 関数は以下を出力します。

0.000000 | 1
0.000000 | 2
-1931.179800 | 3
803.218140 | 4
802.943360 | 1

プログラムがクラッシュする原因となります

void split_data(char *s, double *data, int fields) {
  char buff[DATA_MAX];
  int j = 0, i;

  for(; *s; *s++) {
    while(*s == ' ' || *s == '\t') /* trim leading white space */
      *s++;

    i = 0;
    while(!(*s == ' ' || *s == '\t'))
      buff[i++] = *s++;
    buff[i] = 0;

    data[j++] = atof(buff);
    printf("%lf | %d\n", data[j-1], j);

    if(j == fields)
      return;
  }
}
4

4 に答える 4

0

fieldsが文字配列内の文字列の数より大きい場合、終了条件はjと。の比較のみに基づいているため、プログラムがクラッシュする可能性がありますfields。コードに次の変更を加えてみてください。

if((j == fields) || (*s == '\0'))
    return;
于 2013-02-09T03:45:23.103 に答える
0

問題は、2 番目のループです。

while(!(*s == ' ' || *s == '\t'))
  buff[i++] = *s++;
buff[i] = 0;

'\t' の ' ' に到達しない限り、バッファーを埋め続けます。残念ながら、文字列終了文字 '\0' はそれらのいずれでもないため、文字列の末尾に到達した後も引き続き埋め続けます。運が良ければ、読み続けているメモリに ' ' '\t' が含まれており、バッファがいっぱいになる前にループが停止します。

問題を解決するには、2 番目のループで '\0' も確認する必要があります。最初のループで確認するか (解析する値が十分でない場合に備えて)、さらに ' ' または '\t ' を文字列の末尾に追加します。

于 2013-02-09T03:50:05.843 に答える
0

おそらくbuff短くしすぎたため、プログラムはバッファの末尾をオーバーランしています (おそらく 1 文字だけ)。これにより、おそらく次のスタック変数が上書きされますj

増やしてみてDATA_MAX、問題が解決するかどうかを確認してください。

于 2013-02-09T03:38:44.697 に答える
0

あなたのループ:

   while(!(*s == ' ' || *s == '\t'))
      buff[i++] = *s++;

文字列の終わりのテストも含める必要がありますs。たとえばwhile(!(*s == ' ' || *s == '\t') && *s) ...

そうbuffしないと、オーバーフローするまで「ノイズ」で満たされ続けます。そして、スタック上の他の変数 ( など) が破壊され始めますj。ただし、動作はコンパイラに大きく依存します。

于 2013-02-09T03:40:09.873 に答える