<string.h>(C++ 為 <cstring>)提供了核心字串操作函式。本文整理 9 大類常用函式,附上參數說明、回傳值、邊界條件與完整可編譯範例,作為開發時的快速參考手冊。
| 類別 | 函式 | 功能 | 關鍵備註 |
|---|---|---|---|
| 複製 | strcpy(s1, s2) | 複製整個字串 | s1 必須足夠大,無邊界檢查 |
| strncpy(s1, s2, n) | 最多複製 n 字元 | 若 s2 長度 < n,補 '\0' 至 n;若 ≥ n,不自動加結尾 '\0' | |
| 連接 | strcat(s1, s2) | 將 s2 附加至 s1 末尾 | s1 需有足夠空間,覆蓋原結尾 '\0' |
| strncat(s1, s2, n) | 最多附加 n 字元 | 同樣需確保空間足夠 | |
| 比較 | strcmp(s1, s2) | 字典序比較 | 回傳 0(相等)、<0(s1 |
| strncmp(s1, s2, n) | 比較前 n 字元 | 同上,僅比較前 n 字元 | |
| 分割 | strtok(s1, s2) | 依 s2 字元集分割 s1 | 破壞原字串、非執行緒安全、首次傳 s1 之後傳 NULL |
| 長度 | strlen(s) | 回傳字元數(不含結尾 '\0') | O(n) 掃描,頻繁呼叫建議快取 |
| 搜尋 | strchr(s, c) / strrchr(s, c) | 尋找字元 c 首次/最後出現位置 | 回傳指標或 NULL |
| strstr(s1, s2) | 尋找子字串 s2 在 s1 中位置 | 回傳指標或 NULL | |
| 轉換 | strlwr/strupr | 轉小寫/大寫(非標準,MSVC 為 _strlwr/_strupr) | 就地修改,C++ 建議用 std::transform + toupper/tolower |
// string_demo.cpp
#include
#include // C++ 標準頭檔
using namespace std;
int main()
{
char str1[50] = "Happy birthday to ";
char str2[] = "coffeehu";
char temp1[100], temp2[6], *temp;
char str[] = "This is a sentence with 7 tokens";
// 1. strcpy / strncpy
strcpy(temp1, str1);
strncpy(temp2, str1, 5);
temp2[5] = '\0'; // strncpy 不保證結尾 null,手動補上
cout << "strcpy result: " << temp1 << "\n";
cout << "strncpy result: " << temp2 << "\n";
// 2. strcat / strncat
cout << "strcat result: " << strcat(str1, str2) << "\n";
// 注意:str1 已變更,strncat 會接在新尾端
cout << "strncat result: " << strncat(str1, str2, 6) << "\n";
// 3. strcmp / strncmp
cout << "strcmp result: " << strcmp(temp2, "Happ") << "\n"; // temp2="Happy" > "Happ" → 正數
cout << "strncmp result: " << strncmp(str1, "Happy", 5) << "\n"; // 比較前 5 字元
// 4. strtok 分割
cout << "strtok tokens:\n";
temp = strtok(str, " ");
while (temp != NULL)
{
cout << temp << '\n';
temp = strtok(NULL, " ");
}
// 5. strlen
cout << "strlen result: " << strlen(str2) << "\n";
return 0;
}
strcpy result: Happy birthday to strncpy result: Happy strcat result: Happy birthday to coffeehu strncat result: Happy birthday to coffeehu coffee strcmp result: 1 strncmp result: 0 strtok tokens: This is a sentence with 7 tokens strlen result: 8
| C 函式 | 風險 | C11 Annex K 安全版 | 現代 C++ 建議 |
|---|---|---|---|
| strcpy | 緩衝區溢位 | strcpy_s | std::string / std::strcpy (配合 size 檢查) |
| strcat | 緩衝區溢位 | strcat_s | std::string::operator+= |
| strncpy | 可能缺結尾 null | strncpy_s | std::string::substr / assign |
| strtok | 破壞原串、非執行緒安全 | strtok_s | std::stringstream, std::regex, boost::split |
| sprintf | 格式化溢位 | sprintf_s | std::format (C++20), fmt::format, snprintf |
strlen/printf 會越界。→ 總是手動 dest[n-1] = '\0' 或用 strncpy_s。strcpy 到暫存緩衝區再分割。strtok_s (C11) 或 strtok_r (POSIX)。char* s = "hello"; s[0] = 'H'; → 未定義行為。→ 用 char s[] = "hello"; 或 std::string。strlen 為 O(n),迴圈中重複呼叫極慢。→ 迴圈前快取長度:size_t len = strlen(s); for(i=0;i。 std::ostringstream 或預先 reserve 的 std::string,避免重複 strcat 導致 O(n²)。strncmp 或 memcmp,避免完整掃描。熟練掌握這些基礎字串函式的行為邊界,是寫出健壯、高效 C/C++ 程式的基石。