记一次数据结构课设
設(shè)計內(nèi)容
打開一篇英文文章,在該文章中找出所有給定的單詞,然后對所有給定的單詞替換為另外一個單詞,再存盤。
實現(xiàn)思路
簡單的界面設(shè)計就不去闡述了,代碼方法寫的很分明。
算法的核心是串的查找和替換,我運用kmp算法對串進行查找操作,這個算法是整個代碼最重要的地方,kmp算法的講解可以百度其他大神的博客,我就不獻丑了。因為給定單詞在一篇文章中不一定只出現(xiàn)一次,所以我改良了經(jīng)典的算法步驟,使算法可以以數(shù)組形式返回所有匹配成功位置。
在字符串的替換問題上,有多種情況,詳細(xì)可見char* replace(char* address,char* s,char* p,char* q)函數(shù)。
源代碼
#include<stdio.h> #include<string.h> #include<stdlib.h> #define max 10000 int next[max]; // kmp算法中的next數(shù)組 int T[max]; // 保存匹配字符串的下標(biāo)集void UI(); // 主用戶界面 void return_UI(); // 返回操作界面 void search_UI(); // 字符串查找界面 void replace_UI(); // 字符串替換界面 void inputWordString_UI(); // 輸入文本串UI,將文本串保存到 word.txt文件中 int exitInterface_UI(); // 詢問用戶是否退出 void getNext(char* p, int next[]); // 得到模式串next數(shù)組 int search(char* s, char* p); // 子字符串查找函數(shù),得到文本串中與模式串所有匹配的下標(biāo)集T,無匹配則將T[0] = -1 char* replace(char* address,char* s,char* p,char* q); // 字符串替換函數(shù) char* readFile(char* address); // 讀取文件 void writeFile(char* address, char* str); // 寫入文件/* main: 主函數(shù) */ int main() {UI();return 0; }/* UI: 主用戶界面 無參數(shù) 無返回值 */ void UI() {char* str = readFile("word.txt");printf("\t\t歡迎使用\n\字符串查找與替換程序\n\請輸入命令(數(shù)字):\n\1.字符串的查找;\n\2.字符串替換;\n\3.輸入文本串;\n\4.結(jié)束程序。\n\");printf("默認(rèn)文本串為:%s \n\t",str);int state = 1; // 狀態(tài)(0為異常,1為正常, 2為結(jié)束)while (state < 2) {int operate; // 操作命令scanf("%d", &operate);if (operate == 1) { // 字符串的查找search_UI();printf("\n\t字符串查找操作完成\n");return_UI();UI();} else if (operate == 2) { // 字符串的替換replace_UI();printf("\n\t字符串替換操作完成\n");return_UI();UI();} else if (operate == 3) { // 輸入文本串 inputWordString_UI();return_UI();UI();} else if (operate == 4) { // 退出系統(tǒng) state = exitInterface_UI();if (state == 2) {printf("\t\t謝謝使用\n");exit(0);} else {UI();}} else { // 處理輸入錯誤printf("輸入錯誤,請重新輸入。\n");state = 0;}} }/* return_UI: 返回操作界面 無參數(shù) 無返回值 */ void return_UI() {printf("\t------------------------\n");printf("\t按任意鍵返回\n");getch();system("cls"); } /* search_UI: 字符串查找界面 無參數(shù) 無返回值 */ void search_UI() {char* p; // 子串p = (char*)malloc(sizeof(char)*max);printf("請輸入要查找的子串:");scanf("%s",p);char* s = readFile("word.txt"); // 文本串int n = search(s, p); // 得到匹配總數(shù),匹配位置下標(biāo)集為 Tprintf("\n文本串中共用%d個位置與子串相同。", n);printf("分別為:");int i;for (i = 0; i < n; i++) {printf("%d ",T[i]+1);}printf("\n"); }/* replace_UI: 字符串替換界面 無參數(shù) 無返回值 */ void replace_UI() {char* str = readFile("word.txt"); // 文本串 char* p = (char*)malloc(sizeof(char)); // 被替換的子串 char* q = (char*)malloc(sizeof(char)); // 替換后的子串 printf("請輸入要被替換的子串:");scanf("%s",p);printf("請輸入替換后的子串:");scanf("%s",q);int n = search(str,p); // 得到 n、Tif (n == 0) {printf("\n\t無法替換字符串,因為文本串中無被替換子串。\n");} else {str = replace("word.txt",str,p,q); // 替換并更新文本串 printf("\n\t子串替換成功!\n\t當(dāng)前文本串為:");printf("%s\n",str); } } /* inputWordString_UI: 輸入文本串UI,將文本串保存到 word.txt文件中 無參數(shù) 無返回值 */ void inputWordString_UI() {char* str;str = (char*)malloc(sizeof(char)*max);printf("請輸入文本串: ");getchar();gets(str);getchar();writeFile("word.txt",str); }/* exitInterface_UI:詢問用戶是否退出 無參數(shù) 返回值(int):1:不退出;2:退出 */ int exitInterface_UI() {int operate;printf("\t是否退出程序?\n\選是請輸入1,選否請輸入0\n\");scanf("%d", &operate);if (operate == 1) {return 2; // 退出程序,state狀態(tài)為2(結(jié)束)} else if (operate == 0) {return 1; // 保存程序運行,state狀態(tài)為1(正常)} else {printf("輸入錯誤,請重新輸入!\n");return exitInterface_UI();} }/* getNext: 得到模式串next數(shù)組 參數(shù): char* p: 模式串; int next[]: kmp算法所需next數(shù)組 無返回值 */ void getNext(char* p,int next[]) { int pLen = strlen(p);next[0] = -1; int k = -1;int j = 0;while (j < pLen -1) {if (k == -1 || p[j] == p[k]) {++k;++j;next[j] = k;} else {k = next[k];}} }/* search: 子字符串查找函數(shù),得到文本串中與模式串所有匹配的下標(biāo)集T,無匹配則將T[0] = -1 參數(shù): char* s: 文本串;char* p: 模式串 返回值 int n : 所有匹配下標(biāo)的總數(shù) */ int search(char* s, char* p) {getNext(p, next);int i = 0;int j = 0;int n = 0;int sLen = strlen(s);int pLen = strlen(p);while (i < sLen && j < pLen) {if (j == -1 || s[i] == p[j]) {++i;++j;} else {j = next[j];}if (j == pLen - 1 && s[i] == p[j]) { // 判斷是否完全匹配,并為 T 賦值T[n++] = i - j;j = next[j]; // 匹配成功則初始化 j }}if (n == 0) {T[0] = -1;}return n; }/* replace: 字符串替換函數(shù) 參數(shù): char* address : 文本串的保存路徑, char* s : 文本串, char* p : 被替換子串, char* q : 替換子串 返回值 char* s : 替換后的文本串 */ char* replace(char* address,char* s,char* p,char* q) {int sLen = strlen(s);int pLen = strlen(p);int qLen = strlen(q);int x,y,i,j;int t = 0; // 計數(shù) int m = qLen - pLen; // 替換子串與被替換子串的長度差 for (x = 0,y = 0; x < sLen; x++) { // 遍歷所有位置 if (x == T[y] + t * m){ // 找到可以匹配的位置 ++y;++t;if (pLen < qLen) { // 如果被替換子串長度小于替換子串for (i = sLen - 1 + (t-1) * m; i > x + pLen - 1; i--) { // 則向后位移文本串x + pLen 位置后的字符,位移量為 m(正), 從后向前遍歷 s[i + m] = s[i];}for (i = x, j = 0; i < x + qLen; i++, j++) {s[i] = q[j];} } else if (pLen > qLen) { // 如果被替換子串長度小于替換子串for (i = x + qLen - m; i < sLen + (t-1) * m; i++) { // 則向前位移文本串x + qLen 位置后的字符,位移量為 m(負(fù)), 從前向后遍歷 s[i + m] = s[i];}for (i = sLen + t * m, j = 0; j < -m; j++) {s[i+j] = '\0';}for (i = x, j = 0; i < x + qLen; i++, j++) {s[i] = q[j];}} else { // 如果被替換子串長度等于替換子串for (i = x, j = 0; i < x + qLen; i++, j++) {s[i] = q[j];}}}}writeFile(address,s);return s; }/* readFile: 讀取文件 參數(shù) char* address : 文件地址值 返回值 char* :字符串指針 */ char* readFile(char* address) { FILE* fp;if ((fp = fopen(address,"rb")) == NULL) {fopen(address,"wb");}char str1[max];if (fgets(str1,max,fp) == NULL){str1[0] = NULL;}fclose(fp); // 關(guān)閉文件 char* str;str = (char*)malloc(sizeof(char)*max); // 為str分配內(nèi)存 strcpy(str,str1);return str; }/* writeFile: 寫入文件 參數(shù) char* address : 文件地址值 ;char* str : 要寫入的字符串 無返回值 */ void writeFile(char* address,char* str) {FILE* fp;if ((fp = fopen(address,"wb")) == NULL) {printf("文件打開錯誤\n");exit(0);}fputs(str,fp);fclose(fp); }附:抱歉,寒假沒有來的及整理學(xué)習(xí)內(nèi)容,要學(xué)的東西越來越多,但是肯定是要整理一下的,不然全部都忘記了。
以上
轉(zhuǎn)載于:https://www.cnblogs.com/mxwbq/p/8478101.html
總結(jié)
- 上一篇: tomcat的根路径设置
- 下一篇: 索引碎片与填充因子