strncpy 函数使用及其模拟实现
目录
一、strncpy 函数函数原型
1、功能描述
2、具体行为
3、注意事项
示例
二、strncpy 函数的模拟实现
关键点解析
测试用例
Test1: Hello烫烫烫...
一、strncpy 函数函数原型
char *strncpy(char *destination, const char *source, size_t num);
1、功能描述
strncpy 函数用于将源字符串(source)的前 num 个字符复制到目标空间(destination)中。
2、具体行为
-
正常复制:复制源字符串的前 num 个字符到目标空间。
-
源字符串较短时:如果源字符串长度小于 num(即遇到 null 终止符'\0'),则:
-
然后在目标空间中用 null 字符('\0')填充剩余空间,直到总共写入 num 个字符
-
先复制源字符串所有内容(包括终止符)
-
-
源字符串较长时:如果源字符串前 num 个字符中没有 null 终止符,则不会自动添加终止符
3、注意事项
-
目标空间必须足够大,至少能容纳 num 个字符
-
与 strcpy 不同,strncpy 不保证目标字符串以 null 终止(当源字符串长度 ≥ num 时)
-
如果 num 大于源字符串长度,会浪费空间填充 null 字符
-
使用时通常需要手动确保字符串终止:
destination[num-1] = '\0'
示例
char dest[10];
strncpy(dest, "hello", 10); // 复制"hello"并填充5个'\0'
strncpy(dest, "longer string", 5); // 只复制"longe",不会自动添加'\0'
dest[4] = '\0'; // 需要手动终止
二、strncpy 函数的模拟实现
下面是一个完整的 strncpy
函数模拟实现,包含详细注释和边界条件处理:
#include <stddef.h> // for size_t/*** @brief 模拟实现 strncpy 函数* @param dest 目标字符串地址* @param src 源字符串地址* @param n 要复制的字符数* @return 目标字符串地址*/
char *my_strncpy(char *dest, const char *src, size_t n) {// 记录起始地址用于返回char *start = dest;// 1. 复制字符直到复制完n个字符或遇到src的终止符while (n > 0 && *src != '\0') {*dest++ = *src++;n--;}// 2. 如果n还有剩余,用'\0'填充剩余空间while (n > 0) {*dest++ = '\0';n--;}return start;
}
关键点解析
-
参数处理:
-
使用
const char*
保证源字符串不被修改 -
使用
size_t
类型表示字符数,与标准库一致
-
-
复制过程:
-
第一个 while 循环负责从源字符串复制字符
-
第二个 while 循环负责填充剩余的 null 字符
-
-
边界条件:
-
正确处理 n=0 的情况
-
正确处理 src 长度小于 n 的情况
-
正确处理 src 长度大于等于 n 的情况
-
-
返回值:返回目标字符串起始地址,与标准库行为一致
测试用例
#include <stdio.h>
#include <string.h>int main() {char dest[20];// 测试1: 正常情况my_strncpy(dest, "Hello", 5);printf("Test1: %s\n", dest); // 应输出 "Hello"// 测试2: 源字符串短于nmemset(dest, '#', 20); // 填充非零值my_strncpy(dest, "Hi", 5);printf("Test2: %s\n", dest); // 应输出 "Hi" 后跟3个不可见'\0'// 测试3: 源字符串长于nmy_strncpy(dest, "TooLongString", 5);dest[5] = '\0'; // 手动终止printf("Test3: %s\n", dest); // 应输出 "TooLo"// 测试4: n=0my_strncpy(dest, "Hello", 0);printf("Test4: %s\n", dest); // 应无变化return 0;
}
这个实现完整模拟了标准库 strncpy
的所有行为特征,包括填充 null 字符和不自动终止字符串的特性。
Test1: Hello烫烫烫...
问题原因:
-
my_strncpy
复制了5个字符"H","e","l","l","o"到dest
-
没有自动添加字符串终止符'\0'
-
printf
打印时找不到终止符,继续读取内存直到遇到随机'\0',导致打印出后面内存中的随机内容(显示为"烫烫烫")