Chinaunix首页 | 论坛 | 博客
  • 博客访问: 226184
  • 博文数量: 75
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 848
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-08 10:27
文章分类
文章存档

2014年(9)

2013年(66)

我的朋友

分类: C/C++

2013-11-13 15:31:13

C里操作字符串很高效,但也很麻烦。


1. char * strcpy ( char * destination, const char * source );


最常用的函数,但是却不安全,原因在于,一是要destination有足够的空间,二是要保证source和destination指向的空间没有overlap。


2. int sprintf ( char * str, const char * format, ... );


也许要问,这个怎么用于字符串拷贝呢?可以这么用 sprintf(dest, "%s", src); 但是要调用者保证dest有足够的内存存放src。


3. char * strncpy ( char * destination, const char * source, size_t num );


比起strcpy,多了个长度的控制。从source拷贝num个字符到destination。如果source里不够num字符怎么办呢?会补充0。


一个典型的用法是:


char buf[MAX]; 
strncpy(buf, src, MAX-1);


这段代码的本意是,一个长为MAX的buf,最多也就放MAX-1个字符,最后一个位置放‘\0'。因此最多能从src里拷贝MAX-1个字符,如果src里没这么多,剩余的填充0就是了。


但是这样做就安全了么?不是,如果src刚好MAX-1个字符。注意到strncpy只复制了MAX-1个字符,最后一个位置未知,有潜在的隐患。下段代码可以诠释:


#define MAX 4 
char buf[MAX]; 
char* src="123"; 
memset(buf, 'x', MAX);


// solution 1. memset(buf, 0, MAX); 
strncpy(buf, src, MAX-1); 
// solution 2. buf[MAX-1] = '\0';


printf("%s\n", buf);


有两个办法可以解决:1. 调用strncpy之前memset为0,有点浪费。2. 在strncpy之后对最后一个字符赋值为0。


都可以,但不够优雅。


4. int snprintf( char *buffer, int buff_size, const char *format, ... );


用作字符串拷贝的用法:


char buf[MAX]; 
snprintf(buf, sizeof(buf), "%s", src);


即安全,又简洁。


你可能会关心:如果src的长度大于dest(buf)呢?这个是另外一个问题,这里需要的是安全的字符串拷贝,在C语言里,如果一个字符串指针指向的内存没有结尾字符'\0',是非常危险的。


snprintf会把buf的最后一个位置保留为'\0'。


关于返回值:如果当前buf够用,返回实际写入的字符数;如果不够用,返回将要写入的字符数。换句话说,返回值就是传入的字符数目。


假设当前的buf[4].


待写入    实际写入    返回值 
12           12     2  够用 
123        123   3  够用 
1234     123   4  不够用 
12345  123   5  不够用


sprintf/snprintf的另外一个用法:


itoa不是ANSI C或C++的一部分,可以变相的用sprintf来代替:


sprintf(str,"%d",value) converts to decimal base. 
sprintf(str,"%x",value) converts to hexadecimal base. 
sprintf(str,"%o",value) converts to octal base.
阅读(1124) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~