C的strncpy和snprintf (是否補充最后字符串結尾)


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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM