连接两个没有strcat的字符串

时间:2015-12-27 18:21:16

标签: c string strcat

我想在不使用strcat()函数的情况下连接两个字符串。但是我没有得到所需的结果。请指出我的错误。

void main() {
    char s1[100], s2[100];
    int i;

    puts("First string?");
    gets(s1);

    puts("Second string?");
    gets(s2);

    for (i = strlen(s1); i <= (strlen(s1) + strlen(s2)); i++) {
        s1[i] = s2[i - strlen(s1)];
    }

    puts(s1);
}

5 个答案:

答案 0 :(得分:2)

我在你的程序中没有太大的改变,但这就是我所拥有的(从你的程序中修改)并且它有效。

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

int main(void)
  {
    char s1[100], s2[100];
    size_t i, s1l, s2l, total;

    puts("First string?");
    fgets(s1, sizeof(s1), stdin);
    s1[strlen(s1) - 1] = 0x00;

    puts("Second string?");
    fgets(s2, sizeof(s2), stdin);
    s2[strlen(s2) - 1] = 0x00;

    s1l = strlen(s1);
    s2l = strlen(s2);
    total = s1l + s2l;

    for(i = s1l; i <= total; i++)
      {
        s1[i] = s2[i - s1l];
      }

    puts(s1);

    return(0);
  }

逐字地使用你的程序,问题在于,由于s1的长度在循环的每次迭代中都在变化,因此检查中的strlen(s1)值不断增加,因此你基本上会得到一个无限循环。 ..至少遇到一些随机的空字节。但是,当事先取出字符串的长度时,循环终点计数不会改变,这会导致正确的输出。我的代码将使用clang编译器在FreeBSD 10.2系统上正确编译和运行。

作为旁注,不要在main上返回void。 总是返回int。同时指定您计划使用的库标题。

编辑:我修改了代码以使用fgets代替获取,因为获取完全不安全。它不检查缓冲区大小,因此您可以轻松地缓冲区溢出。

答案 1 :(得分:1)

使用sprintf的变体:

简单

char buf[200];
sprintf(buf, "%s%s" s1, s2);

更简单的更安全

char buf[200]
snprintf(buf, sizeof(buf), "%s%s", s1, s2);//prevents buffer overflow

或者,修改你的循环(参见在线评论中的原因):

int main(void)//note changed main prototype
{
        char s1[100], s2[100];//caution here: s1 must be big enough
                              //to contain its string as well as
                              //the string stored in s2, plus 1 for NULL
        int i;
        int len1, len2;//create variables to store string lengths

        puts("First string?");
        gets(s1);//note, gets is no longer recommended

        puts("Second string?");
        gets(s2);
        len1 = strlen(s1);//store string lengths only once
        len2 = strlen(s2);//to avoid calling them repeatedly in loop

        for(i = 0; i < len2; i++)//index i in one place only
        {
            s1[len1+i] = s2[i];
        }
        s1[len1 + i]=0;//null terminate string when done.
        puts(s1);
        getchar();//added to pause execution in my environment.
        return 0;
}

此处显示使用上述修改的示例会话: enter image description here

答案 2 :(得分:1)

s1的长度在运行时会发生变化,使得索引不正确。尝试以下内容: -

l = strlen(s1);

for(i = 0; i < strlen(s2); i++)
{
   s1[l++] = s2[i];
}

s1[l] = '\0';

假设s1 =&#34;你好&#34;并且s2 =&#34; world&#34 ;,然后在s1 = 5的第一次迭代长度和s2 = 0的索引(i-长度(s1));效果很好。但是在第二次迭代中,长度(s1)= 6,索引为s2 = 0(i-length(s1))。因此从s2获取角色的索引不会改变。这是关于实现中的问题,尽管使用sprintf应该是一种有效的方法。

sprintf(s1, "%s%s", s1, s2);

答案 3 :(得分:0)

您的解决方案不起作用,因为您在每次迭代时重新计算strlen(s1)以测试完成情况,并在s2中计算从中复制字符的偏移量,但您修改了s1循环,所以长度发生变化,更糟糕的是,s1暂时不再'\0'终止:测试表达式i <= strlen(s1) + strlen(s2)调用未定义的行为,复制{{1}时也是如此第二次循环。

使用这些想法来纠正您的代码:

  • 请勿使用s2[i - strlen(s1)]阅读输入,使用gets并删除最终fgets()

  • 仅计算'\n's1的长度,并将其存储在局部变量中。

  • 验证串联不会超过s2的大小。

  • 使用这些局部变量重写循环,或使用s1strcpy

以下是一个例子:

memcpy

答案 4 :(得分:0)

catch