在没有 strcat 的情况下连接两个字符串

concatenate two strings without strcat

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

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

使用 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;
}

此处显示了使用上述修改的示例会话:

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

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

  • 不要使用gets读取输入,使用fgets()并删除最后的'\n'

  • 只计算一次s1s2的长度,并将它们存储在局部变量中。

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

  • 用这些局部变量重写你的循环,或者使用strcpymemcpy

这是一个例子:

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

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

    puts("First string?");
    if (!fgets(s1, sizeof s1, stdin))
        return 1;

    len1 = strlen(s1);
    if (len1 > 0 && s1[len1 - 1] == '\n')
        s1[--len1] = '[=10=]';

    puts("Second string?");
    if (!fgets(s2, sizeof s2, stdin))
        return 1;

    len2 = strlen(s2);
    if (len2 > 0 && s2[len2 - 1] == '\n')
        s1[--len2] = '[=10=]';

    if (len1 + len2 >= sizeof s1)
        return 2;

    /* copy the characters from s2 including the final '[=10=]' */
    for (i = 0; i <= len2; i++) {
        s1[len1 + i] = s2[i];
    }

    puts(s1);

    return 0;
}

s1 的长度在运行时发生变化,导致您的索引 i 不正确。尝试如下所示:-

l = strlen(s1);

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

s1[l] = '[=10=]';

假设s1 = "hello"和s2 = "world",那么在第一次迭代中,s1的长度= 5,s2的索引= 0(i-length(s1));效果很好。但是在第二次迭代中,length(s1) = 6 和 s2 的索引 = 0(i-length(s1))。所以从 s2 中获取字符的索引没有改变。这是关于您的实现中的问题,尽管您应该使用 sprintf 的有效方法。

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

我在你的程序中并没有真正改变太多,但这是我所拥有的(从你的修改而来)并且它有效。

#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 系统上正确编译和运行。

作为旁注,不要 return 在主目录上无效。 始终 return 整数。还要指定您计划使用的库 headers。

编辑:我修改了代码以使用 fgets 而不是 gets,因为 gets 是完全不安全的。它不检查缓冲区大小,因此您很容易发生缓冲区溢出。

// A simple strcat function

int main(void)
{
    char str1[100] ="Avis";
    stringcat(str1,"karthik");
    printf("\n%s",str1);
    return 0;
}
void stringcat(char *str1, char *str2)
{
   while(*str1)
       str1++;
   while(*str2)
       *str1++ = *str2++;
}