1. 程式人生 > >strcpy、strncpy、strncpy_s和snprintf

strcpy、strncpy、strncpy_s和snprintf

1、strcpy

原型宣告: extern char *strcpy(char* dest, const char *src);

依據源串的\0作為結束判斷的,不會檢查需要拷貝的緩衝區的大小,如果目標空間不夠,就有溢位問題。

2、strncpy

原型

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

複製字串src中的內容(字元,數字、漢字....)到字串dest中,複製多少由size_t的值決定,返回指向dest的指標。如果遇到空字元('\0'),則空字元後面為原來的字元

程式碼如下:

dest[]="Hell99iam!";
src[]="abc\0def";
strncpy(dest,src,5);

此時,dest區域是這樣的:'a','b','c','\0','\0','9','i','a','m','!'

而非這樣:'a','b','c','\0','\0','\0','\0','\0','\0','\0'

'\0','\0'並不是新增在'!'的後面。可以用for迴圈輸出每個元素的ascii來確定。

strncpy是字串拷貝推薦的用法

3、strncpy_s

原型:
errno_t strncpy_s(
char *strDest,
size_t numberOfElements,
const char *strSource,
size_t count
);

引數numberOfElements表明dest中的位元組數,防止目標指標dest中的空間不夠,同時返回值改成返回錯誤程式碼,而不是返回char*。

會在字串結束處填補一個空字元。

count引數需要小於目標緩衝區大小。

如果情況如下程式碼:

char dst[5];
strncpy_s(dst, sizeof(dst), "a long string", 5);

表示使用strncpy_s 拷貝5個位元組到dst緩衝區,使得沒用多餘空間給空字元結束符,填補空字元時會溢位,並呼叫異常處理控制代碼。

需要補空字元時使用 _TRUNCATE 或者 (size – 1)

程式碼如下:

char dst[5];
strncpy_s(dst, sizeof(dst), "a long string", _TRUNCATE);
strncpy_s(dst, sizeof(dst), "a long string", sizeof(dst)-1);

跟strncpy不一樣,當count引數比源字串長時,strncpy_s 不會一直補空字元到指定長度。

如果源地址字串和目標地址字串重疊,則結果未定義。

_s版本函式並不是標準庫,不推薦使用

4、snprintf

原型:

int snprintf(char *str, size_t size, const char *format, ...)

將可變個引數(...)按照format格式化成字串,然後將其複製到str中

(1) 如果格式化後的字串長度 < size,則將此字串全部複製到str中,並給其後新增一個字串結束符('\0');

(2) 如果格式化後的字串長度 >= size,則只將其中的(size-1)個字元複製到str中,並給其後新增一個字串結束符('\0'),返回值為欲寫入的字串長度。

#include <stdio.h>
int main () {
  char a[16];
  size_t i;
  i = snprintf(a, 13, "%012d", 12345);  // 第 1 種情況
  printf("i = %lu, a = %s\n", i, a);    // 輸出:i = 12, a = 000000012345
 
  i = snprintf(a, 9, "%012d", 12345);   // 第 2 種情況
  printf("i = %lu, a = %s\n", i, a);    // 輸出:i = 12, a = 00000001
  return 0;
}