strcat函数如何实现字符串连接?

99ANYc3cd6
预计阅读时长 17 分钟
位置: 首页 C语言 正文

strcat 函数简介

我们回顾一下标准库中 strcat 函数的行为:

c语言strcat函数实现
(图片来源网络,侵删)
#include <string.h>
char *strcat(char *dest, const char *src);

功能: 将 src (source) 指向的字符串追加到 dest (destination) 指向的字符串的末尾。

关键点

  1. 目标字符串 (dest) 必须有足够的空间来容纳 dest 原有的内容 + src 的内容 + 一个额外的 \0 (空字符),如果空间不足,会导致缓冲区溢出,这是非常危险的。
  2. 追加操作会覆盖 dest 原有字符串末尾的 \0
  3. 函数返回 dest 指针。
  4. src 指向的字符串是 const,表示 strcat 函数不会修改源字符串。

实现思路

要手动实现 strcat,我们可以分三步走:

  1. 找到目标字符串的末尾:遍历 dest 字符串,直到找到其结尾的空字符 \0,指针就指向了可以开始追加新字符的位置。
  2. 复制源字符串:从 src 字符串的第一个字符开始,将其逐个字符复制到 dest 的末尾位置,直到 src 也遇到 \0 为止。
  3. 添加终止符:将 \0 追加到新拼接好的字符串末尾。

C语言代码实现

下面是一个完整的、带有注释的实现代码。

c语言strcat函数实现
(图片来源网络,侵删)
#include <stdio.h>
/**
 * @brief  将源字符串 src 追加到目标字符串 dest 的末尾
 * 
 * @param dest 目标字符串,必须有足够的空间
 * @param src  源字符串
 * @return char* 返回目标字符串 dest 的指针
 */
char *my_strcat(char *dest, const char *src) {
    char *ptr = dest; // 保存 dest 的起始地址,用于最后返回
    // 1. 移动指针到 dest 字符串的末尾
    // 循环直到找到 dest 字符串的结束符 '\0'
    while (*dest != '\0') {
        dest++;
    }
    // 2. 将 src 字符串的内容复制到 dest 的末尾
    // 循环直到找到 src 字符串的结束符 '\0'
    // 循环结束后,'\0' 也会被复制过去
    while (*src != '\0') {
        *dest = *src;
        dest++;
        src++;
    }
    // 3. 确保新字符串以 '\0' (虽然上面的循环已经完成了这一步,但显式写出更清晰)
    *dest = '\0';
    // 4. 返回目标字符串的起始地址
    return ptr;
}
// --- 测试代码 ---
int main() {
    // char 数组必须足够大,以容纳结果
    char str1[50] = "Hello, "; // 初始化,注意留出足够空间
    char str2[] = "world!";
    printf("strcat 前:\n");
    printf("str1: \"%s\"\n", str1);
    printf("str2: \"%s\"\n", str2);
    // 调用我们自己的 my_strcat 函数
    my_strcat(str1, str2);
    printf("\nstrcat 后:\n");
    printf("str1: \"%s\"\n", str1);
    // 测试链式追加
    char str3[100] = "This is a test";
    my_strcat(str3, " of the ");
    my_strcat(str3, "emergency broadcast system.");
    printf("\n链式追加结果:\n");
    printf("str3: \"%s\"\n", str3);
    return 0;
}

代码解析:

  1. *`char my_strcat(char dest, const char src)`**

    • 函数签名与标准库 strcat 一致。src 被声明为 const char *,这是一个好习惯,表明我们承诺不会修改 src 的内容。
  2. *`char ptr = dest;`**

    • 我们创建一个临时指针 ptr 来保存 dest 的原始地址,因为在接下来的操作中,dest 指针会不断移动,最终指向字符串的末尾,我们需要返回的是字符串的起始地址,ptr 派上了用场。
  3. *`while (dest != '\0') { dest++; }`**

    • 这是第一步。*dest 解引用 dest 指针,获取它当前指向的字符,只要这个字符不是 \0,我们就让 dest 指针向前移动一个位置,当循环结束时,dest 指针恰好指向了 dest 原字符串末尾的 \0 的位置,也就是新内容应该开始的位置。
  4. *`while (src != '\0') { dest = src; dest++; src++; }`**

    c语言strcat函数实现
    (图片来源网络,侵删)
    • 这是第二步。destsrc 都指向各自字符串的有效内容,我们进入一个循环,将 src 指向的字符赋值给 dest 指向的位置,然后两个指针都向前移动,这个过程会一直持续,直到 src 指向 \0,在最后一次赋值时,*dest = *src 实际上就是 *dest = '\0',这完美地完成了为新字符串添加终止符的工作。
  5. *`dest = '\0';`**

    • 虽然上面的循环已经将 src\0 复制过来了,但显式地再写一遍可以增加代码的可读性和健壮性,明确表示我们在这里确保字符串的正确终止。
  6. return ptr;

    • 返回我们一开始保存的 dest 的起始地址。

安全版本实现:strncat

标准库还提供了一个更安全的版本 strncat,它允许你指定最多追加多少个字符,从而防止缓冲区溢出。

char *strncat(char *dest, const char *src, size_t n);

我们可以基于同样的思路实现 my_strncat

/**
 * @brief  将源字符串 src 的前 n 个字符追加到目标字符串 dest 的末尾
 * 
 * @param dest 目标字符串,必须有足够的空间
 * @param src  源字符串
 * @param n    要追加的最大字符数
 * @return char* 返回目标字符串 dest 的指针
 */
char *my_strncat(char *dest, const char *src, size_t n) {
    char *ptr = dest;
    // 1. 移动指针到 dest 字符串的末尾
    while (*dest != '\0') {
        dest++;
    }
    // 2. 复制 src 的前 n 个字符,或者直到遇到 src 的 '\0'
    while (n > 0 && *src != '\0') {
        *dest = *src;
        dest++;
        src++;
        n--; // 每复制一个字符,n 就减 1
    }
    // 3. 确保新字符串以 '\0' 
    *dest = '\0';
    return ptr;
}
// --- 测试 my_strncat ---
int main_strncat_test() {
    char str1[20] = "Hello"; // 目标空间有限
    char str2[] = " world, this is a very long string!";
    printf("\n--- strncat 测试 ---\n");
    printf("strcat 前: \"%s\"\n", str1);
    printf("str2: \"%s\"\n", str2);
    // 只追加 str2 的前 7 个字符(包括空格)
    my_strncat(str1, str2, 7); 
    printf("strncat 后: \"%s\"\n", str1); // 输出 "Hello world"
    return 0;
}

my_strncat 的核心区别在于第二个 while 循环的条件:while (n > 0 && *src != '\0'),它会同时检查是否还有可追加的字符数 (n > 0) 以及源字符串是否已经结束 (*src != '\0'),这样就确保了不会追加超过 n 个字符,从而保证了安全性。

实现 strcat 的核心在于熟练运用指针来遍历和操作字符数组,并始终牢记字符串以 \0 结尾这一关键特性,理解了 strcat 的实现,对于掌握C语言中的指针和字符串操作非常有帮助,也必须时刻警惕缓冲区溢出的风险,在实际编程中优先考虑使用更安全的 strncat 或其他有边界检查的字符串处理函数。

-- 展开阅读全文 --
头像
c语言getchar头文件
« 上一篇 03-04
织梦在线预约报名模板如何快速搭建?
下一篇 » 03-04
取消
微信二维码
支付宝二维码

目录[+]