char * removeChar(char * str, char c){
int len = strlen(str);
int i = 0;
int j = 0;
char * copy = malloc(sizeof(char) * (len + 1));
while(i < len){
if(str[i] != c){
copy[j] = str[i];
j++;
i++;
}else{
i++;
}
}
if(strcmp(copy, str) != 0){
strcpy(str,copy);
}else{
printf("Error");
}
return copy;
}
int main(int argc, char * argv[]){
char str[] = "Input string";
char * input;
input = removeChar(str,'g');
printf("%sn", input);
free(input);
return 0;
}
我不知道为什么每次我尝试运行它时,它总是说未初始化的变量并坚持在 strcpy 行和 printf 行中。
基本上这个函数是获取一个字符串和一个字符,并从字符串中删除该字符(因为我正在学习 malloc,所以这就是我这样编写函数的原因)。
在 while 循环之后执行以下操作:
copy[j] = ' ';
NULL
-终止你的字符串;这样它就可以处理来自<string.h>
的方法,这些方法假定字符串是 NUL 终止的。
PS:你应该看到的一个警告是无论如何都不在你的函数中返回copy
,因为现在如果if语句的条件是错误的,你的函数将不会返回有效的东西,所以添加这个:
return copy;
在函数的末尾(现在已通过编辑进行更正)。
除此之外,您仍然应该得到的唯一警告是针对未使用的参数main()
,没有别的:
prog.c: In function 'main':
prog.c:32:14: warning: unused parameter 'argc' [-Wunused-parameter]
int main(int argc, char * argv[]){
^~~~
prog.c:32:27: warning: unused parameter 'argv' [-Wunused-parameter]
int main(int argc, char * argv[]){
^~~~
当您将字节从str
复制到copy
时,您不会在末尾添加终止空字节。 因此,strcmp
读取的复制字符进入单元化内存,可能超过分配的内存块的末尾。 这将调用未定义的行为。
在while
循环之后,将终止空字节添加到copy
。
此外,如果末尾的if
块为 false,则永远不会返回值。 您需要为此返回一些内容,可能是复制的字符串。
char * removeChar(char * str, char c){
int len = strlen(str);
int i = 0;
int j = 0;
char * copy = malloc(sizeof(char) * (len + 1));
while(i < len){
if(str[i] != c){
copy[j] = str[i];
j++;
i++;
}else{
i++;
}
}
// add terminating null byte
copy[j] = ' ';
if(strcmp(copy, str) != 0){
strcpy(str,copy);
}
// always return copy
return copy;
}
你从未初始化过输入,一些编译器没有注意到, 该值永远不会在行之前使用
input = removeChar(str, 'g');
在您的代码中。因此,他们发出诊断只是为了确定。
strcpy(str, copy)
卡在你的代码中,因为副本从来没有一个结束的 0 字节和 所以取决于你的记忆的非确定性内容在 内存备份副本的分配时刻,strcpy 多长时间 将运行,如果您最终获得 SIGSEGV(或类似)。
strcpy
将循环,直到在您的内存中找到 0 字节。
对于从字符串中删除字符的初学者来说,不需要动态创建字符数组,然后将该数组复制到原始字符串中。
您应该编写一个确实从字符串中删除指定字符的函数,或者编写一个基于源字符串(不包括指定字符)创建新字符串的函数。
这只是一个糟糕的设计,只会让用户感到困惑。那就是函数太复杂了,使用了冗余函数,如malloc
、strlen
、strcmp
和strcpy
。事实上,它有一个不明显的副作用。此外,字符串的长度使用了不正确的类型int
而不是类型size_t
。
至于你的函数实现,那么你忘了将终止零'\0'附加到动态分配数组中构建的字符串中。
如果您确实想从字符串中删除字符,则该函数可以看起来像演示程序中显示的那样。
#include <stdio.h>
char * remove_char(char *s, char c)
{
char *p = s;
while (*p && *p != c) ++p;
for ( char *q = p; *p++; )
{
if (*p != c) *q++ = *p;
}
return s;
}
int main( void )
{
char str[] = "Input string";
puts(str);
puts(remove_char(str, 'g'));
return 0;
}
程序输出为
Input string
Input strin
如果您正在学习malloc
函数并想使用它,则在任何情况下都应尝试实现正确的设计。
若要使用malloc
可以编写一个函数,该函数基于源字符串(不包括指定字符)创建新字符串。例如
#include <stdio.h>
#include <stdlib.h>
char * remove_copy_char(const char *s, char c)
{
size_t n = 0;
for (const char *p = s; *p; ++p)
{
if (*p != c) ++n;
}
char *result = malloc(n + 1);
if (result)
{
char *q = result;
for (; *s; ++s)
{
if (*s != c) *q++ = *s;
}
*q = ' ';
}
return result;
}
int main( void )
{
char *str = "Input string";
puts(str);
char *p = remove_copy_char(str, 'g');
if ( p ) puts(p );
free(p);
return 0;
}
程序输出将与上述相同。
Input string
Input strin
注意函数声明
char * remove_copy_char(const char *s, char c);
^^^^^^
在这种情况下,源字符串可以是字符串文本。
char *str = "Input string";