字符串操作函数

来源:互联网 发布:蓝凌软件下载 编辑:程序博客网 时间:2024/05/22 11:32

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 // 没有结尾\0CHAR 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 : 7szBuf: 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 = 5len += snprintf (szBuf +len, max-len, "%s", "12345"); // max-len = -1len += 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);