C 標準庫字串操作功能有限且易出錯。本文提供一個完整的動態字串庫實現,支援建立、拷貝、連接、比較、查找、分割、子串搜尋等操作,採用鏈表式緩衝區管理,適合嵌入式或無標準庫環境。
typedef char* String;
typedef int Status;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
// 安全檢查巨集
#define CHECK(t) do { if(!(t)) return 0; } while(0)
// 靜態緩衝區(用於 StrTok)
static String STRBUFFER = 0;
// 字串長度
int StrLen(String buf) {
String temp = buf;
while(*temp++);
return temp - buf - 1;
}
// 分配字串空間(含結束符)
String StrMake(int length) {
return (String)malloc(length + 1);
}
// 字串查找字符
String StrChr(String buf, char ch, int length) {
while(length-- && *buf++ != ch);
return buf - 1;
}
// 字串連接(動態擴容)
void StrCat(String *dest, String src) {
String temp = (String)malloc(StrLen(*dest) + StrLen(src) + 1);
String head = temp;
String d = *dest;
while(*d) *temp++ = *d++;
while(*src) *temp++ = *src++;
*temp = '\0';
*dest = head;
}
// 字串拷貝
void StrCpy(String *dest, String src) {
*dest = StrMake(StrLen(src));
String temp = *dest;
while(*src) *temp++ = *src++;
*temp = 0;
}
// 釋放字串
void StrFree(String *str) {
free(*str);
*str = 0;
}
// 字串比較(類 strcmp)
int StrCmp(String buf1, String buf2) {
do {
if(*buf1 > *buf2) return 1;
if(*buf1 < *buf2) return -1;
if(!*buf1) break;
buf1++; buf2++;
} while(1);
return 0;
}
// 列印字串
Status StrPrint(String str) {
CHECK(str);
puts(str);
return TRUE;
}
// 字串分割(類 strtok,可重入)
String StrTok(String dest, String src) {
if(dest) StrCpy(&STRBUFFER, dest);
CHECK(src && STRBUFFER && *STRBUFFER);
int length = StrLen(src);
String ch = StrChr(src, *STRBUFFER, length);
// 跳過分隔符
if(*ch == *STRBUFFER) {
do {
*STRBUFFER++ = '\0';
CHECK(*STRBUFFER);
ch = StrChr(src, *STRBUFFER, length);
} while(*ch == *STRBUFFER);
}
String result = STRBUFFER;
String temp = result;
// 尋找下一個分隔符
while(*temp) {
ch = StrChr(src, *temp, length);
if(*ch == *temp) {
*temp++ = '\0';
CHECK(*temp);
break;
} else temp++;
}
STRBUFFER = temp;
return result && *result ? result : 0;
}
// 子串搜尋(類 strstr)
String StrStr(String dest, String src) {
CHECK(dest && src && *dest && *src);
do {
String temp = src, rt = dest;
while(*temp == *rt) { temp++; rt++; }
if(!*temp) return dest;
CHECK(*rt);
dest++;
} while(*dest);
return 0;
}
int main() {
String s1 = StrMake(20);
String s2 = StrMake(20);
StrCpy(&s1, "Hello");
StrCpy(&s2, " World");
StrCat(&s1, s2); // "Hello World"
StrPrint(s1);
String token = StrTok("a,b,c", ",");
while(token) {
StrPrint(token); // 輸出 a, b, c
token = StrTok(0, ",");
}
StrFree(&s1);
StrFree(&s2);
return 0;
}
| 優點 | 缺點/風險 |
|---|---|
| 完全動態分配,無固定緩衝區限制 | StrTok 使用靜態變數,非執行緒安全 |
| 介面簡潔,語義接近標準庫 | 缺乏錯誤碼細分,僅回傳 0/1 |
| StrTok 支援多字符分隔符 | 頻繁 malloc/free 可能產生碎片 |
| 無標準庫依賴,適合裸機環境 | 未處理 UTF-8 多位元組字符 |
len、capacity、data 避免重複計算長度StrDup、StrCmpIgnoreCase 等常用擴展