从C中删除字符串中的空格?

时间:2009-11-13 00:06:24

标签: c string spaces

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

17 个答案:

答案 0 :(得分:72)

最简单,最有效率通常不会一起......

这是一个可能的解决方案(未经测试):

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

答案 1 :(得分:16)

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

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

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

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

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

哎呀,如果按空间你只是指空间角色:

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

不要在生产中使用它:)

答案 2 :(得分:10)

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

需要考虑的事项:

  • 您需要复制字符串,并删除空格。修改传递的字符串是不好的做法,它可能是一个字符串文字。此外,将字符串视为immutable objects有时会带来好处。
  • 您不能假设源字符串不为空。它可能只包含一个空终止字符。
  • 调用函数时,目标缓冲区可以包含任何未初始化的垃圾。检查它是否为空终止没有任何意义。
  • 源代码文档应说明目标缓冲区需要足够大以包含修剪后的字符串。最简单的方法是使其与未修剪的字符串一样大。
  • 当函数完成时,目标缓冲区需要保存一个没有空格的空终止字符串。
  • 考虑您是要删除所有空格字符还是仅删除空格' '
  • C编程不是一场竞争,因为谁可以尽可能多地挤压一条线路上的运营商。相反,一个好的C程序包含可读代码(总是最重要的质量),而不会牺牲程序效率(有些重要)。
  • 因此,通过让它成为复制代码的一部分,您无法获得隐藏目标字符串空终止插入的奖励积分。相反,将null终止插入显式化,以表明您不是偶然设法使其正确。

我会做什么:

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来优化一点,这是程序员和编译器之间的契约,程序员保证目标和源不是同一个地址(或者更确切地说,他们指向的数据只能通过该指针而不是通过其他指针访问。这样可以实现更高效的优化,因为编译器可以直接从源复制到目标,而不需要临时存储器。

答案 3 :(得分:7)

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

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

答案 4 :(得分:2)

#include <ctype>

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

注释;

  • 这不处理Unicode。

答案 5 :(得分:2)

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

好的,我知道那不是你的意思。并非所有字符串都来自字符串文字,对吧?假设你想要删除空格的这个字符串不是来自字符串文字,我们需要考虑字符串的来源和目的地......我们需要考虑你的整个算法,你试图解决的实际问题,以便提出最简单和最优的方法。

也许你的字符串来自一个文件(例如stdin)并且必然会被写入另一个文件(例如stdout)。如果是这种情况,我会质疑为什么它首先需要成为字符串。只是将它视为一个字符串,当你遇到它们时丢弃空格......

#include <stdio.h>

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

通过消除存储字符串的需要,不仅整个程序变得更多,更多更短,但理论上也更有效。

答案 6 :(得分:2)

如果您仍然感兴趣,此函数会从字符串的开头删除空格,我只是在我的代码中使用它:

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

答案 7 :(得分: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));
}

答案 8 :(得分:1)

这是我能想到的最简单的事情。请注意,该程序使用第二个命令行参数(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;
}

答案 9 :(得分:0)

我假设C字符串在固定内存中,所以如果你替换空格,你必须移动所有字符。

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

答案 10 :(得分:0)

这是我能想到的最简单的(TESTED)并且它有效!!

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

答案 11 :(得分:0)

void spaces_be_gone(char *str)
{
    char *p = --str;
    do while (*++p == ' ');
    while (*++str = *p);
}

答案 12 :(得分: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';
}

答案 13 :(得分: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;
    }
  }
}

答案 14 :(得分: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;
}

答案 15 :(得分:-1)

从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

答案 16 :(得分:-1)

我遇到了这个问题的一个变体,你需要将空间减少到一个空间&#34;代表&#34;空间。

这是我的解决方案:

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

希望它有所帮助: - )