我正在尝试删除字符串末尾的空格。我有以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char *trim(char *str) {
char *end;
end = str + strlen(str) - 1;
while(end > str && isspace((unsigned char)*end)) {
end--;
}
*(end++) = '\0'; //this line causes the segfault
return str;
}
int main(void) {
char *str = "mystring ";
printf("before trim string is %s\n", str);
printf("length before: %d\n", strlen(str)); //should be 10
str = trim(str);
printf("after trim string is %s\n", str);
printf("length after: %d\n", strlen(str)); //should be 8
return 0;
}
运行代码时,出现分段错误。我不确定的是为什么将指针“ end”增加1,然后将其指向的值从空格更改为空终止符会导致段错误。我已经读过,在C中增加一个指针,使该指针不指向数组的元素是未定义的行为。但是,“ mystring”末尾的空格是否仍不属于char数组str []的一部分?任何帮助都非常感谢。
答案 0 :(得分:3)
这里的问题是导致崩溃的行正在尝试修改字符串文字,这将导致未定义的行为。
根据https://en.cppreference.com/w/c/language/string_literal
字符串文字是不可修改的(实际上可能放在.rodata之类的只读存储器中)。如果程序尝试修改由字符串文字形成的静态数组,则该行为是不确定的。
您必须确保将char*
传递给可修改的数组,例如您用malloc()
分配的数组。
答案 1 :(得分:2)
其他响应是正确的-但令您惊讶的是编译器没有收到该错误。下面的代码可以在Visual Studio 2017中编译并正常运行。
请注意trim()中的一个小错误
*(++end) = '\0'; NOT
*(end++) = '\0';
一切都很好。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char *trim(char *str) {
char *end;
end = str + strlen(str) - 1;
while (end > str && isspace((unsigned char)*end)) {
end--;
}
*(++end) = '\0'; //this line causes the segfault
return str;
}
int main(void) {
char str0[] = "mystring "; // minor change here
char *str = str0; // minor change here
printf("before trim string is %s\n", str);
printf("length before: %d\n", strlen(str)); //should be 10
str = trim(str);
printf("after trim string is %s\n", str);
printf("length after: %d\n", strlen(str)); //should be 8
return 0;
}
答案 2 :(得分:2)
使用指针处理字符串时,编译器将常量字符串的第一个字符的存储地址分配给指针“ =”之后,并且常量字符串存在于只读存储器中。 您可以尝试以下两个代码来观察差异:
int main()
{
char str[] = "abcd";
*str = 'c';
printf("%s\n", str);
return 0;
}
int main()
{
char *str = "abcd";
*str = 'c'; // error
printf("%s", str);
return 0;
}