在字符串處理過程當中會經常使用到如下幾個函數 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);