您的函数实现存在四个主要问题。
第一个是该函数按值接受指向源字符串的指针。即参数cad 由用作参数的指针的值初始化。因此更改变量cad 不会影响原始指针。
第二个是你没有检查realloc的调用是否成功。因此,该函数可以调用未定义的行为。
第三个是每次追加新字符时重新分配字符串效率低。
最后第四个是结果动态分配的数组不包含字符串,因为您忘记附加终止零字符'\0'。
如果您想在函数内更改原始指针的值,您应该从函数返回函数中获得的结果指针并将其分配给调用者中的原始指针。或者您应该通过引用将原始指针传递给函数。在 C 中,通过引用传递意味着通过指向对象的指针间接传递对象(可以是指针)。
这是一个演示程序,显示了当函数通过引用接受原始指针时的函数实现。
该函数还返回一个指向结果字符串的指针,可以在调用者中检查函数内动态内存的重新分配是否成功。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * remove_char( char **s, char c )
{
char * result = *s;
if ( c != '\0' )
{
char *dsn = *s;
const char *src = *s;
do
{
if ( *src != c )
{
if ( dsn != src )
{
*dsn = *src;
}
++dsn;
}
} while ( *src++ );
char *tmp = realloc( *s, ( dsn - *s ) * sizeof( char ) );
if( tmp != NULL ) *s = tmp;
result = tmp;
}
return result;
}
int main(void)
{
char *s = malloc( 12 );
strcpy( s, "H#e#l#l#o!" );
puts( s );
if ( remove_char( &s, '#' ) ) puts( s );
free( s );
return 0;
}
程序输出是
H#e#l#l#o!
Hello!
另一种方法是编写一个函数,它不会更改源字符串,而是动态创建一个新字符串,该字符串包含源字符串,但不包括指定的字符。这样的函数更加灵活,因为您可以使用字符串文字来调用它。如果源字符串也是动态分配的,那么函数的调用者在成功调用后就可以释放源字符串。
这是一个演示程序。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * remove_copy( const char *s, char c )
{
size_t src_len = strlen( s );
size_t dsn_len = src_len;
if ( c != '\0' )
{
for ( const char *p = s; ( p = strchr( p, c ) ) != NULL; ++p )
{
--dsn_len;
}
}
char *result = malloc( ( dsn_len + 1 ) * sizeof( char ) );
if ( result != NULL )
{
const char *src_s = s;
char *dsn_s = result;
if ( dsn_len != src_len )
{
for ( const char *p = src_s;
( p = strchr( src_s, c ) ) != NULL;
src_s = p + 1 )
{
if ( p - src_s != 0 )
{
memcpy( dsn_s, src_s, p - src_s );
dsn_s += p - src_s;
}
}
}
strcpy( dsn_s, src_s );
}
return result;
}
int main(void)
{
char s[] = "H#e#l#l#o!";
puts( s );
char *p = remove_copy( s, '#' );
if ( p != NULL ) puts( p );
free( p );
return 0;
}
程序输出与前面演示程序显示的相同
H#e#l#l#o!
Hello!