0

我正在尝试编写一个函数来删除字符串中的空格,我知道我的问题是即使在将下一个字符移动到空格所在的位置之后,我仍然会将该字符复制到其原始位置(我m 重复一个字符两次)。我不太确定如何摆脱那个重复的角色。(即我有“Hello world。”,但我的函数给了我“Hellowworld”。)

void deblank(char str1[], char str2[])
{
   int i, x;

   for (i = 0; str1[i] != '\0'; i++)
   {
      if (str1[i] == ' ')
      {
         x = i + 1;
         str2[i] = str1[x];
      }

      else
      {
         str2[i] = str1[i];
      }
   }

   str2[i] = '\0';
}
4

7 回答 7

1

现在,您只有一个索引,i.

你真的想要两个索引,称它们为iji将成为您的源字符串的索引。j将成为您目标字符串的索引。

您将开始像现在一样遍历源字符串,i在每次迭代时递增。当源中有一个非空格字符时,您会将其复制到目标,并增加目标索引。

当源中有空间时,您不会将其复制到目标或增加目标索引。

通常这看起来像:

size_t j = 0;

for (i=0; input[i]; i++)
    if (input[i] != ' ')
        output[j++] = input[i];
output[j] = '\0';

是的,我会使用类似inputand outputor sourceanddest而不是str1and str2。后者没有表明您正在从/复制到哪个。

我还建议使用isspacefrom<ctype.h>而不是直接与空格字符进行比较,除非您真的只想消除空格字符,但保留其他空格(制表符、回车符、换行符、垂直制表符等)

于 2013-06-07T03:59:02.643 回答
1

[编辑] 重写为仅使用 1 个字符串参数。

void deblank(char str[]) {
   size_t x = 0;
   for (size_t i = 0; str[i]; i++) {
      if (str[i] != ' ') {
         str[x++] = str[i];
      }
   }
   str[x] = '\0';
}
于 2013-06-07T04:01:06.073 回答
1

好的,这只是为接受的答案提供另一种方法,主要是帮助您以更通用的方式解决问题。

#include <stdio.h>
/** 
 * char *remove_needles(char *dest, const char *haystack, const char *needles);
 * 
 * puts in dest, all characters from haystack, that are not found in needles
 */

char *remove_needles(char *dest, const char *haystack, const char *needles) 
{
    const char *hp;   /* this pointer will run through the haystack and is used to sort
                       * needles and hay 
                       */
    char *dp;         /* this pointer will point to the last character in dest */
    const char *np;   /* runs through the needles with the current  */

    dp = dest;         /* to begin with the tail is the head :-) */

    for (hp = haystack; hp != NULL && *hp != '\0'; hp++ ) {

        for (np = needles; *np != '\0'; np++ ) {  
           if ( *hp == *np ) { /* is the current char at hp a needle? */
              break; /* yep: let's break out of this loop it's a needle */
           }
        }

        if ( *np == '\0' ) { 
                           /* *np will only be '\0' if we ran through all the needles but 
                            * the character at the pointer hp was not a needle
                            */
           *dp = *hp;      /* so it's hay and we save it at the tail of dest */
           dp++;           /* and move the tail along */
        }
    }

    return dest;           /* we are all done and we return the result */
}


int main() 
{
      char src[] = "Hello World\n\tare you watching this?";
      char dest[256]; /* this should have at least sizeof(src) space */
      char white_spaces[] = " \t"; /* these are our needles, notice the space before \t */

      remove_needles(dest, src, white_spaces);

      printf("src: `%s'\ndest:`%s'\n", src, dest);
      return 0;
}

要考虑的练习

  1. 您可以将其扩展为将 haystack 中的子字符串放入数组的拆分函数吗?首先将自己限制为 10 个子字符串,声明 chardest[128][10];并尝试一下。

  2. 你怎么能避免像这样声明 dest ?我们知道 dest 可以占用的总内存不会比 haystack 大,是否可以在不手动计算的情况下让自己接近这个数量?

于 2013-06-07T04:41:20.833 回答
0

更聪明的方法是使用第二个计数器来跟踪输出数组中的当前位置。如果输入中的当前字符不是空格,则仅复制到输出。

#include <stdio.h>

void deblank(char str1[], char str2[])
{
   int i, j = 0; /* j points initially to the first element of str2, we only increment it if i doesn't point to space */

   for (i = 0; str1[i] != '\0'; i++)
   {
      if (str1[i] != ' ') /* i doesn't point to a space char */
      {
         str2[j] = str1[i]; /* add the current char to str2, for the first iteration this is at position str2[0] */
         j++; /* increment j++, so that the next time we encounter a non-space char, it is put in the next posisition */
      }
   }

   str2[i] = '\0';
}

int main()
{
    char input[20] = "Hey lo, World!";
    char output[20] = "";

    deblank(input, output);

    printf("%s - %s\n", input, output);

    return 0;
}

印刷:

 $ ./a.out 
 Hey lo, World! - Heylo,World!
于 2013-06-07T04:10:15.550 回答
0

您只是移动 1 个字符并留下其余字符 - 用 'w' 填充 ' '。

从左到右移动,每次遇到空白时都需要将所有字符向左移动。反正就是这个想法。

拥有 2 个字符串会更容易 - 也更快一点:一个源和一个目标。

像这样:

char src[128] = "hello world and then some!";
char dest[128];

int destIndex = 0;
for (int i = 0; i < strlen(src); ++i)
{
    if (src[i] != ' ')
        dest[destIndex++] = src[i];
}
dest[destIndex] = 0;  // make sure the new string is terminated

这样你就不必改变任何东西 - 只需将非空白字符移动到新字符串,你就会得到一个删除所有空格的新字符串。

于 2013-06-07T03:59:28.070 回答
0
code what ur written won't work when multiple spaces are there in between words.


int i, x=0;

   for (i = 0; str1[i] != '\0'; i++)
   {
      if ((str1[i] == ' ')||(str[i] == '\t'))
      {
         continue;
      }

      else
      {
         str2[x] = str1[i];
          x++;
      }
   }

   str2[x] = '\0';
于 2013-06-07T04:00:04.723 回答
0

这应该有效。

void deblank(char str1[], char str2[])
{
   int i, j;

   for (i = 0, j = 0; str1[i] != '\0'; i++, j++)
   {
      if (str1[i] == ' ')
      {
         i++;
         str2[j] = str1[i];
      }

      else
      {
         str2[j] = str1[i];
      }
   }

   str2[j] = '\0';
}
于 2013-06-07T04:00:56.453 回答