从C中的string中删除空格?

什么是从C中的string中删除空格的最简单和最有效的方法?

最简单和最高效的通常不会在一起…

这是一个可能的解决scheme(未经testing):

void RemoveSpaces(char* source) { char* i = source; char* j = source; while(*j != 0) { *i = *j++; if(*i != ' ') i++; } *i = 0; } 

这是一个非常紧凑,但完全正确的版本:

 do while(isspace(*s)) s++; while(*d++ = *s++); 

在这里,仅仅为了我的娱乐,代码高尔夫版本并不完全正确,并且让评论者不高兴。

如果你可能会冒一些未定义的行为,并且从来没有空的string,你可以摆脱身体:

 while(*(d+=!isspace(*s++)) = *s); 

哎呀,如果是空间,你的意思就是空间性格:

 while(*(d+=*s++!=' ')=*s); 

不要在生产中使用它:)

正如我们从贴出的答案中可以看到的,这是令人惊讶的不是一件小事。 当面对这样的任务时,似乎很多程序员select把常识放在窗口外面,以便产生他们可能想出的最难懂的片段。

需要考虑的事项:

  • 您将需要制作一个string的副本,删除空格。 修改传递的string是不好的做法,它可能是一个string文字。 而且,有时将string视为不可变的对象也是有好处的。
  • 您不能假定源string不是空的。 它可能只包含一个空终止字符。
  • 调用函数时,目标缓冲区可以包含任何未初始化的垃圾。 检查它为空终止没有任何意义。
  • 源代码文档应该声明目标缓冲区需要足够大以包含修剪的string。 最简单的方法就是使它与未修剪的string一样大。
  • 当函数完成时,目标缓冲区需要保留一个以空字符结尾的string,并且没有空格。
  • 考虑如果你想删除所有的空白字符或只是空格' '
  • C程序devise并不是谁可以尽可能多地挤入尽可能多的操作员的竞争。 恰恰相反,一个好的C程序包含可读代码(总是最重要的质量),而不牺牲程序的效率(有点重要)。
  • 因为这个原因,你没有获得奖励积分来隐藏插入目标string的空终止,通过让它成为复制代码的一部分。 相反,要明确地使空终止插入,以表明你不是偶然得到正确的。

我会做什么:

 void remove_spaces (char* restrict str_trimmed, const char* restrict str_untrimmed) { while (*str_untrimmed != '\0') { if(!isspace(*str_untrimmed)) { *str_trimmed = *str_untrimmed; str_trimmed++; } str_untrimmed++; } *str_trimmed = '\0'; } 

在此代码中,源string“str_untrimmed”保持不变,这是通过使用适当的const正确性来保证的。 它不会崩溃,如果源string不包含任何东西,但空终止。 它始终为空终止目标string。

内存分配留给调用者。 algorithm只应该专注于做预期的工作。 它删除所有的空格。

代码中没有微妙的技巧。 它不会试图在一条线上挤入尽可能多的运营商。 这将是一个非常差的候选人的IOCCC 。 然而,它将产生与更为晦涩的单线版本相同的机器码。

当复制某些东西的时候,你可以通过声明两个指针作为restrict来进行优化,这是程序员和编译器之间的契约,程序员保证目的地和源地址不是相同的地址(或者说他们的数据指向只能通过该指针访问,而不是通过其他指针)。 这样可以实现更高效的优化,因为编译器可以直接从源文件复制到目标文件,而无需临时内存。

在C中,你可以replace一些string,例如strdup()返回的string:

 char *str = strdup(" abc "); char *write = str, *read = str; do { if (*read != ' ') *write++ = *read; } while (*read++); printf("%s\n", str); 

其他string是只读的,例如那些在代码中声明的string。 您必须将这些内容复制到新分配的内存区域,并通过跳过空格来填充副本:

 char *oldstr = " abc "; char *newstr = malloc(strlen(oldstr)+1); char *np = newstr, *op = oldstr; do { if (*op != ' ') *np++ = *op; } while (*op++); printf("%s\n", newstr); 

你可以看到为什么人们发明了其他语言;)

 #include <ctype> char * remove_spaces(char * source, char * target) { while(*source++ && *target) { if (!isspace(*source)) *target++ = *source; } return target; } 

笔记;

  • 这不处理Unicode。

如果你仍然感兴趣,这个函数从string的开始处删除空格,而我只是在我的代码中工作:

 void removeSpaces(char *str1) { char *str2; str2=str1; while (*str2==' ') str2++; if (str2!=str1) memmove(str1,str2,strlen(str2)+1); } 

从string中删除空格的最简单最有效的方法是简单地从string中删除空格。 例如,使用你的编辑器"hello world""helloworld"查找和replace"hello world" "helloworld" ,然后!

好吧,我知道这不是你的意思。 不是所有的string都来自string文字,对吗? 假设这个string,你想要从空格中删除不是来自string文字,我们需要考虑你的string的来源和目的地…我们需要考虑你的整个algorithm,你想要解决什么样的实际问题 ,在为了提出最简单和最优化的方法。

也许你的string来自一个文件(例如stdin ),并被绑定到另一个文件(如stdout )。 如果是这样的话,我会质疑为什么它首先需要成为一个string。 只要把它看作是一个人物stream,当你碰到他们的时候丢弃这个空间……

 #include <stdio.h> int main(void) { for (;;) { int c = getchar(); if (c == EOF) { break; } if (c == ' ') { continue; } putchar(c); } } 

通过消除string存储的需要,不仅整个程序变得非常短,而且在理论上也更有效率。

 #include<stdio.h> #include<string.h> main() { int i=0,n; int j=0; char str[]=" Nar ayan singh "; char *ptr,*ptr1; printf("sizeof str:%ld\n",strlen(str)); while(str[i]==' ') { memcpy (str,str+1,strlen(str)+1); } printf("sizeof str:%ld\n",strlen(str)); n=strlen(str); while(str[n]==' ' || str[n]=='\0') n--; str[n+1]='\0'; printf("str:%s ",str); printf("sizeof str:%ld\n",strlen(str)); } 

我假设Cstring是在一个固定的内存,所以如果你replace空格,你必须移动所有字符。

最简单的似乎是创build新的string并遍历原始的string,只复制非空格字符。

这是我能想到的最简单的(testing),它的工作原理!

 char message[50]; fgets(message, 50, stdin); for( i = 0, j = 0; i < strlen(message); i++){ message[ij] = message[i]; if(message[i] == ' ') j++; } message[i] = '\0'; 

我遇到了这个问题的一个变化,你需要减less多个空间到一个空间“代表”的空间。

这是我的解决scheme:

 char str[] = "Put Your string Here....."; int copyFrom = 0, copyTo = 0; printf("Start String %s\n", str); while (str[copyTo] != 0) { if (str[copyFrom] == ' ') { str[copyTo] = str[copyFrom]; copyFrom++; copyTo++; while ((str[copyFrom] == ' ') && (str[copyFrom] !='\0')) { copyFrom++; } } str[copyTo] = str[copyFrom]; if (str[copyTo] != '\0') { copyFrom++; copyTo++; } } printf("Final String %s\n", str); 

希望它有助于:-)

取自zString库的代码

 /* search for character 's' */ int zstring_search_chr(char *token,char s){ if (!token || s=='\0') return 0; for (;*token; token++) if (*token == s) return 1; return 0; } char *zstring_remove_chr(char *str,const char *bad) { char *src = str , *dst = str; /* validate input */ if (!(str && bad)) return NULL; while(*src) if(zstring_search_chr(bad,*src)) src++; else *dst++ = *src++; /* assign first, then incement */ *dst='\0'; return str; } 

代码示例

  Exmaple Usage char s[]="this is a trial string to test the function."; char *d=" ."; printf("%s\n",zstring_remove_chr(s,d)); Example Output thisisatrialstringtotestthefunction 

在zString代码中有一个llok,你可能会觉得它有用https://github.com/fnoyanisi/zString