Chr*_*ris 2 c alphabet string.h
我在C中编写一个函数,它将获取一个字符串并删除所有不是小写字母字符的字符.我到目前为止编写了这段代码:
void strclean(char* str) {
while (*str) {
if (!(*str >= 'a' && *str <= 'z')) {
strcpy(str, str + 1);
str--;
}
str++;
}
}
Run Code Online (Sandbox Code Playgroud)
当我传递字符串"hello [] [] world"时,该函数似乎主要工作,除了输出是:
hellowoldd
Run Code Online (Sandbox Code Playgroud)
当我在输入if语句的每一行之后打印它时,这是我收到的输出:
hello][]woldd
hello[]woldd
hello]woldd
hellowoldd
Run Code Online (Sandbox Code Playgroud)
它似乎非常接近,但我不明白为什么它会产生这个输出!最奇怪的部分是我已经将代码提供给其他两个朋友,它在他们的计算机上工作正常.我们都运行相同版本的Linux(ubuntu 14.04.3),并且都使用gcc进行编译.
我不确定代码是否存在导致输出不一致的问题,或者是否是导致问题的编译器问题.也许它与我的机器上的strcpy相比,与他们相比?
strcpy如果范围重叠,则无法保证该功能正常工作,就像在您的情况下一样.从C11 7.24.2.3 The strcpy function /2(我的重点):
该
strcpy函数将指向的字符串s2(包括终止空字符)复制到指向的数组中s1.如果在重叠的对象之间进行复制,则行为未定义.
您可以使用类似memmove,它也有重叠范围,按工作C11 7.24.2.2 The memmove function /2:
该
memmove函数n将指向的对象中的字符复制到指向s2的对象中s1.复制发生就好像n从对象人物指向s2首先拷贝到一个临时数组n不重叠的对象指向的字符s1和s2,然后n从临时数组字符复制到对象指向s1.
但是有一个更好的解决方案,O(n)而不是时间复杂性,同时仍然是重叠安全的:O(n2)
void strclean (char* src) {
// Run two pointers in parallel.
char *dst = src;
// Process every source character.
while (*src) {
// Only copy (and update destination pointer) if suitable.
// Update source pointer always.
if (islower(*src)) *dst++ = *src;
src++;
}
// Finalise destination string.
*dst = '\0';
}
Run Code Online (Sandbox Code Playgroud)
您会注意到我也在使用islower()(from ctype.h)来检测小写字母字符.这更便于携带,因为C标准并未强制要求字母字符具有连续的代码点(数字是唯一保证连续的数字).
也没有单独的检查需要,isalpha()因为,因为C11 7.4.1.2 The isalpha function /2,islower() == true暗示isalpha() == true:
该
isalpha函数测试任何字符为哪个isupper或islower为真,或者......