字符串操作函数

1.  strcpy和strncpy。

功能演示;

a)  strcpy函数。

strcpy函数在C语言中被定义为不安全字符串拷贝函数,一般项目中都不允许使用。

原型:char *strcpy(char *dest, const char *src);

该函数不检查长度,若原字符传src的长度大于目的字符串dst的长度,拷贝则会出现数组越界,编译不会出现问题,运行就会段错误,因此不

建议使用该函数,除非能很好的控制。

b) strncpy函数。

strncpy被经常使用,因为该函数会有长度控制。

原型:char *strncpy(char *dest, const char *src, size_t n);

和strcpy不同的是多了一个size_t类型的参数,该参数表示要从src开始的地方拷贝n字节长度的数据到dst中,但是如果原字符串长度大于目的

字符串dst的长度,那么就会和strcpy一样,因此实际操作中n的长度为目的字符串dest长度 - 1.

为什么传入长度为目的字符串长度 - 1,如下演示例子,strncpy拷贝字符串并不会在末尾加上'\0'字符,因此一般留一个字节加'\0'结束符。

有的时候可以看到strlcpy函数,这个函数在低内核版本还不是Linux库函数,高版本是否加入未验证过,有兴趣的可以看下。

CHAR szbuf[6];
strncpy(szbuf,"012345678", sizeof(szbuf)); 

Before Copy FF FF FF FF FF FF FF FF // szbuf内容
After Copy 30 31 32 33 34 35 FF FF // 没有结尾\0

CHAR szbuf[6]; 
strncpy(szbuf, "0123", sizeof(szbuf)); 

Before Copy FF FF FF FF FF FF FF FF // szbuf内容
After Copy 30 31 32 33 00 00 FF FF // 修改了整个目的缓冲区
由上面的例子可以看出,strncpy也不是很完美,它在拷贝前会将整个缓冲区全清零,当然这个很多时候都被忽略的,因为在实际写代码过程中

我们申请一个数组,第二步初始化时就是一个memset将缓冲区清零了。

如果考虑到效率问题,最有效的初始化数组的方式如下:

char szBuff[512];
szBuff[0] = '\0';

只清零第一个字节时防止被误用,因为对字符串操作时就会用到strlen函数计算长度。

在实际开发中字符串操作都是自己封装接口,例如:

size_t My_Strcpy(OUT CHAR *pcDst, IN const CHAR *pcSrc, IN size_t ulDstSize)
{
    size_t ulSrcLen;
    size_t ulCpyLen;

    ulSrcLen = strlen(pcSrc);

    if ( 0 != ulDstSize)
    {
        ulCpyLen = (ulSrcLen >= ulDstSize) ? (ulDstSize - 1) : ulSrcLen;
        memcpy(pcDst, pcSrc, ulCpyLen);
        pcDst[ulCpyLen] = '\0';
    }
    return (size_t)ulSrcLen;
}
OUT、IN标示参数的输入输出,无实际意义。

2.  strcat和strncat。

功能演示:

strcat、strncat和strcpy、strlcpy很类似。

a) strcat函数。

原型:char *strcat(char *dest, const char *src);

strcat如果拼接长度控制不好会出现拼接越界。

b) strncat函数。

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

Before strncat 30 31 00 FF FF FF B0 84 // szbuf内容
After strncat 30 31 32 33 34 35 00 84 // 写越界一个字节

char szbuf[6]; 
strlcpy(szbuf, "01", sizeof(szbuf));
strncat(szbuf, "23", sizeof(szbuf)-strlen(szbuf));

Before strlcat 30 31 00 FF FF FF B0 84 // szbuf内容
After strlcat 30 31 32 33 00 FF B0 84

跟strncpy类似,如果拼接越界会截取字符串,但是末尾不会加'\0'字符,拼接时也会将缓冲区清零。

实际开发中自己封装一个anqua

3. snprintf函数和vsnprintf。

功能演示:

a)snprintf函数.

原型:int snprintf(char *str, size_t size, const char *format, ...);

snprinf接口主动加'\0',拼接时若源字符串较长,则截断拷贝,向目的buf拷贝size - 1个字符,然后加'\0',但返回长度是源字符串的

长度(不是实际写入的字符串长度)

char szBuf[5];
len = snprintf(szBuf, sizeof(szBuf), "%s", "1234567");
printf(" len : %d\r\n szBuf: %s\r\n", len, szBuf);

输出:
len : 7
szBuf: 1234

所以,该接口在累加拼装字符串时要保证缓冲区足够大。否则,可能写越界。如下:
char szBuf [10];
int len = 0; 
int max = 10;
len += snprintf (szBuf +len, max-len, "%s", "12345"); // max-len = 10 
len += snprintf (szBuf +len, max-len, "%s", "123456"); // max-len = 5
len += snprintf (szBuf +len, max-len, "%s", "12345"); // max-len = -1
len += snprintf (szBuf +len, max-len, "%s", "12345");

Segmentation fault.

b) vsnprintf函数。

原型:int vsnprintf(char *str, size_t size, const char *format, va_list ap);

snprinf接口主动加'\0',拼接时若源字符串较长,则截断拷贝,向目的buf拷贝size - 1个字符,然后加'\0',返回最终生成的字符

串长度。

char szBuf[512];
long ulCnt = 0;

szBuf [0] = '\0';
ulCnt += (long)nsprintf(szBuf + ulCnt, sizeof(szBuf) - ulCnt, "%s ", szIfName);
ulCnt += (long)nsprintf(szBuf + ulCnt, sizeof(szBuf) - ulCnt, "%4d ", uiVlanID);
ulCnt += (long)nsprintf(szBuf + ulCnt, sizeof(szBuf) - ulCnt, "%4d ", uiIfIndex);






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值