第四章学习小结
第四章學習了串和數組的相關內容,以及學習了BF算法和KMP算法。這周上機課老師帶著我們打了AI核心代碼。
看到題目就覺得要求好多代碼肯定很難寫,聽到老師說這道題目會有很多的邊界問題要進行考慮,就感覺更難了,但是在老師的一步步指導下,完成了這道題,因此本章學習小結我將會分享一些完成這道題老師教給我們的思路以及我的一些心得體會。
?
本題要求你實現一個簡易版的 AI 英文問答程序,規則是:
首先看完這道題我們應該首先考慮的是主函數,按照題目的要求將主函數編寫完成,在進行后續的補充完善。
同時處理題目規則一:無論用戶說什么,首先把對方說的話在一行中原樣打印出來以及規則七:在一行中輸出替換后的句子作為 AI 的回答。此時我們調用了<cstdio>文件里的getchar()函數來吸收回車。
//主函數 int main() {int n;string s;cin >>n;getchar();// 吸收回車 <cstdio> for ( int i=1; i<=n ; i++){getline(cin , s);cout << s << endl ;cout << "AI: ";go(s); // 根據s輸出AI的回答 }return 0; }
然后再根據主函數的代碼內容,一步步完善代碼,所以接下來就是要完成go函數的編寫
首先需定義輔助變量t來copy s的字符串,題目有:每行給出一句不超過 1000 個字符的、以回車結尾的用戶的對話,考慮到如果輸入的字符全為大寫的話。那么將數組長度定義為1000或者1001是不夠的,所以要將數組長度定義為3001,包括結尾\0
void go(string s){ // 根據s輸出AI的回答 //定義輔助變量t,來copy s的字符串 char t[3001];int i, j; //定義兩個下標; i :定義到s的第一個非空;...}定義到s的第一個非空字符后,首先要考慮的是空格問題,后面的條件依照空格標準化??紤]刪除空格的情況(刪除前后空格,刪除中間連續的空格保留一個,刪除符號后的空格)首先處理規則二:消除原文中多余空格:把相鄰單詞間的多個空格換成 1 個空格,把行首尾的空格全部刪掉,把標點符號前面的空格刪掉
void go(string s){// 根據s輸出AI的回答 //定義輔助變量t,來copy s的字符串 char t[3001];int i, j; //定義兩個下標; i :定義到s的第一個非空;for(i = 0 ; s[i]!= '\0' && s[i] == ' ' ; i++); //全為空格的時候會將s的最后一個字符‘\0’存儲 j = 0;//保證每次往后掃一次用for,往后掃的次數要跳躍無規律用whilewhile(s[i] != '\0'){ //把s串copy到t,但是連續的空格只copy一次 if(s[i] == ' ' && s[i-1] ==' ')//連續的空格第一個要,后面的都不要 { //一個一個copy到t字符串同時判斷 i++;continue;}...... if(s[j]==' '&&s[j+1]=='\0') //刪除后面空格{j++;continue;}cout << t[j];j++;} }處理規則五:把原文中所有的問號 ? 換成驚嘆號 !
void go(string s){// 根據s輸出AI的回答 //定義輔助變量t,來copy s的字符串 char t[3001];int i, j; //定義兩個下標; i :定義到s的第一個非空;for(i = 0 ; s[i]!= '\0' && s[i] == ' ' ; i++); //全為空格的時候會將s的最后一個字符‘\0’存儲 j = 0;//保證每次往后掃一次用for,往后掃的次數要跳躍無規律用whilewhile(s[i] != '\0'){ //把s串copy到t,但是連續的空格只copy一次 if(s[i] == ' ' && s[i-1] ==' ')//連續的空格第一個要,后面的都不要 { //一個一個copy到t字符串同時判斷 i++;continue;}if(s[i]=='?'){t[j++]='!';++i;continue;//回到循環開頭 }t [j]='\0';// 字符串結尾標志; ...... if(s[j]==' '&&s[j+1]=='\0') //刪除后面空格{j++;continue;}cout << t[j];j++;} }處理規則三:把原文中所有大寫英文字母變成小寫,除了 I,所以用if循環,將除了I以外的大寫字母利用tolower函數接口將大寫轉為小寫。
void go(string s){// 根據s輸出AI的回答 //定義輔助變量t,來copy s的字符串 char t[3001];int i, j; //定義兩個下標; i :定義到s的第一個非空;for(i = 0 ; s[i]!= '\0' && s[i] == ' ' ; i++); //全為空格的時候會將s的最后一個字符‘\0’存儲 j = 0;//保證每次往后掃一次用for,往后掃的次數要跳躍無規律用whilewhile(s[i] != '\0'){ //把s串copy到t,但是連續的空格只copy一次 if(s[i] == ' ' && s[i-1] ==' ')//連續的空格第一個要,后面的都不要 { //一個一個copy到t字符串同時判斷 i++;continue;}if(s[i]=='?'){t[j++]='!';++i;continue;//回到循環開頭 }if( s[i] != 'I'){t[j] = tolower(s[i]);i++;j++;continue;}t[j++] = s[i++]; //不能copy連續的空格 ,先讀變量值,為下一輪循環做準備 //此時t沒有處理'\0' 后面讀出字符串會出錯 } t [j]='\0';// 字符串結尾標志; ...... if(s[j]==' '&&s[j+1]=='\0') //刪除后面空格{j++;continue;}cout << t[j];j++;} }處理規則四:把原文中所有獨立的 I 和 me 換成 you。需要注意的是獨立的I才要換成you,判斷I獨立的條件是I的前后是空格或者是標點符號,其他情況的I則不需要變換。此外j為0時會越界。
void go(string s){// 根據s輸出AI的回答 //定義輔助變量t,來copy s的字符串 char t[3001];int i, j; //定義兩個下標; i :定義到s的第一個非空;for(i = 0 ; s[i]!= '\0' && s[i] == ' ' ; i++); //全為空格的時候會將s的最后一個字符‘\0’存儲 j = 0;//保證每次往后掃一次用for,往后掃的次數要跳躍無規律用whilewhile(s[i] != '\0'){ //把s串copy到t,但是連續的空格只copy一次 if(s[i] == ' ' && s[i-1] ==' ')//連續的空格第一個要,后面的都不要 { //一個一個copy到t字符串同時判斷 i++;continue;}if(s[i]=='?'){t[j++]='!';++i;continue;//回到循環開頭 }if( s[i] != 'I'){t[j] = tolower(s[i]);i++;j++;continue;}t[j++] = s[i++]; //不能copy連續的空格 ,先讀變量值,為下一輪循環做準備 //此時t沒有處理'\0' 后面讀出字符串會出錯 } t [j]='\0';// 字符串結尾標志; j = 0;while(t[j]!='\0'){if(t[j]=='I' && ( j == 0 || isDependent(t[j-1]) ) && isDependent(t[j+1]) ) {cout << "you";j++;continue;}if(t[j]=='m' && t[j+1]=='e' && (j==0 || isDependent(t[j-1])) && isDependent(t[j+2]) ) //j+2不會越界 {cout << "you";j = j+2;continue;}if(t[j]==' ' && isDependent(t[j+1])){j++;continue;}cout << t[j];j++;} if(s[j]==' '&&s[j+1]=='\0') //刪除后面空格{j++;continue;}cout << t[j];j++;} cout <<endl; }處理I和me問題時調用了isDependent函數,因此我們需要定義isDependent函數來判斷ch是否為分隔符??崭?、標點、 \0<這三類是分隔符號>
bool isDependent(char ch) { ch = tolower(ch);if((ch >='0' && ch<='9') || (ch>='a' && ch<='z'))return false;else return true; }最后就是要處理規則六:把原文中所有獨立的 can you 換成 I can —— 這里“獨立”是指被空格或標點符號分隔開的單詞。首先我們需要判斷can you 是否獨立,因此需要定義iscanyou函數來完成這個功能。
bool canyou(char t[],int j) {if(t[j]=='c'&&t[j+1]=='a'&&t[j+2]=='n'&&t[j+3]==' '&&t[j+4]=='y'&&t[j+5]=='o'&&t[j+6]=='u')return true;else return false; }在go函數中,通過調用canyou函數來處理規則六。
void go(string s){// 根據s輸出AI的回答 //定義輔助變量t,來copy s的字符串 char t[3001];int i, j; //定義兩個下標; i :定義到s的第一個非空;for(i = 0 ; s[i]!= '\0' && s[i] == ' ' ; i++); //全為空格的時候會將s的最后一個字符‘\0’存儲 j = 0;//保證每次往后掃一次用for,往后掃的次數要跳躍無規律用whilewhile(s[i] != '\0'){ //把s串copy到t,但是連續的空格只copy一次 if(s[i] == ' ' && s[i-1] ==' ')//連續的空格第一個要,后面的都不要 { //一個一個copy到t字符串同時判斷 i++;continue;}if(s[i]=='?'){t[j++]='!';++i;continue;//回到循環開頭 }if( s[i] != 'I'){t[j] = tolower(s[i]);i++;j++;continue;}t[j++] = s[i++]; //不能copy連續的空格 ,先讀變量值,為下一輪循環做準備 //此時t沒有處理'\0' 后面讀出字符串會出錯 } t [j]='\0';// 字符串結尾標志; j = 0;while(t[j]!='\0'){if(t[j]=='I' && ( j == 0 || isDependent(t[j-1]) ) && isDependent(t[j+1]) ) //獨立的I(前后是空格或者是標點符號)才要換成you ,j為0會越界 {cout << "you";j++;continue;}if(t[j]=='m' && t[j+1]=='e' && (j==0 || isDependent(t[j-1])) && isDependent(t[j+2]) ) //j+2不會越界 {cout << "you";j = j+2;continue;}if(t[j]==' ' && isDependent(t[j+1])){j++;continue;}if(canyou(t,j)&&(j==0||isDependent(t[j-1]))&&isDependent(t[j+7])) //canyou共有七個字符{cout<<"I can";j=j+7; continue;}cout <<endl; }最后將以上函數整合,如需聲明函數的進行聲明,代碼就完成了。
?
本章完成實踐和作業花費的時間比較長,感覺題目很長而且很難,考慮的要點太多了。但是這次老師親自帶我們做實踐題之后,感覺對題目長的代碼題沒那么恐懼了,最重要的是理清思路,考慮全面了再從主函數開始入手,逐步完善每一個要點。
本章學習比上一章進步的一點是做到了選擇用一個方法來寫代碼,即便出了bug也慢慢改,沒有換各種方法來寫題。
接下來的目標是希望自己看到新的編程題自己能夠理清好思路,寫好算法,然后在一步步實踐中提高自己的編程能力。
?
轉載于:https://www.cnblogs.com/pppipio/p/10706467.html
總結
- 上一篇: 不要一棍子打翻所有黑盒模型,其实可以让它
- 下一篇: 常用取值