【问题标题】:C - 2D Array sscanf and indexing errorC - 2D 数组 sscanf 和索引错误
【发布时间】:2015-09-21 00:13:02
【问题描述】:

我正在尝试解析文本文档并将每一行的数据放入 char 字符串的二维数组中。但是,文件关闭后,我的二维数组的每一行都是最后一行数据的副本。就好像最后一行覆盖了所有以前的数据。例如,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

【问题讨论】:

    标签: c multidimensional-array


    【解决方案1】:

    这是因为您没有复制内容,而是在每次迭代时覆盖了 tempN 指针。

    这里

    array[h][0] = temp0;
    

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

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

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

    尝试复制内容

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

    如果您不在兼容 POSIX 的系统上,则使用等效功能。

    编辑:澄清this comment says,你不应该那样做!如果您想实现自己的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 字节的'\0' 来计算字符串的长度,并且strcpy() 也会将字符从input 复制到result迭代直到找到'\0',而不是memcpy() 通常经过优化以更快地复制,您可以使用memcpy(),因为您知道字符串的长度,无论如何您都需要它来为结果分配空间。

    简而言之,调用strlen() 后跟strcpy() 不是明智之举,你知道长度不需要再次计算。

    【讨论】:

    • 如果你不喜欢strdup,可以使用array[h][0] = malloc(sizeof(char) * (strlen(temp0) + 1)); strcpy(array[h][0], temp0);
    • 不,你不应该使用sizeof(char),因为标准保证它是1。您必须检查malloc() 没有返回NULL。最重要的是,有什么理由避免strdup()?假设它确实做到了,malloc() -> 检查NULL 并在这种情况下返回NULL,复制数据。而且您的副本效率并不高,因为您将计算字符串的长度两次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    • 2017-10-27
    • 2021-06-27
    • 1970-01-01
    • 2023-03-30
    • 2014-06-01
    • 2016-02-20
    相关资源
    最近更新 更多