所以我有一个包含重复项的字符串数组。我的总体目标是删除重复项并相应地调整数组大小。到目前为止,我最好的方法是使用memmove()函数。
我当前的测试方法是遍历数组并扫描每个项目。如果遇到一个字符串不止一次,那么我将使用memmove()用列表中的下一个项目覆盖重复项。列表中的每一项也将使用memmove()在数组中上移一位。然后,我将调整整个数组的大小,以删除数组末尾的空内存位置。
我已经这样声明了数组:
char source[43][20];
该数组只是一个城市列表(我仅包括了前6个用于演示的城市):
York
Leeds
Liverpool
Manchester
Reading
Oxford
我设法用下面的代码覆盖了第一个元素和第二个元素:
memmove(&(source[0][0]), &(source[1][0]), strlen(source[1]) * sizeof(char));
提供此输出:
Leeds
Leeds
Liverpool
Manchester
Reading
Oxford
但是当我尝试使用此代码覆盖第二个元素上的第三个元素时:
memmove(&(source[1][0]), &(source[2][0]), strlen(source[2]) * sizeof(char));
我得到以下输出:
Leeds
Liverpooφu
Liverpool
Manchester
Reading
Oxford
如您所见,利物浦无法正常工作。目前,我目前也不知道如何调整数组的大小,因此,我将不胜感激。感谢任何帮助人员:)。
答案 0 :(得分:3)
进行复制时,不会复制终止的空字节。这意味着复制之后发生的任何垃圾都会被当作字符串的一部分读取。
由于数组元素的大小固定,因此只需复制整个子数组即可:
memcpy(source[0], source[1], sizeof(source[0]));
如果要移动多个元素:
memmove(source[0], source[1], sizeof(source[0]) * num_to_move);
答案 1 :(得分:0)
复制字符串时,您忘记了零终止字符。您需要strlen(...) + 1
复制包含零个终止字符的字符串。
sizeof(char)
可以省略-char
总是1个字节,sizeof(char)
总是1个字节。
这里不需要使用memmove
,假设strlen(source[2]) + 1 < 20
,则source[1], source[1] + strlen(source[2])
和source[2], source[2] + strlen(source[2])]
会干扰存储区域。然后memcpy
即可。但就此而言,只需strcpy
个字符串。
strcpy(source[0], stource[1]);
strcpy(source[1], stource[2]);
// etc...
如果您不关心复制的额外字节,则可以一次性移动所有字符串,例如:
memmove(&source[0], &source[1], sizeof(source) - 1 * sizeof(*source));
答案 2 :(得分:0)
请注意,您无法调整数组大小。为了能够使用realloc
,您可以执行以下操作:
char (*source)[20] = malloc(sizeof *source * 43);
这将为您提供一个指向20个字符的数组的指针,然后为43个此类数组分配内存。以后可以重新分配。像这样:
char (*source)[20] tmp = realloc(source, sizeof *source * size);
if(tmp)
source = tmp;
else
// Handle error
请注意,char (*source)[20]
与char *source[20]
完全不同。后者是20个指针的数组。
还要注意,sizeof
可能有些棘手。上面的方法有效,但是如果您使用char **source
而不是char (*source)[20]
,则必须对其进行修改。
为了完整起见,即使其他人提到过,您的问题也在于您没有复制\0
字符。最简单的解决方案是使用strcpy
,但是strncpy
更安全。
strncpy(source[0], source[1], 20);