string.h里面几个安全函数的比较snprintf strncpy strncat

在字符串处理过程中会常用到以下几个函数
strcpy() sprintf() strcat() 
但它们都存在一定的安全隐患,相对应用的安全版本为:
strncpy() snprintf() strncat()

int sprintf( char *buffer, const char *format, [ argument] … ) ;
int snprintf(char *str, size_t size, const char *format, ...);

此两函数功能:把格式化的数据写入某个字符串.
返回值:字符串长度( strlen )

首先让我们来看下 sprintf()函数
Example
/* sprintf example */
#include <stdio.h>

int main (int argc, char *argv[])
{
	char buffer [50];
	int n, a=5, b=3;
	n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
	printf ("[%s] is a %d char long string\n",buffer,n);
	return 0;
}
Example Output:
[5 plus 3 is 8] is a 13 char long string 

关于 sprintf() 不安全问题,主要由其参数决定,
(1) 缓冲区溢出,char *buffer多大多小难以预测.
(2) printf习惯造成的忘记第一个参数
(3) 参数对应问题,相对容易检查

snprintf();
函数说明:最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n的话,是不会溢出。
函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。
#include <stdio.h>

int main()
{
     char str[10]={0,};
     snprintf(str, sizeof(str), "0123456789012345678");	//如果使用sprintf()将会出错
	 printf("str=%s\n", str);
	 //snprintf(str, 18, "0123456789012345678");		//也能成功,但是不推荐使用
     printf("str=%s\n", str);
     return 0;
}
Example Output:
str=123456789
str=12345678901234567


提到sprintf()不得不说到在格式化时间的时候还有 sprintf 的孪生兄弟 strftime.
size_t strftime ( char * ptr, size_t maxsize, const char * format, const struct tm * timeptr );
Example:
/* strftime example */
#include <stdio.h>
#include <time.h>

int main (int argc, char *argv[])
{
	time_t rawtime;
	struct tm * timeinfo;
	char buffer [80];

	time (&rawtime);
	timeinfo = localtime ( &rawtime );

	strftime(buffer,80,"Now it's %Y%m%d%H%M%S",timeinfo);
	puts(buffer);

	return 0;
}
Example output:
Now it's 20120701170808

extern char *strcat(char *dest,char *src);
函数说明:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'.
src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串.
函数返回值:返回指向dest的指针。

extern char *strncat(char *dest,char *src,size_t n);
函数说明:把src所指字符串前n个字符添加添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'.
src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串.
函数返回值:返回指向dest的指针。

char* strncat(char *dest,char *src,size_t n)
{
	size_t dest_len = strlen(dest);
	size_t i;
	for (i = 0; i < n && src[i] != '\0' ; i++ )
	{
		dest[dest_len + i] = src[i];
	}
	dest[dest_len + i] = '\0';

	return dest;
}

char *strcat(char *strDest, const char *strSrc)
{
	char *address = strDest; 
	assert((strDest != NULL) && (strSrc != NULL)); 
	while(*strDest) 
	{ 
		strDest++; 
	} 
	while(*strDest++ = *strSrc++)
	{
		NULL; 
	}
	return address;
}


char *strcpy(char *dest, char *src);
char *strncpy(char *dest, char *src, size_t n);

strcpy只用来拷贝字符串,它遇到'\0'就结束拷贝。
strncpy将字符串src中最多n个字符复制到字符数组dest中,与strcpy不同只有遇到NULL才停止复制
而是多了一个条件停止,就是说如果复制到第n个字符还未遇到NULL,也停止,返回指向dest的指针
但是如n>strlen(dest)的长度,dest栈空间溢出产生崩溃异常
char *strcpy(char *dest, const char *src)
{
	char *p = dest;

	while (*src)
		*dest++ = *src++;

	*dest = '/0';
	return p;
}
strncpy 标准用法
strncpy(path,src,sizeof(path)-1);
path[sizeof(path)-1] = '\0';
len = strlen(path);


转载于:https://my.oschina.net/u/198124/blog/65109

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值