我想在不使用任何预定义函数的情况下删除 C 中字符串中的多余空格。
这是我的代码:
但仍然在 XYZ 之后打印一个额外的空间。
有没有更好的方法请分享
#include <stdio.h>
#include <string.h>
int main() {
char str[30] = " abcdef abc xyz ";
int l = strlen(str),n=0;
printf("("); // added for clarity
for(int i=0;i<l;i++)
{
if(str[i]==' ')
{
n++;
if(i==0 || i==l-1)
{
continue;
}
else
{
if(n>1)
{
continue;
}
else{
printf("%c",str[i]);
}
}
}
else{
n=0;
printf("%c",str[i]);
}
}
printf(")\n"); // added for clarity
return 0;
}
程序输出为
(abcdef abc xyz )
预期产出是
(abcdef abc xyz)
每次当
n
等于1
且i
不等于0
或l-1
时,你的程序总是输出一个空格。因此将始终输出一个尾随空格(如果至少有两个尾随空格)。
还有许多 continue 语句使您的代码过于复杂。
并且使用标准字符串函数
strlen
是多余的。
始终尝试编写更通用的代码。那就是你可以编写一个单独的函数,可以调用任何字符串来输出它。
这里有一个演示程序。
#include <stdio.h>
void output_string( const char *s )
{
int space = 0;
for ( ; *s != '\0'; ++s )
{
if (*s != ' ')
{
if (space) putchar( ' ' );
putchar( *s );
space = s[1] == ' ';
}
}
}
int main( void )
{
putchar( '(' );
output_string( " abcdef abc xyz " );
printf( ")\n" );
}
程序输出为
(abcdef abc xyz)
如果包含制表符的处理功能会更通用
'\t'
.
为此,包含标题
<ctype.h>
并更改此语句就足够了
space = s[1] == ' ';
到
space = isblank( ( unsigned char )s[1] );
如您所见,该函数没有 continue 语句。如果可能,您应该避免使用 continue 语句。通常使用 continue 语句会使程序的可读性降低。
你的代码的目标是做两件事。
你的程序逻辑处理 1) 很好。它还可以在开始时提供空格。但是,它不处理末尾的空格。这是因为您不知道空格序列的开头是否是结尾序列,所以您在知道它是结尾序列之前就打印了空格。
解决这个问题的最好方法是“预处理”,即查看循环之前的字符串并找到第一个非空格字符。并查看字符串并找到最后一个非空格字符(从末尾开始向后移动。)
现在您可以使用您展示的算法处理从起始位置到结束位置的字符,它会起作用。
帽子提示:@weather vane 的评论,说的是同样的事情,但没有像这个答案那样解释。
strlen
l
的类型错误(应该是size_t
)char *trimAndStrip(char *str, char ch)
{
char *head = str, *tail = str;
if(str)
{
while(*tail == ch) tail++;
while(*tail)
{
if(*tail != ch) *head++ = *tail++;
else
{
*head++ = *tail++;
while(*tail == ch) tail++;
}
}
if(head > str && *head == ch) head--;
*head = 0;
}
return str;
}
int main(void)
{
char str[] = " abcdef abc xyz ";
char str1[] = "abcdefxyz";
char str2[] = " ";
char str3[] = "";
printf("\"%s\"\n", trimAndStrip(str, ' '));
printf("\"%s\"\n", trimAndStrip(str1, ' '));
printf("\"%s\"\n", trimAndStrip(str2, ' '));
printf("\"%s\"\n", trimAndStrip(str3, ' '));
}