从 c 中的字符串中删除尾随空格时出现分段错误
Segmentation fault when removing trailing whitespace from string in c
我正在尝试删除字符串末尾的白色 space。我有以下代码:
#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++) = '[=10=]'; //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,然后将其指向的值从白色 space 更改为空终止符会导致段错误。我读过在 C 中递增指针以使指针不指向数组元素是未定义的行为。但是,"mystring" 末尾的白色 space 不会仍然是 char 数组 str[] 的一部分吗?非常感谢任何帮助。
这里的问题是导致崩溃的行试图修改字符串文字,这会导致未定义的行为。
根据https://en.cppreference.com/w/c/language/string_literal,
String literals are not modifiable (and in fact may be placed in read-only memory such as .rodata). If a program attempts to modify the static array formed by a string literal, the behavior is undefined.
您必须确保将 char*
传递给可修改的数组,例如您使用 malloc()
.
分配给自己的数组
其他回答是正确的 - 但令我惊讶的是您的编译器没有发现错误。下面编译并运行良好 Visual Studio 2017.
请注意 trim()
中的一个小错误
*(++end) = '[=10=]'; NOT
*(end++) = '[=10=]';
现在一切都很好。
#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) = '[=11=]'; //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;
}
当用指针处理字符串时,编译器将常量字符串“=”后第一个字符的存储地址赋值给指针,常量字符串存在于只读内存中。
你可以尝试这两个代码来观察差异:
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;
}
我正在尝试删除字符串末尾的白色 space。我有以下代码:
#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++) = '[=10=]'; //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,然后将其指向的值从白色 space 更改为空终止符会导致段错误。我读过在 C 中递增指针以使指针不指向数组元素是未定义的行为。但是,"mystring" 末尾的白色 space 不会仍然是 char 数组 str[] 的一部分吗?非常感谢任何帮助。
这里的问题是导致崩溃的行试图修改字符串文字,这会导致未定义的行为。
根据https://en.cppreference.com/w/c/language/string_literal,
String literals are not modifiable (and in fact may be placed in read-only memory such as .rodata). If a program attempts to modify the static array formed by a string literal, the behavior is undefined.
您必须确保将 char*
传递给可修改的数组,例如您使用 malloc()
.
其他回答是正确的 - 但令我惊讶的是您的编译器没有发现错误。下面编译并运行良好 Visual Studio 2017.
请注意 trim()
中的一个小错误*(++end) = '[=10=]'; NOT
*(end++) = '[=10=]';
现在一切都很好。
#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) = '[=11=]'; //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;
}
当用指针处理字符串时,编译器将常量字符串“=”后第一个字符的存储地址赋值给指针,常量字符串存在于只读内存中。 你可以尝试这两个代码来观察差异:
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;
}