1. 前言 在 C 語言中,字串操作是學習程式設計時重要的技能之一。特別是,字串切割 (子字串的抽取)在處理資料與格式轉換時常被使用。 本文將詳細說明C 語言中字串切割的方法 ,包括使用標準函式庫函式的方法、自製函式的製作方法、對多位元組字元(日文)之支援、字串分割方法 等。此外,還會介紹應用範例與錯誤處理,請務必閱讀至最後。本文可學到的內容 閱讀本文後,您將掌握以下技能。C 語言字串的基本概念與終止字元 ' '
的作用 strncpy
與 strchr
等使用標準函式庫函式進行子字串切割 使用自製函式 的字串操作實作方法 考慮多位元組字元(日文)之UTF-8 與 Shift_JIS 字串處理 使用 strtok
的字串分割方法 取得特定字元前後的方法 及其應用範例 即使是初學者也能輕鬆理解,我們將結合程式碼範例進行說明。為何在 C 語言中字串切割很重要? C 語言將字串視為「陣列(char 型陣列)」 ,因此無法像其他高階語言(如 Python、JavaScript 等)那樣輕鬆取得子字串。因此,在以下情境中選擇適當的方法相當重要。1. 輸入資料的處理 例如,在解析日誌資料或 CSV 檔等資料時,需要抽取特定項目。2. 搜尋特定關鍵字 在字串中尋找特定關鍵字,並取得其前後資訊,對於搜尋功能與資料抽取是必不可少的。3. 提升程式安全性 透過適當使用 strncpy
等函式,可防止緩衝區溢位(寫入超過緩衝區大小的資料) 。這對於避免安全風險相當重要。本文結構 本文將依照以下流程說明。C 語言的字串是什麼?基本概念與終止字元的重要性 C 語言中子字串切割方法【標準函式庫篇】 C 語言中子字串切割方法【自製函式篇】 依照字元編碼的字串切割方法 C 語言中字串分割的方法 應用範例:取得特定字元前後的方法 總結 FAQ 那麼,首先讓我們詳細探討「C 語言的字串是什麼?基本概念與終止字元的重要性」。
2. C 語言的字串是什麼?基本概念與終止字元的重要性 2.1 C 語言字串的基本概念 字串是「char 陣列」 在 C 語言中,字串被視為字元陣列(char 型的陣列) 。例如,以下程式碼是字串定義與顯示的基本範例。#include <stdio.h>
int main() {
char str[] = "Hello, World!"; // 將字串常值定義為陣列
printf("%s
", str); // 輸出字串
return 0;
}
在此程式碼中,字串 "Hello, World!"
以 char
型的陣列儲存,並透過 printf("%s", str);
輸出。字串的內部結構 字串 "Hello"
在記憶體中會如下儲存。 在 C 語言中,表示字串結尾的特殊字元(空字元 ' '
)會自動在最後加入 ,因此字串長度為 「實際字元數 + 1」 。2.2 終止字元(空字元 ' '
)的重要性 什麼是空字元? 空字元(' '
)是表示字串結尾的特殊字元 。要正確處理 C 語言的字串,需要了解此空字元的存在。#include <stdio.h>
int main() {
char str[6] = {'H', 'e', 'l', 'l', 'o', ' '}; // 明確指定終止字元
printf("%s
", str); // 正確顯示
return 0;
}
在上述程式碼中,若沒有 ' '
,則 "Hello"
的結尾不會被識別,可能會發生未預期的行為 。缺少空字元時的問題 如以下所示,若忘記終止字元,可能會導致記憶體異常運作 。#include <stdio.h>
int main() {
char str[5] = {'H', 'e', 'l', 'l', 'o'}; // 未包含空字元
printf("%s
", str); // 發生未預期的行為
return 0;
}
錯誤的原因 printf("%s", str);
會持續輸出字元,直到找到空字元 ' '
。如果沒有 ' '
,可能會輸出記憶體中其他資料。 2.3 正確的字串定義方法 方法① 使用字串常值 最常見的字串定義方式是使用字串常值。char str[] = "Hello";
使用此方法時,C 編譯器會自動加入空字元 ' '
,因此不需要額外處理。方法② 明確定義陣列 若手動包含 ' '
進行定義,請如下寫法。char str[6] = {'H', 'e', 'l', 'l', 'o', ' '};
需要指定字元數 +1 的大小,並在最後加入 ' '
。 如果忘記在 str[5]
放入 ' '
,會發生未預期的行為。 2.4 確認字串大小的方法 要取得字串長度(字元數),請使用 strlen
函式。#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello";
printf("字串長度: %lu
", strlen(str)); // 輸出 5(不含空字元)
return 0;
}
strlen
的運作strlen
會計算直到出現空字元 ' '
為止的字元數 。與 sizeof(str)
不同,取得的是「實際字串的長度」而非陣列大小。 2.5 小結 C 語言的字串以 char
陣列表示 。終止字元(空字元 ' '
)表示字串結尾,必須包含 。取得字串長度請使用 strlen
。若未以適當方式定義字串,可能會發生未預期的錯誤 。3. C 語言中切割子字串的方法【標準函式庫篇】 在 C 語言中切割子字串,可以利用標準函式庫的方法。本節將說明使用 strncpy
與 strchr
等標準函式庫函式來部分取得字串的方法 。3.1 使用 strncpy
取得子字串 strncpy
是一個將字串的一部份複製到另一個緩衝區的函式 。strncpy
的基本語法char *strncpy(char *dest, const char *src, size_t n);
dest
: 複製目的地的緩衝區src
: 複製來源的字串n
: 要複製的最大字元數(不含 ' '
)基本使用範例 #include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6]; // 用於存放子字串的緩衝區
strncpy(dest, src, 5); // 複製前5個字元 "Hello"
dest[5] = ' '; // 手動加入空字元
printf("子字串: %s
", dest); // 輸出 "Hello"
return 0;
}
strncpy
的注意事項需要手動加入空字元 ' '
strncpy
會複製最多 n
個字元,但不會自動加入 ' '
,因此必須明確地加入 dest[n] = ' ';
。注意緩衝區溢位 如果 n
大於 dest
的大小,可能會寫入緩衝區之外。3.2 使用 strncpy_s
的安全字串複製 strncpy_s
是加強 strncpy
安全性的版本,可防止緩衝區溢位。strncpy_s
的基本語法errno_t strncpy_s(char *dest, rsize_t destsz, const char *src, rsize_t n);
dest
: 複製目的地的緩衝區destsz
: dest
的大小src
: 複製來源的字串n
: 要複製的最大字元數使用範例 #include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
if (strncpy_s(dest, sizeof(dest), src, 5) == 0) {
dest[5] = ' '; // 為了保險起見,加入空字元
printf("子字串: %s
", dest);
} else {
printf("複製錯誤
");
}
return 0;
}
strncpy_s
的優點可指定緩衝區大小 (destsz
),因此能安全複製。 如果 n
大於 destsz
,會回傳錯誤。 但需注意,strncpy_s
是在 C11 標準中加入的,部分環境可能無法使用。 3.3 使用 strchr
切割至特定字元 使用 strchr
可以找到特定字元的位置,並取得至該字元之前的字串。strchr
的基本語法char *strchr(const char *str, int c);
str
: 要搜尋的字串c
: 想要尋找的字元(char
型)使用範例 #include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
char *pos = strchr(str, ','); // 尋找 ',' 的位置
if (pos != NULL) {
int length = pos - str; // 計算至 ',' 的字元數
char result[20];
strncpy(result, str, length);
result[length] = ' '; // 加入空字元
printf("子字串: %s
", result); // 輸出 "Hello"
}
return 0;
}
要點 strchr
會回傳第一個找到的 c
的位址 ,因此可用來決定子字串的範圍。利用 pos - str
計算子字串長度,然後用 strncpy
複製,即可取得至特定字元的子字串。 3.4 使用 strstr
進行關鍵字搜尋與切割 strstr
用於搜尋子字串,並取得其之後的字串,非常方便。strstr
的基本語法char *strstr(const char *haystack, const char *);
haystack
: 要搜尋的字串needle
: 要搜尋的子字串使用範例 #include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
char *pos = strstr(str, "World"); // 搜尋 "World" 的位置
if (pos != NULL) {
printf("找到的子字串: %s
", pos);
} else {
printf("找不到子字串。
");
}
return 0;
}
要點 strstr
會回傳第一個找到的 needle
的指標。如果回傳 NULL
,表示 needle
不存在於 haystack
中。 3.5 總結 使用 strncpy
可以安全地複製子字串,但需要手動加入空字元。 strncpy_s
可以指定 destsz
,提升安全性。使用 strchr
可以取得至特定字元的子字串。 使用 strstr
可以取得特定關鍵字的位置,並切割其之後的字串。 活用標準函式庫,可在 C 語言中簡潔且安全地實作字串處理。
4. C語言切割子字串的方法【自製函式篇】 只要善用標準函式庫,就能進行基本的子字串切割,但視情況可能需要更彈性的方式 。因此,本節將說明使用自製函式的子字串切割 。4.1 製作自製函式的好處 使用標準函式庫可以進行子字串的複製與搜尋,但會有以下問題。strncpy
不會自動加入空字元 '\0'
strchr
與 strstr
只能進行部分搜尋更彈性的字串操作較為困難 因此,依據特定用途客製化的自製函式 是有效的做法。4.2 基本的子字串抽取函式 首先,建立一個從指定位置切割字串的基本函式。函式規格 參數 const char *source
(原始字串)int start
(起始位置)int length
(要切割的字元數)char *dest
(存放切割後字串的緩衝區)處理內容 將從 start
起的 length
個字元複製到 dest
自動加入 '\0'
實作程式碼 #include <stdio.h>
#include <string.h>
void substring(const char *source, int start, int length, char *dest) {
int i;
for (i = 0; i < length && source[start + i] != ' '; i++) {
dest[i] = source[start + i];
}
dest[i] = ' '; // 加入空字元
}
int main() {
char text[] = "Hello, World!";
char result[10];
substring(text, 7, 5, result); // 切割 "World"
printf("子字串: %s
", result);
return 0;
}
要點 for
迴圈會複製指定的 length
個字元。遇到 ' '
時結束迴圈。 加入 dest[i] = ' ';
,確保一定在末尾放置空字元 。 4.3 malloc
用於動態子字串取得 在上述函式中,需要事先確保 dest
的大小。但若能動態分配所需大小,函式會更通用。函式規格 使用 malloc
取得所需記憶體 將從 start
起的 length
個字元子字串複製到新緩衝區 呼叫端必須使用 free
釋放 實作程式碼 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *substring_dynamic(const char *source, int start, int length) {
char *dest = (char *)malloc(length + 1); // 為了空字元 +1
if (dest == NULL) {
return NULL; // 記憶體分配失敗時
}
int i;
for (i = 0; i < length && source[start + i] != ' '; i++) {
dest[i] = source[start + i];
}
dest[i] = ' ';
return dest;
}
int main() {
char text[] = "Hello, World!";
char *result = substring_dynamic(text, 7, 5);
if (result != NULL) {
printf("子字串: %s
", result);
free(result); // 釋放記憶體
} else {
printf("記憶體分配失敗。
");
}
return 0;
}
要點 使用 malloc
動態分配記憶體 ,因此不必在意緩衝區大小。 使用完畢後需以 free(result);
釋放記憶體。 4.4 多位元組字元(日本語)支援 在處理日文(UTF-8 等多位元組字元)時,因為一個字元不一定是 1 位元組 ,單純的 substring
函式無法正確運作。考慮多位元組字元的實作 使用 mbstowcs
,將多位元組字串轉換為寬字元字串(wchar_t
) 使用 wcsncpy
取得子字串 使用 wcstombs
再轉回多位元組字串 實作程式碼(UTF-8 支援) #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>
void substring_utf8(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, ""); // 設定 locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // 將 UTF-8 字串轉換為寬字元字串
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // 使用寬字元字串切割
wresult[length] = L' ';
wcstombs(dest, wresult, 256); // 轉回多位元組字串
}
int main() {
char text[] = "こんにちは、世界!"; // UTF-8 字串
char result[20];
substring_utf8(text, 5, 3, result); // 取得 "世界"
printf("子字串: %s
", result);
return 0;
}
要點 使用 setlocale(LC_ALL, "");
設定 locale,以支援多位元組。 使用 mbstowcs
將多位元組字串轉換為寬字元字串。 使用 wcsncpy
取得子字串後,wcstombs
再轉回多位元組字串。 4.5 小結 自製 substring
函式即可彈性取得子字串。 使用動態記憶體分配 (malloc
),即可取得可變大小的子字串。 處理多位元組字元(如日文)時,活用 mbstowcs
/ wcstombs
。 若標準函式庫的 strncpy
或 strchr
難以應對時,透過自製函式即可讓 C 語言的字串處理更為強大。
5. 依照字元編碼的字串切割方法 在 C 語言中,如果不注意字元編碼的差異,字串切割處理可能無法正確運作。特別是處理像日文這樣的多位元組字元(UTF-8、Shift_JIS、EUC-JP 等)時,因為一個字元不等於一個位元組,單純使用 strncpy
或 substring
函式無法適當處理。 本節將詳細說明依照字元編碼的字串切割方法 。5.1 ASCII(單位元組字元)的情況 基本的子字串取得 ASCII 文字因為 1字元 = 1位元組 ,所以可以使用 strncpy
或 substring
函式輕鬆處理。實作範例 #include <stdio.h>
#include <string.h>
void substring_ascii(const char *source, int start, int length, char *dest) {
strncpy(dest, source + start, length);
dest[length] = ' '; // 加入 NUL 字元
}
int main() {
char text[] = "Hello, World!";
char result[6];
substring_ascii(text, 7, 5, result); // "World" 取得
printf("子字串: %s\n", result);
return 0;
}
重點 對於 ASCII 文字(僅英數字)的情況,使用 strncpy
已足夠應對 必須一定要加入 ' '
(NUL 字元) 5.2 UTF-8(多位元組字元)的情況 UTF-8 的特性 在 UTF-8 中,單一字元的位元組數為 1~4 位元組 可變,若直接使用 strncpy
可能會在字元中間被截斷。正確的處理方法 在 C 語言中,若要安全處理 UTF-8,建議使用 mbstowcs
轉換成寬字元字串(wchar_t
) ,再取得子字串。支援 UTF-8 的子字串取得 #include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_utf8(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, ""); // 設定 locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256); // 將多位元組字串轉換為寬字元字串
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length); // 取得子字串
wresult[length] = L' ';
wcstombs(dest, wresult, 256); // 再次將寬字元字串轉換回多位元組字串
}
int main() {
char text[] = "こんにちは、世界!"; // UTF-8 字串
char result[20];
substring_utf8(text, 5, 3, result); // "世界" 取得
printf("子字串: %s\n", result);
return 0;
}
重點 如果不使用 setlocale(LC_ALL, "");
設定 locale,則多位元組字元無法正確處理。 使用 mbstowcs
將多位元組字串轉換為 wchar_t
,再以 wcsncpy
安全處理。 使用 wcstombs
再次將寬字元字串轉回多位元組字串。 5.3 Shift_JIS(多位元組字元)的情況 Shift_JIS 的特性 在 Shift_JIS 中,1字元可能是 1 位元組或 2 位元組 ,因此直接使用 strncpy
會導致文字亂碼。支援 Shift_JIS 的子字串取得 在 Shift_JIS 的情況下,也建議使用 轉換為寬字元字串後處理的方法 。Shift_JIS 的實作 #include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_sjis(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, "Japanese"); // 設定處理 Shift_JIS 的 locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256);
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length);
wresult[length] = L' ';
wcstombs(dest, wresult, 256);
}
int main() {
char text[] = "こんにちは、世界!"; // Shift_JIS 字串(視環境而定)
char result[20];
substring_sjis(text, 5, 3, result);
printf("子字串: %s\n", result);
return 0;
}
重點 若要正確處理 Shift_JIS,需設定 setlocale(LC_ALL, "Japanese");
。 使用 mbstowcs
與 wcstombs
,安全處理字串。 5.4 EUC-JP(多位元組字元)的情況 EUC-JP 的特性 EUC-JP 亦如同 Shift_JIS,因為每個字元的位元組數不同,需要使用寬字元進行轉換處理 。支援 EUC-JP 的子字串取得 #include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
void substring_eucjp(const char *source, int start, int length, char *dest) {
setlocale(LC_ALL, "ja_JP.eucJP"); // 設定處理 EUC-JP 的 locale
wchar_t wsource[256];
mbstowcs(wsource, source, 256);
wchar_t wresult[256];
wcsncpy(wresult, wsource + start, length);
wresult[length] = L' ';
wcstombs(dest, wresult, 256);
}
int main() {
char text[] = "こんにちは、世界!"; // EUC-JP 字串(視環境而定)
char result[20];
substring_eucjp(text, 5, 3, result);
printf("子字串: %s\n", result);
return 0;
}
重點 使用 setlocale(LC_ALL, "ja_JP.eucJP");
設定 EUC-JP 的 locale。 使用 mbstowcs
/ wcstombs
正確處理多位元組字元。 5.5 總結 字元編碼 位元組數 建議的處理方法 ASCII 1 位元組 strncpy
可行UTF-8 1~4 位元組 使用 mbstowcs
/ wcstombs
Shift_JIS 1 或 2 位元組 使用 mbstowcs
/ wcstombs
EUC-JP 1 或 2 位元組 使用 mbstowcs
/ wcstombs
如果僅是 ASCII 文字,strncpy
可行 對於 UTF-8、Shift_JIS、EUC-JP,使用 mbstowcs
/ wcstombs
依環境適當設定 setlocale(LC_ALL, "...");
6. C 語言中字串分割的方法 字串分割的處理在 CSV 資料的解析、命令列參數處理、日誌資料的解析 等多種情況下都是必需的。C 語言中,有使用 strtok
與 strtok_r
等標準函式庫函式的方法,也有自行撰寫函式的方法。 本節將詳細說明 以特定分隔字元分割字串的方法 。6.1 使用 strtok
的字串分割 strtok
是一個以 指定的分隔字元(分隔符)分割字串 的函式。基本語法 char *strtok(char *str, const char *delim);
str
:要分割的字串(在第一次呼叫時指定)delim
:分隔字元(可指定多個)返回值 :第一個 token(分割後的第一段)注意點 :strtok
會修改原始字串(將分隔字元改為 ' '
)使用範例:以逗號 ,
分割字串 #include <stdio.h>
#include <string.h>
int main() {
char str[] = "apple,banana,orange,grape"; // 要分割的字串
char *token = strtok(str, ","); // 取得第一個 token
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok(NULL, ","); // 取得下一個 token
}
return 0;
}
執行結果 Token: apple
Token: banana
Token: orange
Token: grape
strtok
的注意點會修改原始字串 strtok
會 將分隔字元改寫為 ' '
,因此原始字串會遺失。不是執行緒安全的 strtok
在內部使用全域靜態變數 ,因此在多執行緒環境下不建議使用。6.2 使用 strtok_r
的執行緒安全字串分割 strtok_r
是 strtok
的執行緒安全版,因為將狀態保存於 saveptr
,所以在多執行緒環境中也能安全使用 。基本語法 char *strtok_r(char *str, const char *delim, char **saveptr);
str
:要分割的字串(在第一次呼叫時指定)delim
:分隔字元(可指定多個)saveptr
:保存內部狀態的指標(每次呼叫會更新)使用範例:以空格分割字串 #include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello World from C"; // 要分割的字串
char *token;
char *saveptr; // 保存內部狀態的指標
token = strtok_r(str, " ", &saveptr); // 取得第一個 token
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok_r(NULL, " ", &saveptr); // 取得下一個 token
}
return 0;
}
strtok_r
的優點6.3 使用自製函式分割字串(不使用 strtok
的方法) strtok
會修改原始字串,因此也可以建立不改變字串的自製函式來分割字串。自製函式的規格 輸入 const char *source
(原始字串)const char delim
(分隔字元)char tokens[][50]
(用來存放分割後字串的陣列)處理 複製 source
,以免修改原始字串 根據 delim
將分割結果存入 tokens
實作程式碼 #include <stdio.h>
#include <string.h>
void split_string(const char *source, char delim, char tokens[][50], int *count) {
int i = 0, j = 0, token_index = 0;
while (source[i] != ' ') {
if (source[i] == delim) {
tokens[token_index][j] = ' ';
token_index++;
j = 0;
} else {
tokens[token_index][j] = source[i];
j++;
}
i++;
}
tokens[token_index][j] = ' ';
*count = token_index + 1;
}
int main() {
char text[] = "dog,cat,bird,fish";
char tokens[10][50]; // 最多可容納 10 個單詞
int count;
split_string(text, ',', tokens, &count);
for (int i = 0; i < count; i++) {
printf("Token: %s\n", tokens[i]);
}
return 0;
}
執行結果 Token: dog
Token: cat
Token: bird
Token: fish
要點 source
不修改,先建立副本再處理。將分割結果存入 tokens
陣列,保留原始字串。 6.4 字串分割的應用(CSV 資料處理) 可以使用 strtok
解析 CSV(逗號分隔)資料。CSV 資料解析範例 #include <stdio.h>
#include <string.h>
int main() {
char csv[] = "Alice,24,Female\nBob,30,Male\nCharlie,28,Male"; // CSV 資料
char *line = strtok(csv, "\n"); // 逐行處理
while (line != NULL) {
char *name = strtok(line, ",");
char *age = strtok(NULL, ",");
char *gender = strtok(NULL, ",");
printf("姓名: %s, 年齡: %s, 性別: %s\n", name, age, gender);
line = strtok(NULL, "\n");
}
return 0;
}
執行結果 姓名: Alice, 年齡: 24, 性別: Female
姓名: Bob, 年齡: 30, 性別: Male
姓名: Charlie, 年齡: 28, 性別: Male
6.5 總結 方法 優點 缺點 strtok
可以簡單分割 會修改原始字串 strtok_r
執行緒安全 使用方式稍微複雜 自製函式 不會修改原始字串 程式碼會變長 CSV 解析 對資料處理很便利 需注意 strtok
的限制
結論 若是簡單分割則使用 strtok
若是多執行緒則使用 strtok_r
若不想修改原始字串則使用自製函式 也可應用於 CSV 資料解析 接下來的章節將詳細說明「應用範例:抽取特定字元前後的方法 」。
7. 應用範例:提取特定字元前後的方法 在字串處理時,常常需要 提取特定字元或關鍵字的前後 的操作。例如,可以考慮以下情況。僅取得 URL 的網域部分 從檔案路徑中抽取檔名 取得特定標籤或符號前後的字串 在 C 語言中,透過使用 strchr
與 strstr
可以實現此類處理。另外,若需要更彈性的處理,建立自訂函式也是有效的方法。7.1 strchr
使用取得特定字元前的字串 strchr
可用於定位特定的字元 (首次出現的)的位置。基本語法 char *strchr(const char *str, int c);
str
: 要搜尋的字串c
: 想要尋找的字元(char
型) strchr
若找到 c
,會回傳其位址。使用範例:從檔案路徑取得檔名 #include <stdio.h>
#include <string.h>
void get_filename(const char *path, char *filename) {
char *pos = strrchr(path, '/'); // 搜尋最後的 '/'
if (pos != NULL) {
strcpy(filename, pos + 1); // '/' 的次的位址開始複製
} else {
strcpy(filename, path); // 若無 '/',直接複製
}
}
int main() {
char path[] = "/home/user/documents/report.txt";
char filename[50];
get_filename(path, filename);
printf("檔名: %s\n", filename);
return 0;
}
執行結果 檔名: report.txt
要點 strrchr
可用於取得最後出現的特定字元(/
)的位置 。使用 pos + 1
複製斜線之後的字串,即可僅取得檔名 。 7.2 strstr
使用取得特定關鍵字之後的字串 strstr
可用於搜尋特定字串(關鍵字),並取得其位置之後的字串 。基本語法 char *strstr(const char *haystack, const char *needle);
haystack
: 要搜尋的字串needle
: 要搜尋的子字串 strstr
若找到 needle
,會回傳其位置的位址。使用範例:從 URL 取得網域 #include <stdio.h>
#include <string.h>
void get_domain(const char *url, char *domain) {
char *pos = strstr(url, "://"); // 搜尋 "://"
if (pos != NULL) {
strcpy(domain, pos + 3); // "://" 之後開始複製
} else {
strcpy(domain, url); // 若無 "://",直接複製
}
}
int main() {
char url[] = "https://www.example.com/page.html";
char domain[50];
get_domain(url, domain);
printf("網域部分: %s\n", domain);
return 0;
}
執行結果 網域部分: www.example.com/page.html
要點 使用 strstr
取得 "https://"
或 "http://"
中的 "//"
之後的部分。 使用 pos + 3
從 ://
之後開始複製。 7.3 strchr
使用分割特定字元前後的部分 利用 strchr
,可以將特定字元前後的字串分割並取得 。使用範例:從電子郵件地址分離使用者名稱與網域 #include <stdio.h>
#include <string.h>
void split_email(const char *email, char *username, char *domain) {
char *pos = strchr(email, '@'); // 搜尋 '@' 的位置
if (pos != NULL) {
strncpy(username, email, pos - email); // '@' 之前的部分
username[pos - email] = '\0'; // 加入 NUL 字元
strcpy(domain, pos + 1); // '@' 之後的部分
}
}
int main() {
char email[] = "user@example.com";
char username[50], domain[50];
split_email(email, username, domain);
printf("使用者名稱: %s\n", username);
printf("網域: %s\n", domain);
return 0;
}
執行結果 使用者名稱: user
網域: example.com
要點 使用 strchr
搜尋 '@'
的位置。 strncpy
用於複製 '@'
之前的部分,並加入 NUL 字元 。使用 strcpy
複製 '@'
之後的部分 。 7.4 應用:抽取 HTML 標籤內的特定屬性 在 HTML 標籤中取得特定屬性時,也可以利用 strstr
。使用範例:從 <a href="URL">
取得 URL #include <stdio.h>
#include <string.h>
void get_href(const char *html, char *url) {
char *start = strstr(html, "href="); // 搜尋 href=" 的位置
if (start != NULL) {
start += 6; // 移動到 href=" 之後
char *end = strchr(start, '"'); // 搜尋下一個 "
if (end != NULL) {
strncpy(url, start, end - start);
url[end - start] = '\0'; // 加入 NUL 字元
}
}
}
int main() {
char html[] = "<a href=\"https://example.com\">Click Here</a>";
char url[100];
get_href(html, url);
printf("抽出的 URL: %s\n", url);
return 0;
}
執行結果 抽出的 URL: https://example.com
要點 使用 strstr
搜尋 "href="
的位置,並移動 6 個字元。 使用 strchr
搜尋 "
(引號)的位址,以確定範圍。 7.5 小結 處理內容 使用函式 優點 取得特定字元前的部分 strchr
/ strrchr
簡單且高速 取得特定字元後的部分 strstr
可搜尋關鍵字 以特定字元分割前後 strchr
+ strncpy
對於使用者名稱、網域分割等很方便 取得 HTML 標籤屬性 strstr
+ strchr
可應用於網頁爬蟲
結論 strchr
與 strstr
的活用,可輕鬆取得特定字元或關鍵字的前後 。檔案路徑處理、URL 解析、電子郵件地址分割等,於多種情境中都有幫助 。亦可應用於如網頁爬蟲等高階處理 。
8. 總結 在本文中,C語言中字串的切割方法 從基礎到應用都做了詳細說明。現在,回顧各章節的重要要點,並依用途整理最適方法。8.1 文章回顧 章節 內容 重要要點 C語言字串的基礎 在C語言中,字串被視為 char
陣列,終止字元 ' '
很重要 處理字串時,不要忘記空字元結尾 使用標準函式庫切割 使用 strncpy
、strchr
等 strncpy
需要 手動加入空字元結尾 。自訂函式切割 建立彈性的 substring
函式 使用 malloc
可 取得可變長度的子字串 依文字編碼處理 對 UTF-8、Shift_JIS、EUC-JP 的對應方法 使用 mbstowcs
/ wcstombs
轉換為寬字元較安全 字串分割方法 使用 strtok
、strtok_r
,或自訂函式分割 strtok
會 修改原始字串 ,需注意抽取特定字元前後 使用 strchr
、strstr
取得資料 可應用於 檔名取得、URL 解析、HTML 解析
8.2 依用途的最佳方法 1. 子字串切割 使用情境 最佳方法 想取得固定長度的字串 strncpy
或 substring()
想要安全的切割 strncpy_s
(C11 之後)處理多位元組字元(UTF-8、Shift_JIS、EUC-JP) mbstowcs
/ wcstombs
2. 字串分割 使用情境 最佳方法 想簡單分割字串 strtok
想要執行緒安全的分割 strtok_r
想在不修改原始字串的情況下分割 自訂函式(split_string()
)
3. 取得特定字元前後 使用情境 最佳方法 從檔案路徑取得檔名 strrchr(path, '/')
從 URL 取得網域部分 strstr(url, "://")
從電子郵件地址分離使用者名稱與網域 strchr(email, '@')
從 HTML 標籤取得屬性值 strstr(tag, "href="")
+ strchr(tag, '"')
8.3 C語言字串處理的注意事項 1. 徹底管理空字元 ' '
的結尾 在 C 語言的字串處理中,適當管理終止字元 ' '
是最重要的 。特別是使用 strncpy
或 strchr
時,請注意手動加入空字元 。安全的字串複製範例 #include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
strncpy(dest, src, 5);
dest[5] = ' '; // 為了安全加入空字元結尾
printf("子字串: %s
", dest);
return 0;
}
2. 注意緩衝區溢位 在 C 語言的字串操作中,需要謹慎實作以避免存取陣列範圍外。特別是使用 strncpy
時,控制要複製的位元組數 是很重要的。 安全的字串複製範例 #include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
char dest[6];
strncpy(dest, src, sizeof(dest) - 1);
dest[5] = ' '; // 明確加入空字元
printf("子字串: %s
", dest);
return 0;
}
3. 多位元組字元處理使用 mbstowcs
在處理 UTF-8、Shift_JIS 等多位元組字元時,單純使用 strncpy
或 strlen
會無法正確運作。 因此,處理多位元組字元時,建議先使用 mbstowcs
轉換為寬字元字串,再適當處理。#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, ""); // 設定 locale
char text[] = "こんにちは、世界!"; // UTF-8
wchar_t wtext[256];
mbstowcs(wtext, text, 256); // 轉換為寬字元字串
printf("轉換後的寬字元字串: %ls
", wtext);
return 0;
}
4. 緩衝區大小管理 在字串處理中,事先計算所需記憶體大小 ,並防止緩衝區溢位 是很重要的。特別是使用 malloc
取得動態記憶體時,請正確掌握其大小。8.4 進一步學習方向 C 語言的字串處理是提升程式安全性與可讀性的關鍵技能。基於本文介紹的內容,若再學習以下主題,將能進行更高階的字串處理。深化學習的主題 正規表達(regex) (可透過 C 語言的外部函式庫實作)檔案操作(使用 fgets、fscanf 進行字串處理) 記憶體管理(使用 malloc、realloc 進行動態字串處理) 資料解析(JSON、XML 的解析方法) 8.5 總結 C 語言的字串以 char
陣列管理,故終止字元 ' '
的處理很重要 子字串切割可使用 strncpy
、substring()
、malloc
字串分割可活用 strtok
/ strtok_r
/ 自訂函式 取得特定字元前後時,可活用 strchr
、strstr
處理多位元組字元(如日文)時,使用 mbstowcs
保持安全的字串處理,注意緩衝區溢位 若能活用本文內容,將能在 C 語言中實作實用的字串處理 。在理解基本函式的基礎上,挑戰自訂函式與應用處理,寫出更有效率的程式碼吧!