【问题标题】:C counter resets unexpectedlyC 计数器意外重置
【发布时间】:2013-02-09 03:33:43
【问题描述】:

下面的代码应该从字符串 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;
  }
}

【问题讨论】:

  • 显示完整的程序,数据数组中有多少元素,字段的值。看起来像内存问题。

标签: c arrays counter ansi


【解决方案1】:

你的循环:

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

还应包含对字符串 s 结尾的测试。例如while(!(*s == ' ' || *s == '\t') && *s) ...

否则,buff 将继续充满“噪音”,直到溢出。然后堆栈上的其他变量将开始被破坏,例如j。但行为非常依赖于编译器。

【讨论】:

  • 我将其更改为 while(!(*s == ' ' || *s == '\t') && *s) 并且它有效。我不确定它与 j 变量重置有什么关系
  • 你可能会用噪音溢出buff,然后破坏j
  • “噪音”是内存中的随机数据。但这些“随机”数据通常完全为零,因为出于安全原因,操作系统必须先清空任何内存,然后才能将其提供给您。所以j 被零覆盖,你将j++ 打印为 1。(调试模式下的 MSVC 也将内存设置为零。)
【解决方案2】:

您可能使buff 太短,因此您的程序超出了缓冲区的末尾(可能只有一个字符)。这将导致它覆盖下一个堆栈变量,可能是j

尝试增加DATA_MAX,看看是否能解决问题。

【讨论】:

    【解决方案3】:

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

    if((j == fields) || (*s == '\0'))
        return;
    

    【讨论】:

      【解决方案4】:

      问题是你的第二个循环:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-10
        • 1970-01-01
        • 1970-01-01
        • 2015-03-29
        • 1970-01-01
        相关资源
        最近更新 更多