字串複製:strcpy()、strncpy()

  每次都為了有沒有包含字串結尾字元「\0」而煩惱,就做個筆記吧。

前言:sizeof()與strlen()

  進入正題前,先看看字串長度,順便複習陣列和指標。 #include <stdio.h> #include <string.h> void main() { char arr1[] = {'1', '2', '3', '\0'}; char arr2[] = "123"; char *ptr = "123"; printf("--- arr1 ---\n"); printf("length of string : %lu\n", strlen(arr1)); printf("size of array : %lu\n", sizeof(arr1)); printf("--- arr2 ---\n"); printf("length of string : %lu\n", strlen(arr2)); printf("size of array : %lu\n", sizeof(arr2)); printf("--- ptr_arr1 ---\n"); printf("length of string : %lu\n", strlen(&arr1[0])); printf("size of pointer : %lu\n", sizeof(&arr1[0])); printf("--- ptr ---\n"); printf("length of string : %lu\n", strlen(ptr)); printf("size of pointer : %lu\n", sizeof(ptr)); } 輸出如下: --- arr1 --- length of string : 3 size of array : 4 --- arr2 --- length of string : 3 size of array : 4 --- ptr_arr1 --- length of string : 3 size of pointer : 8 --- ptr --- length of string : 3 size of pointer : 8   arr1和arr2是等效的,只是若要用arr2的宣告方式,要#include <string.h>。strlen()回傳長度不包含串結尾字元「\0」,sizeof()輸入若為陣列,才不管裡面的值是什麼,一律回傳整個陣列宣告長度;sizeof()輸入若為指標,將回傳儲存一個位址所需要的大小,在64位元的作業系統中,是8-Byte,也就是64-bit。

strncpy()

函式宣告 char *strncpy(char *dest, const char *src, size_t n); 測試範例 #include <stdio.h> #include <string.h> void main() { char src[] = "1234"; char arr[7]; int i, n; for (n = 0; n <= sizeof(arr); n++) { memset(arr, 0xff, sizeof(arr)); printf("N = %2d: ", n); strncpy(arr, src, n); for (i = 0; i < sizeof(arr); i++) { if (arr[i] == (char)0xff) printf("%c ", '.'); else if (arr[i] == '\0') printf("%c ", '_'); else printf("%c ", arr[i]); } printf("\n"); } } 輸出如下:
顯示「.」代表未改變,保持原始值。
顯示「_」代表字串結尾字元「\0」。
N = 0: . . . . . . . N = 1: 1 . . . . . . N = 2: 1 2 . . . . . N = 3: 1 2 3 . . . . N = 4: 1 2 3 4 . . . N = 5: 1 2 3 4 _ . . N = 6: 1 2 3 4 _ _ . N = 7: 1 2 3 4 _ _ _   若N超出strlen(src),會補'\0',若想src[]全部複製,可以選擇N = strlen(src) + 1即可,若想讓陣列看起來更乾淨,可以選擇N = sizeof(arr)。

strcpy()

函式宣告 char *strcpy(char *dest, const char *src); 測試範例 #include <stdio.h> #include <string.h> void main() { char src[] = "1234"; char arr[7]; int i, n; memset(arr, '.', sizeof(arr)); strcpy(arr, src); for (i = 0; i < sizeof(arr); i++) { if (arr[i] == '\0') printf("%c ", '_'); else printf("%c ", arr[i]); } printf("\n"); } 輸出如下:
顯示「.」代表未改變,保持原始值。
顯示「_」代表字串結尾字元「\0」。
1 2 3 4 _ . .   使用strcpy(arr, src)的效果,與strncpy(arr, src, strlen(src) + 1)等效。

溢位

  使用strcpy(),當strlen(src) + 1 > sizeof(arr),超出陣列arr的範圍會照樣複製,例如: char src[] = "1234"; char arr[4]; strcpy(arr, src); 得到的arr將是
'1' '2' '3' '4' '\0'
紅底格子為溢位的位址。
  使用strncpy(),當n > sizeof(arr),超出陣列arr的範圍會照樣複製或補'\0',例如: char src[] = "1234"; char arr[7]; size_t n = 10; strncpy(arr, src, n); 得到的arr將是
'1' '2' '3' '4' '\0' '\0' '\0' '\0' '\0' '\0'
紅底格子為溢位的位址。建議strncpy的n參數選用sizeof(arr),就可以確保程式安全,不會改動到陣列arr[]範圍以外的值。

留言

這個網誌中的熱門文章

私有IP

echo "text" > file 發生 Permission denied

Git指令彙整