繁体   English   中英

连接两个没有strcat的字符串

[英]concatenate two strings without 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);
}

我对您的程序没有真正的改变,但是这就是我(从您的程序修改而来的)并且可以正常工作。

#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而不是gets,因为gets完全不安全。 它不检查缓冲区大小,因此您很容易发生缓冲区溢出。

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

使用上述修改的示例会话如下所示: 在此处输入图片说明

s1的长度在运行时更改,这使索引i不正确。 尝试以下类似的方法:-

l = strlen(s1);

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

s1[l] = '\0';

假设s1 =“ hello”且s2 =“ world”,则在第一次迭代中s1 = 5,索引s2 = 0(i- length(s1)); 效果很好。 但是在第二次迭代中,长度(s1)= 6,索引s2 = 0(i-length(s1))。 因此从s2提取字符的索引不变。 这是关于实现中的问题,尽管您应该通过使用sprintf来获得有效的方式。

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

您的解决方案不起作用,因为您在每次迭代时都要重新计算strlen(s1)以测试是否完成并计算s2的偏移量以从中复制字符,但是您在循环中修改了s1 ,因此长度改变了,甚至更糟了s1暂时不再以'\\0'终止:测试表达式i <= strlen(s1) + strlen(s2)调用未定义的行为,当您第二遍复制s2[i - strlen(s1)]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] = '\0';

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

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

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

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

    puts(s1);

    return 0;
}
// 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++;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM