1

下面的代码应该从字符串 s 中获取数据并将其拆分为以空格为分隔符的双精度数组数据。当 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

你可能写得buff太短了,所以你的程序超出了缓冲区的末尾(可能只有一个字符)。这将导致它覆盖下一个堆栈变量,可能是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 回答
0

如果fields大于字符数组中的字符串数,则程序可能会崩溃,因为您的退出条件仅基于 j 与 的比较fields。您可以尝试在您的代码中进行以下修改吗?

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

问题是你的第二个循环:

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

除非你到达 '\t' 的 ' ' ,否则你会一直填充缓冲区,不幸的是,字符串终止字符 '\0' 都不是,所以在到达字符串末尾后你仍然继续填充。如果您很幸运,您继续阅读的内存包含任何 ' ' '\t' 并且您的循环将在缓冲区满之前停止。

为了解决您的问题,您还应该在第二个循环中检查 '\0' - 如果您在第一个循环中执行它会更好(以防没有足够的值来解析)或添加额外的 ' ' 或 '\t ' 到字符串的末尾。

于 2013-02-09T03:50:05.843 回答