我试图解析一个文本文档,并将每一行的数据放入一个二维的字符串数组中。但是,在文件关闭后,我的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()
也会迭代从input
到result
的字符,直到找到' '
,而memcpy()
通常被优化为复制得更快,您可以使用memcpy()
,因为您知道字符串的长度,您无论如何都需要它来为结果分配空间。
简而言之,调用strlen()
然后调用strcpy()
不是一件明智的事情,当然你知道长度,不需要再次计算。