一、strcpy():容易溢出
- 头文件:#include <string.h>
- strcpy() 函数用来复制字符串;
- 其原型为:char *strcpy(char *dest, const char *src);
- strcpy()是依据 \0 作为结束判断的;
- 通常,我们的 from 都来源于用户的输入,很可能是非常大的一个字符串,因此 strcpy 不够安全;
(1)【参数】dest 为目标字符串指针,src 为源字符串指针;
(2)注意:src 和 dest 所指的内存区域不能重叠,且dest 必须有足够的空间放置 src 所包含的字符(包含结束符NULL);
(3)【返回值】成功执行后返回目标数组指针 dest;
(4)strcpy() 把src所指的由NULL结束的字符串复制到dest 所指的数组中,返回指向 dest 字符串的起始地址;
(5)注意:如果参数 dest 所指的内存空间不够大,可能会造成缓冲溢出(buffer Overflow)的错误情况,在编写程序时请特别留意,或者用strncpy()来取代;
二、strncpy():多余补0,效率和已有数据丢失
- strncpy()用来复制字符串的前n个字符;
- 其原型为:char * strncpy(char *dest, const char *src, size_t n);
(1)【参数说明】dest 为目标字符串指针,src 为源字符串指针;
(2)strncpy()会将字符串src前n个字符拷贝到字符串dest;
(3)不像strcpy(),strncpy()不会向dest追加结束标记’\0’,这就引发了很多不合常理的问题,将在下面的示例中说明;
(3.1)如果src的前n个字节不含NULL字符,则结果不会以NULL字符结束;
(3.2)如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节;
(4)src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串;
(5)注意:src 和 dest 所指的内存区域不能重叠,且dest 必须有足够的空间放置n个字符;
(6)【返回值】返回指向dest的指针(该指向dest的最后一个元素);
(7)在 ANSI C 中,strcpy 的安全版本是 strncpy。
(8)但 strncpy 其行为是很诡异的(不符合我们的通常习惯)。标准规定 n 并不是 sizeof(s1),而是要复制的 char 的个数。一个最常见的问题,就是 strncpy 并不帮你保证 \0
结束。
示例
1. 看这个程序,buf 将会被 “abcdefgh” 填满,但却没有 \0 结束符了。
char buf[8];
strncpy( buf, "abcdefgh", 8 );
// 另外,如果 s2 的内容比较少,而 n 又比较大的话,
// strncpy() 将会把之间的空间都用 \0 填充。这又出现了一个效率上的问题,如下:
// 下面的 strncpy() 会填写79个char,而不仅仅是 "abcdefgh" 本身,还包含71 (79-8)个 '\0'
char buf[80];
strncpy( buf, "abcdefgh", 79 );
2. strncpy 的标准用法为:(手工写上 \0), 如下:
strncpy(path, src, sizeof(path) - 1);
path[sizeof(path) - 1] = '\0';
len = strlen(path);
3. 定义一个 字符串数组的时候,一定要留一个字节给空字符’\0’。
char qq[8] = "qwer123"
char ww[8] = "qwer1234"
printf("%s\n",qq); // qwer123
printf("%s\n",ww); // qwer123
// 执行这条语句后,打印的结果都是一样的。都是qwer123
// 因为 ww[8]的最后一个字节被'\0'填充了。
三、sprintf()
- <stdio.h>
- 函数原型:int sprintf(char *str, const char *format, …);
- 返回值:如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。
#include <stdio.h>
#include <math.h>
int main()
{
char str[80];
sprintf(str, "Pi 的值 = %f", M_PI);
return(0);
}
四、snprintf()
- <stdio.h>
- 函数原型: int snprintf(char *str, size_t size, const char *format, …)
- 设将可变参数(…)按照 format 格式化成字符串,并将字符串复制到 str 中,size 为要写入的字符的最大数目,超过 size 会被截断。
- 如果格式化后的字符串长度小于等于 size,则会把字符串全部复制到 str 中,并给其后添加一个字符串结束符 \0;
- 如果格式化后的字符串长度大于 size,超过 size 的部分会被截断,只将其中的 (size-1) 个字符复制到 str 中,并给其后添加一个字符串结束符 \0,返回值为欲写入的字符串长度。
#include <stdio.h>
int main()
{
char buffer[50];
char* s = "runoobcom";
// 读取字符串并存储在 buffer 中
int j = snprintf(buffer, 6, "%s\n", s);
// 输出 buffer及字符数
printf("string:\n%s\ncharacter count = %d\n", buffer, j);
return 0;
}
// 结果:
string:
runoo
character count = 10
五、strdup()
- 函数原型:char* strdup (const char *s);
- strdup 函数会调用 malloc 分配足够长度的内存并返回。
- 需要在你不使用的时候 free 它。
- 要进行返回值检查。