C-2D阵列sscanf和索引错误



我试图解析一个文本文档,并将每一行的数据放入一个二维的字符串数组中。但是,在文件关闭后,我的2-D数组的每一行都是最后一行数据的副本。就好像最后一行覆盖了以前的所有数据。例如,array[0][1]打印与array[19][1]相同的值,即使array[0][1]应该是不同的值。

C代码:

int h = 0;
const char* array[20][5];
while(fgets(line, sizeof(line), fp) != NULL)
{
        sscanf(line,"%s%*[^n]",firstWord);
        if (strcmp("transition",firstWord) == 0)
        {
                sscanf(line,"%s%s%s%s%s%s",garbage,temp0,temp1,temp2,temp3,temp4);
                array[h][0] = temp0;
                array[h][1] = temp1;
                array[h][2] = temp2;
                array[h][3] = temp3;
                array[h][4] = temp4;
                h++;
        }
}
fclose(fp);

文本文档示例:

transition  0   1   3       1       R   
transition  3   0   4       0       R   
transition  1   _   7       _       R   
transition  0   _   5       _       R   
transition  0   0   1       x       R   
transition  1   1   2       x       L   
transition  2   0   2       0       L   
transition  2   1   2       1       L   
transition  2   x   2       x       L   
transition  4   0   4       0       L   
transition  4   1   4       1       L   
transition  4   _   4       _       L   
transition  4   x   4       x       L   
transition  1   0   1       0       R   
transition  1   x   1       x       R   
transition  3   1   3       1       R   
transition  0   x   0       x       R   
transition  7   _   7       _       R   
transition  2   _   0       _       R   
transition  3   _   6       _       R

这是因为您没有复制内容,并且在每次迭代中都会覆盖tempN指针。

此处

array[h][0] = temp0;

对于h的每个值,您存储一个指向temp0的指针,然后用下一个scanf()覆盖temp0

因此,当您取消引用array[h][0]时,它指向temp0,其内容是scanf()在上一次迭代中扫描的内容。

您还可以跳过检查scanf()是否成功,这意味着您可能会尝试打印或复制未初始化的值,如果您这样做,您的程序将调用未定义的行为,而您将在地狱中尝试调试它。

尝试复制内容而不是

array[h][0] = strdup(temp0);

或者如果您不在符合POSIX的系统上,则使用等效函数。

编辑:要澄清此评论所说的内容,您永远不应该这样做!如果你想实现自己的strdup(),正确的方法是

char *strdup(const char *const input)
{
    char *result;
    size_t length;
    length = strlen(input);
    result = malloc(length + 1);
    if (result == NULL)
        return NULL;
    memcpy(result, input, length + 1);
    return result;
}

为了更安全,您可以检查input == NULL,但strdup()的标准实现不进行检查,因此这将是您的补充。

  • 为什么要这样做

简单地说,strlen()通过迭代字符串的字符来计算字符串的长度,直到找到终止nul字节的''strcpy()也会迭代从inputresult的字符,直到找到'',而memcpy()通常被优化为复制得更快,您可以使用memcpy(),因为您知道字符串的长度,您无论如何都需要它来为结果分配空间。

简而言之,调用strlen()然后调用strcpy()不是一件明智的事情,当然你知道长度,不需要再次计算。

相关内容

  • 没有找到相关文章

最新更新