为什么这不连接两个字符串?

Why does this not concatenate two strings?

这是我的代码的要求:

This function appends the src string to the dest string, overwriting the terminating null byte ('[=14=]') at the end of dest, and then adds a terminating null byte.

Returns a pointer to the resulting string dest.

这是我得到的输出:

Hello
World!
Hello World!
Hello

这是我的代码:

char *_strcat(char *dest, char *src) {
    int lengthd = 0;
    int lengths = 0;
    int i = 0;
    int j = 0;
    int k = 0;
    char tmp[10];
    while (dest[i] != '[=11=]') {
        lengthd++;
        i++;
    }
    while (src[k] != '[=11=]') {
        tmp[lengths] = src[k];
        lengths++;
        k++;
    }
    for (; j < lengths - 1; j++) {
        dest[lengthd + 1] = tmp[j];
    }
    dest[lengthd + 1] = '[=11=]';
    return (dest);
}

int main(void) {
    char s1[98] = "Hello ";
    char s2[] = "World!\n";
    char *ptr;
    printf("%s\n", s1);
    printf("%s", s2);
    ptr = _strcat(s1, s2);
    printf("%s", s1);
    printf("%s", s2);
    printf("%s", ptr);
    return (0);
}

至少由于字符数组 tmp 与幻数 10

的声明
char tmp[10];

函数没有意义。

而且在这个 while 循环中

  while (src[k] != '[=11=]')
  {
          lengths++;
          k++;
          tmp[lengths] = src[k];
  }

跳过数组 tmp 的第一个元素。

也在这个for循环中

  for (; j < lengths-1; j++)
  {
          dest[lengthd + 1] = tmp[j];
  }

循环条件不正确。表达式 dest[lengthd + 1] 也会跳过指针 dest 指向的字符串的终止零字符。并且所有的字符都写在同一个位置 lengthd + 1.

除此之外,main 中使用的名称 s1s2ptr 未声明。

函数可以通过以下方式声明和定义

char * my_strcat( char *dest, const char *src )
{
    char *p = dest;

    while ( *p ) ++p;

    while ( ( *p++ = *src++ ) != '[=13=]' );

    return dest;
}

可以这样称呼

char s1[13] = "Hello ";
const char *s2 = "World!";

puts( my_strcat( s1, s2 ) );

使用与您的方法类似的方法定义函数的另一种方法如下

char * my_strcat( char *dest, const char *src )
{
    size_t i = 0;

    while ( dest[i] != '[=15=]' ) ++i;

    for ( size_t j = 0; src[j] != '[=15=]'; j++ )
    {
        dest[i++] = src[j];
    }

    dest[i] '[=15=]';  

    return dest;
}

您的代码因多种原因而失败:

  • 您使用临时数组复制源字符串:此数组tmp 的固定长度为 10 个字节,如果源字符串长于 10 个字节,则该数组太小。否则,当您超出此数组的末尾写入时,您将有未定义的行为。
  • 反正这个临时数组真的没必要。
  • 最终循环在 lengths - 1 处停止,因此您在副本的最后一个字节之前停止。
  • 您将所有字节复制到同一位置dest[lengthd + 1]
  • 你终于在同一位置再次设置了空终止符。
  • 您从未更改 dest[lengthd] 处的空终止符,因此该函数似乎对 dest.
  • 没有影响
  • main() 中的测试无法生成您发布的输出,可能是因为 "%s\n" 中的错字。
  • 避免使用以 _.
  • 开头的标识符

这是修改后的版本:

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

char *my_strcat(char *dest, char *src) {
    int i = 0;
    int k = 0;

    /* find the offset of the null terminator in dest */
    while (dest[i] != '[=10=]') {
        i++;
    }
    /* copy the bytes from the src string there */
    while (src[k] != '[=10=]') {
        dest[i] = src[k];
        i++;
        k++;
    }
    /* set the null terminator */
    dest[i] = '[=10=]';
    /* return the pointer to the destination array */
    return dest;
}

int main(void) {
    char s1[98] = "Hello ";
    char s2[] = "World!";
    char *ptr;
    printf("%s\n", s1);
    printf("%s", s2);
    ptr = my_strcat(s1, s2);
    printf("%s", s1);
    printf("%s", s2);
    printf("%s", ptr);
    return 0;
}

请注意,源字符串未被修改,偏移量应具有类型 size_t 并且可以作为赋值的副作用递增:

char *my_strcat(char *dest, const char *src) {
    size_t i = 0;
    size_t k = 0;

    /* find the offset of the null terminator in dest */
    while (dest[i] != '[=11=]') {
        i++;
    }
    /* copy the bytes from the src string there */
    while (src[k] != '[=11=]') {
        dest[i++] = src[k++];
    }
    /* set the null terminator */
    dest[i] = '[=11=]';
    /* return the pointer to the destination array */
    return dest;
}

您也可以使用指针代替偏移量:

char *my_strcat(char *dest, const char *src) {
    /* use a working pointer to preserve dest for the return value */
    char *p = dest;

    /* find the offset of the null terminator in dest */
    while (*p != '[=12=]') {
        p++;
    }
    /* copy the bytes from the src string there */
    while (*src != '[=12=]') {
        *p++ = *src++;
    }
    /* set the null terminator */
    *p = '[=12=]';
    /* return the pointer to the destination array */
    return dest;
}

最后一个更改:您可以结合读取源字节、复制到目标和测试空终止符,它已经被复制了:

char *my_strcat(char *dest, const char *src) {
    /* use a working pointer to preserve dest for the return value */
    char *p = dest;

    /* find the offset of the null terminator in dest */
    while (*p != '[=13=]') {
        p++;
    }
    /* copy the bytes from the src string there */
    while ((p++ = *src++) != '[=13=]') {
        /* nothing */
    }
    /* the null terminator was copied from the source string */
    /* return the pointer to the destination array */
    return dest;
}