C正在删除字符串中的字符



现在我使用这段代码来删除字符串中的一些字符。

void eliminate(char *str, char ch){
for(; *str != '';str++){
if(*str == ch){
strcpy(str, str+1);
str--;
}
}
}

在char*str中有一些类似的字符串

"sll $6, $5, 16"

在删除"$&";,绳子看起来像这样。

"sll 6, 5, 16"

但是在删除"之后&";,绳子变得很奇怪。

"sll 6 5 6"

上面的代码有问题吗?而且,它只发生在Linux和在线GDB中。我的windows笔记本电脑中的VS代码很好地消除了目标字符。

正如注释中所指出的,strcpy()在处理具有重叠内存块的数据时是不安全的。CCD_ 5是在CCD_;dst内存重叠。

您可以简单地跳过要在循环中消除的字符:

#include <stdio.h>
void drop_char (char *str, char ch) {
if (!str) return;
for(char* cp = str; 1 ; ) {
if(*cp != ch)
*str++ = *cp;
if ('' == *cp++)
break;
}
}
int main () {
char str [] = "sll     $6, $5, 16";
printf ("Original   : [%s]", str);
drop_char(str, '$');
printf ("nDropping $ : [%s]", str);
drop_char(str, ',');
printf ("nDropping , : [%s]", str);
printf ("n");
return 0;
}

在不使用显式指针数学的情况下,我们可以在迭代输入字符串时使用两个索引。i是每次迭代都有增量的索引,而j只有在找到而没有的目标字符时才递增。

void drop_char(char *str, char ch) {
size_t i = 0, j = 0;    
for (; str[i]; ++i) {
if (str[i] != ch) 
str[j++] = str[i];
}
str[j] = '';
}

如果我们有字符串char test[] = "hello"并调用drop_char(test, 'l'),则过程看起来像:

i = 0, j = 0
char: 'h'
'h' != 'l'
test[0] = 'h'
i = 1, j = 1
char: 'e'
'e' != 'l'
test[1] = 'e'
i = 2, j = 2
char: 'l'
'l' == 'l'
i = 3, j = 2
char: 'l'
'l' == 'l'
i = 4, j = 2
char: 'o'
'o' != 'l'
test[2] = 'o'
i = 5, j = 3
test[3] = ''

对于像本语句中那样使用函数strcpy处理重叠字符串的初学者

strcpy(str, str+1);

调用未定义的行为。

来自C标准(7.23.2.3 strcpy函数(

2 strcpy函数复制s2指向的字符串(包括终止的null字符(插入s1所指向的数组中如果复制发生在重叠的对象之间,行为是未定义

此语句

str--;

当删除的字符是字符串的第一个字符时,也可以调用未定义的行为。

关于函数声明的一些备注。

这样的函数应该遵循C标准字符串函数的一般约定,并返回指向结果字符串的指针。

另一个通用约定是,这样的函数不检查传递的指针是否等于NULL。函数的用户有责任将有效指针传递给字符串。

此外,如果用户将''作为要删除的字符传递,则函数将不处理源字符串,只返回它。

下面是一个演示程序,展示了如何声明和定义函数。

#include <stdio.h>
char * eliminate( char *s, char c )
{
if ( c != '' )
{
char *src = s, *dsn = s;
do
{
if ( *src != c )
{
if ( dsn != src ) *dsn = *src;
++dsn;
}
} while ( *src++ );
}
return s;
}
int main( void )
{
char s[] = "sll     $6, $5, 16";
printf( ""%s"n", eliminate( s, '$') );
}

程序输出为

"sll     6, 5, 16"

相关内容

  • 没有找到相关文章

最新更新