删除空格后的垃圾输出
garbage output after whitespace removing
我有这个代码:
int i =0;
char * str = "ar bitrary whitespace";
int whitespace=0,index;
for(index = 0;index < strlen(str);index++)
{
if(isspace(str[index]) != 0)
{
whitespace++;
}
}
char * tmp = (char *)calloc(strlen(str)-whitespace +1,sizeof(char));
memset(tmp,'[=10=]',strlen(tmp)+1);
while(i < strlen(str))
{
if(isspace(str[i]) != 0)
{
i++;
continue;
}else if(isspace(str[i]) == 0)
{
strcat(tmp,&str[i]);
i++;
}
}
printf("\nnew string is: %s \n",tmp);
问题是输出是一个没有删除空格的字符串+一些垃圾字符。
我已经使用 memset 来 null 终止 tmp,有问题吗?
我不会看你的问题,你肯定会覆盖'[=12=]'
终止符。
既然我看了你的问题,看来你需要更好地理解字符串和数组,
- 永远不要写
while (i < strlen(str))
- 不要使用
strcat()
添加单个字符,您显然确实覆盖了那里的 '[=12=]'
。此外,永远不要使用 strcat()
来连接多个字符串。
也值得注意,
你 memset()
在 calloc()
之后已经初始化为 0
。这意味着您正在执行一些不必要的事情,并且尝试了两次,就好像第一次失败了一样,我可以保证它没有。
事实上,既然你已经使用了calloc()
并且tmp
指向的所有字节都是0
那么strlen(tmp)
将return 0
,因此您的 memset()
等同于
tmp[0] = '[=10=]';
你真的不需要初始化 tmp
除非你最终从 str
.
复制实际字节
我总是建议不要 calloc()
字符串,因为
- 你真的不需要对某些东西进行两次初始化。
- 您应该确保您的代码确实考虑了终止
'[=12=]'
,而不是因为您 calloc()
就简单地假设它在那里。这是一个你用 calloc()
隐藏的错误,但它会在某个时候出现。
试试这个,看看你能不能理解我改变的原因
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int main(void)
{
int whitespace;
int length;
char *str = "ar bitrary whitespace";
char *tmp;
whitespace = 0;
for (length = 0; str[length] != '[=11=]'; ++length) {
if (isspace(str[length]) != 0) {
whitespace++;
}
}
tmp = malloc(length - whitespace + 1);
if (tmp == NULL)
return -1;
for (int i = 0, j = 0; str[i] != '[=11=]'; ++i) {
if (isspace(str[i]) != 0)
continue;
tmp[j++] = str[i];
}
tmp[length - whitespace] = '[=11=]';
printf("new string is: %s\n",tmp);
free(tmp);
return 0;
}
这是你的问题
memset(tmp,'[=10=]',strlen(tmp)+1);
strlen(tmp)
通过在 tmp
中寻找 '[=12=]'
来工作,这里是先有鸡还是先有蛋的情况。
你不应该以任何方式进行 memset,只需在完成复制后添加 '[=12=]'
并且不要使用 strcat
,而是维护一个指向 tmp
的指针,只需执行 *p = str[i]
然后递增 p
源字符串的长度可以在这个循环之前计算出来
for(index = 0;index < strlen(str);index++)
否则,如果代码不会被优化,函数 strlen
将在循环的每次迭代中被调用。事实上,使用该功能对于这样的任务来说是多余的。
此声明
memset(tmp,'[=11=]',strlen(tmp)+1);
没有意义,因为 calloc
的调用已经用零初始化了内存。
此声明
strcat(tmp,&str[i]);
还会从源字符串中复制位置 i
之后的空格。因此它可以写入超出为指针指向的数组分配的内存 tmp
.
您可以编写一个单独的函数,看起来就像这个演示程序中显示的那样
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
char * remove_blanks( const char *s )
{
size_t n = 0;
const char *p = s;
do
{
if ( !isspace( ( unsigned char )*p ) ) ++n;
} while ( *p++ );
char *t = malloc( n );
if ( t )
{
char *q = t;
p = s;
do
{
if ( !isspace( ( unsigned char )*p ) ) *q++ = *p;
} while ( *p++ );
}
return t;
}
int main(void)
{
char * str = "ar bitrary whitespace";
printf( "\"%s\"\n", str );
char *t = remove_blanks( str );
printf( "\"%s\"\n", t );
free( t );
}
程序输出为
"ar bitrary whitespace"
"arbitrarywhitespace"
我有这个代码:
int i =0;
char * str = "ar bitrary whitespace";
int whitespace=0,index;
for(index = 0;index < strlen(str);index++)
{
if(isspace(str[index]) != 0)
{
whitespace++;
}
}
char * tmp = (char *)calloc(strlen(str)-whitespace +1,sizeof(char));
memset(tmp,'[=10=]',strlen(tmp)+1);
while(i < strlen(str))
{
if(isspace(str[i]) != 0)
{
i++;
continue;
}else if(isspace(str[i]) == 0)
{
strcat(tmp,&str[i]);
i++;
}
}
printf("\nnew string is: %s \n",tmp);
问题是输出是一个没有删除空格的字符串+一些垃圾字符。 我已经使用 memset 来 null 终止 tmp,有问题吗?
我不会看你的问题,你肯定会覆盖'[=12=]'
终止符。
既然我看了你的问题,看来你需要更好地理解字符串和数组,
- 永远不要写
while (i < strlen(str))
- 不要使用
strcat()
添加单个字符,您显然确实覆盖了那里的'[=12=]'
。此外,永远不要使用strcat()
来连接多个字符串。
也值得注意,
你
memset()
在calloc()
之后已经初始化为0
。这意味着您正在执行一些不必要的事情,并且尝试了两次,就好像第一次失败了一样,我可以保证它没有。事实上,既然你已经使用了
calloc()
并且tmp
指向的所有字节都是0
那么strlen(tmp)
将return0
,因此您的memset()
等同于tmp[0] = '[=10=]';
你真的不需要初始化
tmp
除非你最终从str
. 复制实际字节
我总是建议不要 calloc()
字符串,因为
- 你真的不需要对某些东西进行两次初始化。
- 您应该确保您的代码确实考虑了终止
'[=12=]'
,而不是因为您calloc()
就简单地假设它在那里。这是一个你用calloc()
隐藏的错误,但它会在某个时候出现。
试试这个,看看你能不能理解我改变的原因
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int main(void)
{
int whitespace;
int length;
char *str = "ar bitrary whitespace";
char *tmp;
whitespace = 0;
for (length = 0; str[length] != '[=11=]'; ++length) {
if (isspace(str[length]) != 0) {
whitespace++;
}
}
tmp = malloc(length - whitespace + 1);
if (tmp == NULL)
return -1;
for (int i = 0, j = 0; str[i] != '[=11=]'; ++i) {
if (isspace(str[i]) != 0)
continue;
tmp[j++] = str[i];
}
tmp[length - whitespace] = '[=11=]';
printf("new string is: %s\n",tmp);
free(tmp);
return 0;
}
这是你的问题
memset(tmp,'[=10=]',strlen(tmp)+1);
strlen(tmp)
通过在 tmp
中寻找 '[=12=]'
来工作,这里是先有鸡还是先有蛋的情况。
你不应该以任何方式进行 memset,只需在完成复制后添加 '[=12=]'
并且不要使用 strcat
,而是维护一个指向 tmp
的指针,只需执行 *p = str[i]
然后递增 p
源字符串的长度可以在这个循环之前计算出来
for(index = 0;index < strlen(str);index++)
否则,如果代码不会被优化,函数 strlen
将在循环的每次迭代中被调用。事实上,使用该功能对于这样的任务来说是多余的。
此声明
memset(tmp,'[=11=]',strlen(tmp)+1);
没有意义,因为 calloc
的调用已经用零初始化了内存。
此声明
strcat(tmp,&str[i]);
还会从源字符串中复制位置 i
之后的空格。因此它可以写入超出为指针指向的数组分配的内存 tmp
.
您可以编写一个单独的函数,看起来就像这个演示程序中显示的那样
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
char * remove_blanks( const char *s )
{
size_t n = 0;
const char *p = s;
do
{
if ( !isspace( ( unsigned char )*p ) ) ++n;
} while ( *p++ );
char *t = malloc( n );
if ( t )
{
char *q = t;
p = s;
do
{
if ( !isspace( ( unsigned char )*p ) ) *q++ = *p;
} while ( *p++ );
}
return t;
}
int main(void)
{
char * str = "ar bitrary whitespace";
printf( "\"%s\"\n", str );
char *t = remove_blanks( str );
printf( "\"%s\"\n", t );
free( t );
}
程序输出为
"ar bitrary whitespace"
"arbitrarywhitespace"