49

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

4

16 回答 16

100

最简单和最有效的通常不会一起使用……</p>

这是就地删除的可能解决方案:

void remove_spaces(char* s) {
    char* d = s;
    do {
        while (*d == ' ') {
            ++d;
        }
    } while (*s++ = *d++);
}
于 2009-11-13T00:11:23.447 回答
19

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

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

在这里,只是为了我的消遣,是不完全正确的代码版本,让评论者感到不安。

如果你可以冒险一些未定义的行为,并且永远不会有空字符串,你可以摆脱身体:

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

哎呀,如果你用空格表示空格字符:

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

不要在生产中使用它:)

于 2009-11-13T00:30:31.087 回答
17

正如我们从发布的答案中看到的那样,这令人惊讶地不是一项微不足道的任务。当面对这样的任务时,似乎许多程序员选择将常识抛到窗外,以便产生他们可能想出的最晦涩的片段。

需要考虑的事项:

  • 您将需要制作字符串的副本,并删除空格。修改传递的字符串是不好的做法,它可能是字符串文字。此外,有时将字符串视为不可变对象也有好处。
  • 您不能假设源字符串不为空。它可能只包含一个空终止字符。
  • 调用函数时,目标缓冲区可以包含任何未初始化的垃圾。检查它是否为空终止没有任何意义。
  • 源代码文档应说明目标缓冲区需要足够大以包含修剪后的字符串。最简单的方法是使其与未修剪的字符串一样大。
  • 函数完成后,目标缓冲区需要保存一个以空字符结尾且没有空格的字符串。
  • 考虑是否要删除所有空白字符或仅删除空格' '
  • C 编程并不是关于谁能在一条线路上挤入尽可能多的运算符的竞争。恰恰相反,一个好的 C 程序包含可读的代码(始终是最重要的品质)而不牺牲程序效率(有些重要)。
  • 出于这个原因,通过让它成为复制代码的一部分,您不会因为隐藏目标字符串的空终止插入而获得奖励积分。相反,使空终止插入显式,以表明您不是偶然成功地把它弄对了。

我会做什么:

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';
}

在此代码中,源字符串“str_untrimmed”保持不变,这是通过使用适当的 const 正确性来保证的。如果源字符串只包含一个空终止符,它不会崩溃。它总是 null 终止目标字符串。

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

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

但是,在复制某些内容时,您可以通过将两个指针声明为 来进行一些优化restrict,这是程序员和编译器之间的合同,程序员保证目标和源不是相同的地址。这允许更有效的优化,因为编译器可以直接从源复制到目标,而无需中间的临时内存。

于 2015-05-21T11:40:12.723 回答
9

在 C 中,您可以就地替换一些字符串,例如 strdup() 返回的字符串:

char *str = strdup(" a b c ");

char *write = str, *read = str;
do {
   if (*read != ' ')
       *write++ = *read;
} while (*read++);

printf("%s\n", str);

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

char *oldstr = " a b c ";

char *newstr = malloc(strlen(oldstr)+1);
char *np = newstr, *op = oldstr;
do {
   if (*op != ' ')
       *np++ = *op;
} while (*op++);

printf("%s\n", newstr);

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

于 2009-11-13T00:18:16.680 回答
2
#include <ctype>

char * remove_spaces(char * source, char * target)
{
     while(*source++ && *target)
     {
        if (!isspace(*source)) 
             *target++ = *source;
     }
     return target;
}

笔记;

  • 这不处理 Unicode。
于 2009-11-13T00:12:57.750 回答
2

如果你仍然感兴趣,这个函数会从字符串的开头删除空格,我只是让它在我的代码中工作:

void removeSpaces(char *str1)  
{
    char *str2; 
    str2=str1;  
    while (*str2==' ') str2++;  
    if (str2!=str1) memmove(str1,str2,strlen(str2)+1);  
}
于 2013-06-23T08:14:50.570 回答
1
#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));
}
于 2014-04-03T06:20:13.000 回答
1

从字符串中删除空格的最简单最有效的方法是简单地从字符串文字中删除空格。例如,使用您的编辑器用 , 和 presto 来“查找和替换"hello world""helloworld"

好吧,我知道你不是这个意思。并非所有字符串都来自字符串文字,对吗?假设您希望从中删除空格的字符串不是来自字符串文字,我们需要考虑字符串的来源和目的地......我们需要考虑您的整个算法,您要解决的实际问题是什么为了建议最简单和最优化的方法。

也许您的字符串来自一个文件(例如stdin)并且一定会被写入另一个文件(例如stdout)。如果是这样的话,我会质疑为什么它首先需要成为一个字符串。把它当作一个字符流来对待,当你遇到它们时丢弃空格......

#include <stdio.h>

int main(void) {
    for (;;) {
        int c = getchar();
        if (c == EOF) { break;    }
        if (c == ' ') { continue; }
        putchar(c);
    }
}

通过消除存储字符串的需要,不仅整个程序变得非常短,而且理论上也更加高效。

于 2015-05-21T09:44:43.110 回答
0

取自 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 代码,你会发现它很有用 https://github.com/fnoyanisi/zString

于 2016-02-18T23:46:35.377 回答
0

这是我能想到的最简单的方法(已测试)并且有效!!

char message[50];
fgets(message, 50, stdin);
for( i = 0, j = 0; i < strlen(message); i++){
        message[i-j] = message[i];
        if(message[i] == ' ')
            j++;
}
message[i] = '\0';
于 2016-12-26T07:30:29.480 回答
0

这是我能想到的最简单的事情。请注意,该程序使用第二个命令行参数(argv[1])作为删除空格的行。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/*The function itself with debug printing to help you trace through it.*/

char* trim(const char* str)
{
    char* res = malloc(sizeof(str) + 1);
    char* copy = malloc(sizeof(str) + 1);
    copy = strncpy(copy, str, strlen(str) + 1);
    int index = 0;

    for (int i = 0; i < strlen(copy) + 1; i++) {
        if (copy[i] != ' ')
        {
            res[index] = copy[i];
            index++;
        }
        printf("End of iteration %d\n", i);
        printf("Here is the initial line: %s\n", copy);
        printf("Here is the resulting line: %s\n", res);
        printf("\n");
    }
    return res;
}

int main(int argc, char* argv[])
{
    //trim function test

    const char* line = argv[1];
    printf("Here is the line: %s\n", line);

    char* res = malloc(sizeof(line) + 1);
    res = trim(line);

    printf("\nAnd here is the formatted line: %s\n", res);

    return 0;
}
于 2020-04-24T15:05:03.483 回答
0
/* Function to remove all spaces from a given string.
   https://www.geeksforgeeks.org/remove-spaces-from-a-given-string/
*/
void remove_spaces(char *str)
{
    int count = 0;
    for (int i = 0; str[i]; i++)
        if (str[i] != ' ')
            str[count++] = str[i];
    str[count] = '\0';
}
于 2021-04-25T16:39:03.733 回答
0

这是在微控制器中实现的,它可以工作,它应该避免所有问题,这不是一个聪明的方法,但它会工作:)

void REMOVE_SYMBOL(char* string, uint8_t symbol)
{
  uint32_t size = LENGHT(string); // simple string length function, made my own, since original does not work with string of size 1
  uint32_t i = 0;
  uint32_t k = 0;
  uint32_t loop_protection = size*size; // never goes into loop that is unbrakable
  while(i<size)
  {
    if(string[i]==symbol)
    {
      k = i;
      while(k<size)
      {
        string[k]=string[k+1];
        k++;
      }
    }
    if(string[i]!=symbol)
    {
      i++;
    }
    loop_protection--;
    if(loop_protection==0)
    {
      i = size;
      break;
    }
  }
}
于 2021-06-09T19:57:47.330 回答
0

虽然这不像其他答案那么简洁,但对于 C 的新手来说,这很容易理解,改编自 Calculix 源代码。

char* remove_spaces(char * buff, int len)
{
    int i=-1,k=0;
    while(1){
        i++;
        if((buff[i]=='\0')||(buff[i]=='\n')||(buff[i]=='\r')||(i==len)) break;
        if((buff[i]==' ')||(buff[i]=='\t')) continue;
        buff[k]=buff[i];
        k++;
    }
    buff[k]='\0';
    return buff;
}
于 2021-07-06T04:46:04.560 回答
-1

我假设 C 字符串位于固定内存中,因此如果替换空格,则必须移动所有字符。

最简单的似乎是创建新字符串并迭代原始字符串并仅复制非空格字符。

于 2009-11-13T00:14:23.473 回答
-1

我遇到了这个问题的一个变体,你需要将多个空格减少到一个空格“代表”这些空格。

这是我的解决方案:

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);

希望能帮助到你 :-)

于 2017-04-08T19:44:12.577 回答