void delchar(char *s, char c){
char *p, *q = NULL;
for(p = s;*p != '\0'; p++){
if(*p == c){
q = p;
do{
*q = *(q + 1);
q++;
}while(*q != '\0');
}
}
}
我想使用此代码删除字符串中的特定字母,因此我创建了一个指针p来扫描字符串,创建另一个指针q以移动该特定字母后面的元素并覆盖它。但事实证明表达式* q = *(q + 1)用于移动和覆盖错误“程序收到信号SIGSEGV,分段错误”。我只是不知道它的原因。
答案 0 :(得分:2)
即使您不会因此而出现分段错误,您的算法也存在缺陷。即使删除了字符,也可以提前p
光标。
使用while
代替for
:
#include <stdio.h>
#include <string.h>
void delchar(char *s, char c)
{
char *p, *q = NULL;
p = s;
while (*p != '\0')
{
if (*p == c)
{
q = p;
do {
*q = *(q + 1);
q++;
} while(*q != '\0');
}
else
p++; // Advance cursor only if no character was deleted
}
}
int main()
{
char str[1024];
strcpy(str, "Yes or no?");
delchar(str, ' ');
printf("%s\n", str);
return 0;
}
输出:
Yesorno?
您可能会遇到分段错误的原因是尝试更新字符串文字。字符串文字不会被修改。它们与char数组完全不同。主要区别在于您无法覆盖其内容。
int main()
{
char *str = "to to"; // string literal
delchar(str, ' '); // segmentation fault
char array[] = "to to"; // array of char
delchar(array, ' '); // no segmentation fault
printf("%s\n", str);
return 0;
}
您可以使用strcpy()
复制字符串,就像我上面一样,或者您可以使用字符数组而不是字符串文字。
答案 1 :(得分:0)
有一个原因可能发生这种情况:当你尝试写入程序代码部分中的字符串(而不是堆栈或堆)时。
调用这样的代码(数据在(只读)代码部分):
char *s = "1234567890";
delchar(s, '5');
将是segfault,但是这(数据在堆上):
char *s;
s = malloc(1024);
strcpy(s, "1234567890");
delchar(s, '5');
不会。
要修复,我不会触及现有的char *
,而是分配一个新的字符,复制除了要从中删除的字符之外的每个字符(注意:代码未经过测试,但是你得到这个想法。
char *delchar(const char *s, char c) {
char *n, *p = calloc(strlen(s)+1, 1);
n = p;
while (*s != '\0') {
if (*s != c) {
*n = *s;
n++;
}
s++;
}
return p;
}
代码更清晰,更易于阅读,而且您无法触及现有字符串。别忘了free()
当然的结果。
答案 2 :(得分:-1)
从字符串中删除所有字符的典型算法是:
void remove_ch (char* restrict dest, const char* restrict src, char ch)
{
while(*src != '\0')
{
if(*src != ch)
{
*dest = *src;
src++;
}
dest++;
}
*dest = '\0';
}
要进行就地删除,您必须重写此功能。删除restrict
并考虑使用临时char
内存位置,因为重叠内存区域之间的复制可能会调用未定义的行为。
完成修改后,您应该能够传递与dest
和src
相同的参数。