【问题标题】:strcat(); printing extra charactersstrcat();打印多余的字符
【发布时间】:2010-07-02 18:52:30
【问题描述】:

我自己创建了 strcat() 函数,但在添加字符串后,它会打印一个额外的 ascii 符号。 请说出原因?

  #include<stdio.h>
  #include<conio.h>
  #include<string.h>
  void xstrcat(char string1[],char string2[]);
  void main(void)
{ char x[100];
  char string1[40],string2[40];
  printf("Enter a string:");
  gets(string1);
  puts("Enter another string:");
  gets(string2);
  xstrcat(string1,string2);
  printf("%s",string1);
  getch();
}
  void xstrcat(char string1[],char string2[])
{
  int i,x,y;
  x=strlen(string1);
  y=strlen(string2);
  for(i=0;i<y;i++)
  { string1[i+x]=string2[i];
  }//for ends
}

【问题讨论】:

  • @fahad:在框的顶部有一个小按钮,您可以在其中写下您的问题,看起来像 101 \n 010。以后请在您的代码中使用它。似乎您提出的每个问题都必须由其他人重新格式化。
  • 与您的问题相切,但不要使用 gets: stackoverflow.com/questions/2843073/… 。甚至它自己的文档也说不要使用它。
  • 可能是void main,已知它会引发未定义的行为。最好尽快切换到正确的int main
  • gets 让输入变得很容易......然后 scanf 很容易
  • @fahad,使用fgets 也同样简单,并且没有致命的错误且没有解决方法。

标签: c


【解决方案1】:

您的 xstrcat() 函数没有在结果字符串的末尾放置空终止符。

一种可能的解决方法是在 xstrcat() 函数返回之前添加以下内容:

string1[x+y] = '\0';

【讨论】:

  • 我自己添加了\0,因为我的老师告诉我它是添加的,你不需要添加它。有什么建议吗?我按照你说的做了,现在程序运行良好:)
  • 在做什么时添加了自己? C 中的字符串文字自动包含 0 终止符,而 strcpy、strcat 等库函数将写入 0 字节。但是在这里,您正在自己逐字节地操作内存。在一般情况下,该语言如何可能将以下字节更改为 0 而不会出现严重错误?
【解决方案2】:

在 C 中,字符串以 NUL 字节(值为 0 的字符)终止。 strlen 会告诉你从字符串的开头到 NUL 字节有多少个字符,不计算 NUL 字节本身

所以当你执行这个循环时:

for(i=0;i<y;i++)
  { string1[i+x]=string2[i];
  }

您永远不会将终止 NUL 字节从 string2 复制到 string1,因此 string1 不再有终止 NUL(您在循环的前面用 string2 的第一个字符覆盖了它的 NUL)。当一个字符串缺少它的终止 NUL 时,读取它的函数(例如printf)将继续读取字符串的预期端点,直到它们最终在内存中更远的地方找到一个 NUL 字节。这可能会导致打印额外的字符和/或崩溃。

要么将y 更改为y+1,要么在string1x+y 位置显式插入'\0'

【讨论】:

    【解决方案3】:
    void xstrcat(char string1[],char string2[])
    {
      //int i,x,y;
      size_t i, x, y;
      // They could also be unsigned, but size_t is an unsigned big enough to hold the
      // biggest in memory index possible
    
      x=strlen(string1);
      y=strlen(string2);
    
      //for(i=0;i<y;i++)
      for (i=0; i<=y; i++) // This picks up the null at the end
      { string1[i+x]=string2[i];
      }//for ends
    }
    

    或者你可以这样做:

    void xstrcat(char * string1, const char * string2)
    {
       while(*string1) {
           string1++;
       }
       strcpy(string1, string2);
    }
    

    这应该会快一点,因为它不必遍历任何一个字符串而是一次。它也不需要那么多额外的变量。

    【讨论】:

    • 你的替代版本也好不到哪里去;两个版本都不会多次遍历任一字符串。另一个替代版本只是strcpy(string1+=strlen(string1),string2);,但我认为问题的重点是如何从头开始实现strcat,而不是基于其他库函数。
    • @R:strlen遍历字符串统计字符,复制字符串需要遍历。第一个版本遍历 string2 一次以获取长度,一次用于复制,而 string1 仅遍历一次以获取长度,而第二个版本仅遍历 string1 一次以获取长度(通过找到其结尾),并且仅在完成长度和复制的情况下遍历 string2 一次(只要因为 strcpy 被实现为副本,直到 null)。
    【解决方案4】:

    你的循环

    for (i = 0; i < y; i++) {
        string1[i+x]=string2[i];
    }
    

    如果您不知道在 c 或 c++ 中字符串以 NULL ( 0 ) 字符结尾,那么您正在读取的字符串 2 的长度为 1,它将只读取 NULL 之前的最后一个字符。

    所以你的 string1 最后不会有 NULL 字符。

    所以现在当你尝试打印你的 string1 时,它肯定会在最后打印一些字符,因为你的字符串大小为 40,这些字符是垃圾。

    大多数情况下,您将打印 40 个字符的字符串,除非这些垃圾值为 0。

    所以你应该把第二个字符串读到 0,所以让你的循环

    for (i = 0; i <= y; i++)
    

    或者你可以简单地在字符串 1 的末尾添加一个 NULL 字符,然后在其中添加 string2。

    string1[x+y] = 0;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-11
      • 2013-08-29
      • 1970-01-01
      相关资源
      最近更新 更多