【数据结构】之串(C语言描述)
串(字符串)是编程中最常用的结构,但 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.
posted on 2017-04-10 17:47 ITGungnir 阅读(6418) 评论(0) 编辑 收藏 举报