我用C写了一个函数来从字符串中删除空白字符。我关心的是下面trim()函数的最后一行,其中源包含在目标中。测试用例和其他一些测试结果都很好。复制源和目标在同一内存中的字符串的全部或部分会导致奇怪的问题吗?
源代码:#include <stdio.h>
#include <string.h>
void trim(char *line)
{
int i, len = strlen(line);
char *ptr, whitespace[] = " tn";
// scan for first char which does not match a char in whitespace string
for (i=0; i<len; i++)
if (strchr(whitespace, line[i]) == NULL)
break;
ptr = line + i;
// scan for last char which does not match a char in whitespace string
for (i=len; i>0; i--)
if (strchr(whitespace, line[i]) == NULL)
break;
line[i] + 1) = ' ';
// copy result to line (this is the line relevant to the question)
strncpy(line, ptr, len);
}
int main(void)
{
int i;
char test[4][64] = {
"a line with no leading and trailing spaces",
" a line with some leading and trailing spaces ",
"ta line with leading and trailing tabst",
"na line with leading and trailing newlinesn"
};
for (i=0; i<4; i++)
{
printf("test %dnno trim: %sn", i, test[i]);
trim(test[i]);
printf("trimmed: %sn", test[i]);
}
return 0;
}
如果你读这个strncpy
参考,你会看到
如果字符数组重叠,该行为是未定义的。
您需要使用memmove
,它被指定用于处理重叠内存。
首先,第二个循环是错误的。我将它复制到这里,以显示它失败的确切位置:
// scan for last char which does not match a char in whitespace string
for (i=len; i>0; i--)
if (strchr(whitespace, *(line + i)) == NULL)
break;
*(line + i + 1) = ' ';
二选一:
- 或者将
for
循环重写为for(i = len-1; i>=0; i--)
, - 或者在循环中写入对
*(line + i - 1)
的引用。
你第一次进入循环,你得到一个