在C语言中将字符串中的额外空格去除

3

我有这个字符串

"go    for    goa" 

输出结果应该是

"go for goa"

我希望去除额外的空格。也就是说,两个或者更多连续的空格应该被替换成一个空格。我想使用一个原地算法来完成这个任务。

以下是我尝试过的代码,但它并没有起作用:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Function to remove spaces in an string array */
char *removeSpaces(char *str) {
  int  ip_ind = 1;
  /* In place removal of duplicate spaces*/
  while(*(str + ip_ind)) {
    if ((*(str + ip_ind) == *(str + ip_ind - 1)) && (*(str + ip_ind)==' ')) {
      *(str_ip_ind-1)= *(str + ip_ind);
    }
    ip_ind++;
  }
  /* After above step add end of string*/
  *(str + ip_ind) = '\0';
  return str;
}
/* Driver program to test removeSpaces */
int main() {
  char str[] = "go   for  go";
  printf("%s", removeSpaces(str));
  getchar();
  return 0;
}
8个回答

12

大多数解决方案似乎过于复杂:

#include <ctype.h>
#include <stdio.h>

void strip_extra_spaces(char* str) {
  int i, x;
  for(i=x=0; str[i]; ++i)
    if(!isspace(str[i]) || (i > 0 && !isspace(str[i-1])))
      str[x++] = str[i];
  str[x] = '\0';
}

int main(int argc, char* argv[]) {
  char str[] = "  If  you  gaze   into  the abyss,    the   abyss gazes also   into you.    ";
  strip_extra_spaces(str);
  printf("%s\n",str);
  return 0;
}

@GiorgiMoniava,我已经修复了。 - Victor
很棒的解决方案。 - Tursko
老但依然伟大!谢谢。 - PageMaker

4

我甚至无法理解你的函数试图做什么。首先,在第一次循环中,-1将访问字符串的开始位置之前的位置。尝试使用以下代码:

char *removeSpaces(char *str) {
    char *inp = str, *outp = str;
    int prevSpace = 0;

    while (*inp) {
        if (isspace(*inp)) {
            if (!prevSpace) {
                *outp++ = ' ';
                prevSpace = 1;
            }
        } else {
            *outp++ = *inp;
            prevSpace = 0;
        }
        ++inp;
    }
    *outp = '\0';
    return str;
}

不会的,因为他将ip_ind初始化为1。 - Muthu Ganapathy Nathan

1
你的 if 条件不起作用。我将展示我的代码,它与你的相似,只是使用了两个指针:backfront
如果 front 不是空格,或者 front 是空格但 back 不是空格,你需要将 front 复制到 back+1
char *removeSpaces(char *str)
{
    if (*str == '\0') return str;

    char *back = str;
    char *front = str + 1;
    /* In place removal of duplicate spaces*/
    while(*front != '\0')
    {
        if (*front != ' ' || *back != ' ')    // highlight
            *(++back) = *front;
        front++;
    }

    /* After above step add end of string*/
    *(back + 1) = '\0';

    return str;
}

希望这能对您有所帮助。

1
你没有检查空格.. 你正在检查制表符。用空格替换\t。

1

你希望知道如何找到留有空间的最佳答案吗?这里是一个简单的JavaScript翻译:

function strip_extra_spaces(str) {
  var i, x;
  for (i = x = 0; str[i]; ++i)
    if (!isspace(str[i]) || (i > 0 && !isspace(str[i - 1])))
      str[x++] = str[i];
  str[x] = '\0';
  return str;
}

str = "  If  you  gaze   into  the abyss,    the   abyss gazes also   into you.    ";
console.log(
  strip_extra_spaces(str.split(""))
  .join("")
  .replace(/\0.+/g, "")
  .replace(/\s/g, '☐')
)

function isspace(c) {
  return c == ' ';
}

我在寻找类似的C#代码来比较多个字符串,参考了recursion.ninja和其他类似的C#答案,例如Efficient way to remove ALL whitespace from String?,但这些方法都有问题——会完全删除空格。

public static string TrimAllWithInplaceCharArray(string a) {
    var len = a.Length;
    var srcA = a.ToCharArray();
    int dstIdxA = 0;
    int planSpace = 0;

    for (int i = 0; i < len; ++i) {
        var ch = srcA[i];
        switch (ch) {
            case '\u0020': case '\u00A0': case '\u1680': case '\u2000': case '\u2001':
            case '\u2002': case '\u2003': case '\u2004': case '\u2005': case '\u2006':
            case '\u2007': case '\u2008': case '\u2009': case '\u200A': case '\u202F':
            case '\u205F': case '\u3000': case '\u2028': case '\u2029': case '\u0009':
            case '\u000A': case '\u000B': case '\u000C': case '\u000D': case '\u0085':
                if (planSpace == 1) planSpace = 2;
                break;

            default:
                if (planSpace > 1)
                {
                    srcA[dstIdxA++] = ' ';
                }
                srcA[dstIdxA++] = ch;
                planSpace = 1;
                break;
        }
    }
    return new string(srcA, 0, dstIdxA);
}

0

简单的一个给你

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char a[100];
int i,t,k;
scanf("%[^\n]s",a);
t=strlen(a);
for(i=0;i<t;)
{
    if((a[i]==' ')&&(a[i+1]==' '))
    {
        for(k=i+1;k<t;k++)
        {
            a[k]=a[k+1];
        }
        t=t-1;
    }
    else
        i++;
}
printf("%s",a);
return 0;
}

0

问题:

  1. 你正在跟踪 '\t' 制表符,但你必须删除空格。
  2. 此外,你正在跟踪并查找 '\t',但你没有步骤来删除它(我添加了一个)。
  3. 每次不必增加 ip_ind,只有在未执行删除时才需要增加,因为当删除完成时,该场景将等于增加。
  4. 你的情况将无法处理 "",为避免这种情况,请按照以下方式添加检查参数(方法1),或者从0开始使用 ip_ind(方法2)。 (感谢 @Lee Daniel Crocker)

解决方案:

你可以尝试像这样做。

方法1:ip_ind 从1开始。

/* Function to remove spaces in an string array */
char *removeSpaces(char *str)
{
  int  ip_ind = 1;
  char *ptr;

  if(*str)
    return str;

  /* In place removal of duplicate spaces*/
  while(*(str + ip_ind))
  {
    if ( (*(str + ip_ind) == *(str + ip_ind - 1)) && (*(str + ip_ind)==' ') )
    {
        ptr = str + ip_ind;
        //Functionality for removal of spaces.
        do{
           *(ptr-1) = *ptr;
        }while(*ptr++ != '\0');


    }
    else //Inc only if deletion is not done.
    ip_ind++;
  }

 /* After above step add end of string*/
  *(str + ip_ind) = '\0';

 return str;
}

方法二:ip_ind 从零开始。

char *removeSpaces(char *str)
{
  int  ip_ind = 0;
  char *ptr;
  /* In place removal of duplicate spaces*/
  while(*(str + ip_ind))
  {
    if ( (*(str + ip_ind) == *(str + ip_ind + 1)) && (*(str + ip_ind)==' ') )
    {
        ptr = str + ip_ind+1;

        do{
           *(ptr-1) = *ptr;
        }while(*ptr++ != '\0');


    }
    else
    ip_ind++;
  }

 /* After above step add end of string*/
  *(str + ip_ind) = '\0';

 return str;
}

不使用额外指针ptr,无法解决这个问题吗? - krrishna
@krrishna 不是这样的,因为你指向的是当前位置,你需要 ip_ind 来遍历到末尾至少需要一个变量。在这种情况下,它是 ptr - Muthu Ganapathy Nathan

0

这就是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Function to remove spaces in an string array */
char *removeSpaces(char *str) {
  int  ip_ind = 0;
  while (*(str+ip_ind) != 0) {
    if (*(str + ip_ind++) == 32) {
      if (*(str + ip_ind) == 32) {
        int x=ip_ind;
        while (*(str + x +1) != 0) {
          *(str + x)= *(str + 1 + x++);
        }
        *(str + x)= 0;
        --ip_ind;
      }
    }
  }
  return str;
}
/* Driver program to test removeSpaces */
int main() {
  char str[] = "go   for  go";
  printf("%s\n", str);
  printf("%s\n", removeSpaces(str));
  char str2[] = "go     for  go for go";
  printf("%s\n", str2);
  printf("%s\n", removeSpaces(str2));
  return 0;
}

输出:

dda$ ./a.out
go   for  go
go for go
go     for  go for go
go for go for go
dda$

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接