好的,不知道又過了幾天(廢),終於要來到第 5 篇了。
strcat
、strncat
:串接字串
所屬標頭檔:<string.h>
函式宣告:
char *strcat( char *dest, const char *src );
char *strncat( char *dest, const char *src, size_t count );
看到這熟悉的命名,該不會跟 strcpy()
、strncpy()
那組函式很像吧?沒錯,所以按照上次的慣例,我們先來看看 strcat()
。
strcat()
有兩個參數,分別是 dest 和 src,而這個函式的功用是將 src 接到 dest 後面,再回傳 dest 指向的字串。那你可能會問:那原本 dest 的 \0
字元會跑去哪呢?答案是會被 src 的第一個字元(也就是 src[0]
)所取代,並在最後面補上一個 \0
來當做新字串的結束字元。
看到名字多了一個 n 的函式,你可能會猜,是不是這個 strcat()
也會造成緩衝區溢位的問題呢?沒錯,所以接下來要介紹比較推薦的函式:strncat()
。
如果有看過之前那一篇的話,應該都已經知道這個函式要怎麼用了,他會多接受一個整數,作為控制最多串接的字元數。不過這裡的機制跟 strcpy()
有點不一樣:
- 無論如何都會在最後放一個
\0
,而這個\0
並不受 count 的限制。也就是說,真正串接字元數的最大值其實是 count + 1。
讓我們來看看他們的使用範例:
#include <stdio.h>
#include <string.h>
int main(){
// strcat
char s1[8] = "hi ", s2[8] = "sky";
strcat(s1, s2);
printf("%s\n\n", s1);
// strncat
char s3[8], s4[8];
scanf("%s%s", s4, s3);
printf("s3: %s\ns4: %s\n", s3, s4);
strncat(s4, s3, 4);
printf("s3: %s\ns4: %s\n", s3, s4);
return 0;
}
strncat()
部分的輸入可分別使用以下四種:
1234 123
1234 1234
1234 12345
12345 12345
至於結果會如何,就請大家自己試一試囉XD
這裡需要知道的地方是,s3 和 s4 的記憶體配置情況,通常會是像下圖這樣:
Undefined Behavior
在使用這兩個函式時,也可能會造成 undefined behavior,以下列舉出可能的情況:
strcat
- 緩衝區溢位(其實是 dest 不夠長)
- dest 和 src 有重疊的部分
- 如果 dest 或是 src 指向的字串沒有以
\0
結尾
strncat
- dest 不夠長(包含最後多放的
\0
) - dest 和 src 有重疊的部分
- 如果 src 不是指向一個字串
- 如果 dest 指向的字串沒有以
\0
結尾
這個部分在 C99 已受到限制:宣告中新增了 restrict
關鍵字,對於這個關鍵字有興趣的人可以自己查查看。
其實這次我對 strncat()
那邊的解說有點不太滿意,但也想不出能更簡潔說明的方法了qwq,希望大家還是能透過實作一次了解這個函式的特色。
另外,最近的更新頻率應該會降低許多(好像從來沒有高過),因為開學了而且還要準備升大學的資料。總之,就加油吧! (三年前)
參考資料:
- cppreference - strcat
- cppreference - strncat
- 最近有點混亂的腦袋