c语言:拷贝字符串

一、strcpy():容易溢出

  1. 头文件:#include <string.h>
  2. strcpy() 函数用来复制字符串;
  3. 其原型为:char *strcpy(char *dest, const char *src);
  4. strcpy()是依据 \0 作为结束判断的;
  5. 通常,我们的 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,效率和已有数据丢失

  1. strncpy()用来复制字符串的前n个字符;
  2. 其原型为: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()

  1. <stdio.h>
  2. 函数原型:int sprintf(char *str, const char *format, …);
  3. 返回值:如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。
#include <stdio.h>
#include <math.h>

int main()
{
   char str[80];
   sprintf(str, "Pi 的值 = %f", M_PI);
   return(0);
}

四、snprintf()

  1. <stdio.h>
  2. 函数原型: int snprintf(char *str, size_t size, const char *format, …)
  3. 设将可变参数(…)按照 format 格式化成字符串,并将字符串复制到 str 中,size 为要写入的字符的最大数目,超过 size 会被截断。
  4. 如果格式化后的字符串长度小于等于 size,则会把字符串全部复制到 str 中,并给其后添加一个字符串结束符 \0;
  5. 如果格式化后的字符串长度大于 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()

  1. 函数原型:char* strdup (const char *s);
  2. strdup 函数会调用 malloc 分配足够长度的内存并返回。
  3. 需要在你不使用的时候 free 它。
  4. 要进行返回值检查。
  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值