串(字符串)是編程中最常用的結構,但 C語言 中沒有“字符串”這種變量,只能通過字符數組的形式表示字符串。
C語言 為我們提供了一個 string.h 的頭文件,通過這個頭文件,我們可以實現對字符串的各種操作,如拷貝、比較等,具體用法請參考【C語言庫函數】。
當然,我們對字符串的操作可能不僅僅局限於 string.h 這個頭文件給我們提供的這些方法,因此,我們可以自己實現一個字符串的數據結構,通過在這里面編寫一些實用的方法,實現我們的需求。
以下是實用 C語言 編寫的一個字符串的頭文件 String.h,代碼如下:
/** * 串(順序存儲方式) * 注意:字符串都是以“\0”符號結尾的 */ #include <Constant.h> // 定義字符串的數據結構體 typedef struct String { char* data; // 字符串中的數據 int currLength; // 字符串的當前長度 int maxLength; // 字符串的總長度 } String; // 0.獲取某個字符串的長度 int getCharArrayLength(char* string) { int length = 0; while(string[length] != '\0') { length++; } return length; } // 1.初始化字符串(創建一個新的字符串,其中包含string中的所有字符) Status initString(String* S, char* string) { int i = 0; // 獲取字符串的長度 int length = getCharArrayLength(string); // 字符串賦值 S->data = (char*)malloc(length * sizeof(char)); if(S->data == NULL) { printf("initString => 空間分配失敗,初始化字符串失敗!\n"); return FAILURE; } S->currLength = length; S->maxLength = length; for(i = 0; i < length; i++) { S->data[i] = string[i]; } return SUCCESS; } // 2.復制字符串(將字符串string中的所有字符復制到字符串S中) Status copyString(String* S, char* string) { int i; int length = getCharArrayLength(string); if(S->data == NULL) { printf("copyString => 字符串不存在,復制失敗!\n"); return FAILURE; } if(length > S->maxLength) { S->data = (char*)realloc(S->data, length * sizeof(char)); if(S->data == NULL) { printf("copyString => 重分配空間失敗,復制字符串失敗!\n"); return FAILURE; } S->maxLength = length; } S->currLength = length; for(i = 0; i < length; i++) { S->data[i] = string[i]; } return SUCCESS; } // 3.判斷字符串是否為空 Status isStringEmpty(String* S) { if(S->data == NULL) { printf("isStringEmpty => 字符串不存在!\n"); exit(1); } if(S->currLength == 0) { return TRUE; } return FALSE; } // 4.比較兩個字符串的大小(返回的是S1與S2比較的結果) // 當兩個字符串的長度相等,且對應字符都相同時,稱這兩個字符串相等;否則,看第一個不相等的字符比較結果,字符較大的字符串較大 Status compareString(String* S1, String* S2) { int i = 0; // 判空 if(S1->data == NULL || S2->data == NULL) { printf("compareString => 其中一個字符串不存在!\n"); exit(1); } // 某一個字符串為空 if(S1->currLength == 0) { if(S2->currLength == 0) { return EQUAL; } else { return SMALLER; } } if(S2->currLength == 0) { if(S1->currLength == 0) { return EQUAL; } else { return BIGGER; } } // 兩個字符串都不為空時,逐個字符比較 for(i = 0; ;i++) { if(i == S1->currLength && i == S2->currLength) { return EQUAL; } if(i >= S1->currLength) { return SMALLER; } if(i >= S2->currLength) { return BIGGER; } if(S1->data[i] > S2->data[i]) { return BIGGER; } else if(S1->data[i] < S2->data[i]) { return SMALLER; } } } // 5.獲取字符串的長度 int getStringLength(String* S) { if(S->data == NULL) { printf("getStringLength => 字符串不存在!\n"); exit(1); } return S->currLength; } // 6.清空字符串 Status clearString(String* S) { if(S->data == NULL) { printf("clearString => 字符串不存在!\n"); return FAILURE; } S->currLength = 0; return SUCCESS; } // 7.將字符串S2連接到字符串S1后面並返回 Status concatString(String* S1, String* S2) { if(S1->data == NULL || S2->data == NULL) { printf("concatString => 其中一個字符串不存在!\n"); return FAILURE; } int i; int len1 = getStringLength(S1); int len2 = getStringLength(S2); if(S1->maxLength < len1 + len2) { S1->data = (char*)realloc(S1->data, (len1 + len2) * sizeof(char)); if(S1->data == NULL) { printf("concatString => 重分配空間失敗,字符串拼接失敗!\n"); return FAILURE; } S1->maxLength = len1 + len2; } for(i = 0; i < len2; i++) { S1->data[len1 + i] = S2->data[i]; } S1->currLength = len1 + len2; return SUCCESS; } // 8.返回字符串S中從pos位置開始,長度為len的子串 char* getSubString(String* S, int pos, int len) { char* result; int i; if(S->data == NULL) { printf("getSubString => 字符串不存在!\n"); exit(1); } if(pos < 0 || pos >= S->currLength) { printf("getSubString => pos參數超出范圍!\n"); exit(1); } if(len > S->currLength - pos) { printf("getSubString => 子串長度超出范圍!\n"); exit(1); } for(i = 0; i < len; i++) { *(result + i) = S->data[pos + i]; } *(result + i) = '\0'; return result; } // 9.返回字符串S中從pos位置開始的與子串string相等的第一個子串的位置 int locateSubString(String* S, char* string, int pos) { int i, j; int length = getCharArrayLength(string); if(S->data == NULL) { printf("locateSubString => 字符串不存在!\n"); exit(1); } if(pos < 0 || pos >= S->currLength) { printf("locateSubString => pos參數超出范圍!"); exit(1); } if(length + pos > S->currLength) { printf("locateSubString => 子串長度超出范圍!\n"); exit(1); } for(i = pos; i <= S->currLength - length; i++) { for(j = 0; j < length; j++) { if(S->data[i + j] != string[j]) { break; } } if(j == length) { return i; } } return -1; } // 10.在字符串S的pos位置插入字符串string Status stringInsert(String* S, int pos, char* string) { int i; int length = getCharArrayLength(string); if(S->data == NULL) { printf("stringInsert => 字符串不存在,插入字符失敗!\n"); return FAILURE; } if(pos < 0 || pos > S->currLength) { printf("stringInsert => pos參數超出范圍,插入字符失敗!\n"); return FAILURE; } if(S->currLength + length > S->maxLength) { S->data = (char*)realloc(S->data, (S->currLength + length) * sizeof(char)); if(S->data == NULL) { printf("stringInsert => 重分配空間失敗,插入字符失敗!\n"); return FAILURE; } S->maxLength = S->currLength + length; } for(i = S->currLength - 1; i >= pos; i--) { S->data[i + length] = S->data[i]; } for(i = 0; i < length; i++) { S->data[pos + i] = string[i]; } S->currLength += length; return SUCCESS; } // 11.刪除字符串S中從pos位置開始的len個字符 Status stringDelete(String* S, int pos, int len) { int i; if(S->data == NULL) { printf("stringDelete => 字符串不存在,刪除字符失敗!\n"); return FAILURE; } if(pos < 0 || pos >= S->currLength) { printf("stringDelete => pos參數超出范圍,刪除字符失敗!\n"); return FAILURE; } if(pos + len > S->currLength) { printf("stringDelete => 子串長度超出范圍,刪除字符失敗!\n"); return FAILURE; } for(i = pos + len; i < S->currLength; i++) { S->data[i - len] = S->data[i]; } S->currLength -= len; return SUCCESS; } // 12.用字符串newStr替換字符串S中出現的所有與子串oldStr相同的不重疊的子串 Status replaceString(String* S, char* oldStr, char* newStr) { int index; int oldLen = getCharArrayLength(oldStr); int newLen = getCharArrayLength(newStr); if(S->data == NULL) { printf("replaceString => 字符串不存在,替換失敗!\n"); return FAILURE; } index = locateSubString(S, oldStr, 0); while(index >= 0 && index + oldLen <= S->currLength) { stringDelete(S, index, oldLen); stringInsert(S, index, newStr); if(oldLen + index + newLen >= S->currLength) { break; } index = locateSubString(S, oldStr, index + newLen); } return SUCCESS; } // 13.遍歷字符串 void traverseString(String* S) { int i; if(S->data == NULL) { printf("traverseString => 字符串不存在,遍歷失敗!\n"); exit(1); } printf("遍歷字符串:"); for(i = 0; i < S->currLength; i++) { printf("%c", S->data[i]); } printf("\n"); } // 14.銷毀字符串 Status destroyString(String* S) { if(S->data == NULL) { printf("destroyString => 字符串不存在,不需要銷毀!\n"); return FAILURE; } free(S->data); S->data = NULL; S->currLength = 0; S->maxLength = 0; return SUCCESS; } // 測試函數 int testString() { // 聲明變量 String str1, str2; // 初始化字符串 if(initString(&str1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]") == SUCCESS) { printf("初始化字符串S1成功!\n"); traverseString(&str1); // 遍歷 } if(initString(&str2, "abc") == SUCCESS) { printf("初始化字符串S2成功!\n"); traverseString(&str2); } // 清空字符串 if(clearString(&str2) == SUCCESS) { printf("清空字符串S2成功!\n"); } // 判斷字符串是否為空 printf("字符串S1是否為空?%s\n", isStringEmpty(&str1) ? "是" : "否"); printf("字符串S2是否為空?%s\n", isStringEmpty(&str2) ? "是" : "否"); // 字符串復制 if(copyString(&str2, "abcdefg") == SUCCESS) { printf("字符串復制成功!\n"); traverseString(&str2); } // 字符串連接 if(concatString(&str1, &str2) == SUCCESS) { printf("將字符串S2連接到S1后面成功!\n"); traverseString(&str1); } // 比較兩個字符串的大小 printf("S1比S2的關系?%d\n", compareString(&str1, &str2)); // 字符串的長度 printf("字符串S1的長度:%d\n", getStringLength(&str1)); printf("字符串S2的長度:%d\n", getStringLength(&str2)); // 取字符串的子串 printf("S1從58位置開始7個長度的子串是:%s\n", getSubString(&str1, 0, 7)); // 返回子串第一次出現的位置 printf("字符串S1中從20位置起,ABCDE子串第一次出現的位置是%d\n", locateSubString(&str1, "ABCD", 20)); // 插入字符串 if(stringInsert(&str1, 26, "||||||") == SUCCESS) { printf("在S1的26位置插入字符串||||||成功!\n"); traverseString(&str1); } // 刪除字符串 if(stringDelete(&str1, 26, 6) == SUCCESS) { printf("從S1的26位置刪除6個字符成功!\n"); traverseString(&str1); } // 替換字符串 if(replaceString(&str1, "abcdefg", "0123456789") == SUCCESS) { printf("成功將S1中的所有abcdefg替換為0123456789!\n"); traverseString(&str1); } // 銷毀字符串 if(destroyString(&str1) == SUCCESS) { printf("銷毀字符串S1成功!\n"); } if(destroyString(&str2) == SUCCESS) { printf("銷毀字符串S2成功!\n"); } return 0; }
常量頭文件 Constant.h 中的代碼如下:
#include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 #define SUCCESS 1 #define FAILURE 0 #define SMALLER -1 #define EQUAL 0 #define BIGGER 1 typedef int Status;
主函數所在的文件 main.c 中的代碼如下:
#include <String.h> int main() { testString(); return 0; }
運行結果如下:
初始化字符串S1成功! 遍歷字符串:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[] 初始化字符串S2成功! 遍歷字符串:abc 清空字符串S2成功! 字符串S1是否為空?否 字符串S2是否為空?是 字符串復制成功! 遍歷字符串:abcdefg 將字符串S2連接到S1后面成功! 遍歷字符串:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]abcdefg S1比S2的關系?1 字符串S1的長度:65 字符串S2的長度:7 S1從58位置開始7個長度的子串是:abcdefg 字符串S1中從20位置起,ABCDE子串第一次出現的位置是26 在S1的26位置插入字符串||||||成功! 遍歷字符串:abcdefghijklmnopqrstuvwxyz||||||ABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]abcdefg 從S1的26位置刪除6個字符成功! 遍歷字符串:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]abcdefg 成功將S1中的所有abcdefg替換為0123456789! 遍歷字符串:0123456789hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()<>[]0123456789 銷毀字符串S1成功! 銷毀字符串S2成功! Process returned 0 (0x0) execution time : 1.783 s Press any key to continue.