单词小助手完善
題目分析
任務二:例2為單詞小助手,要求完成以下任務:
1.改寫程序為良好程序風格(文檔注釋,函數注釋,語句注釋)。
2.將單詞測試中的功能完善,可針對做錯的單詞重復記憶。
3.查詢單詞的功能添加英文詞查詢,中文查詢的功能完善(考慮如何顯示同樣中文意義,不同的英文單詞)
提高要求:
可將程序中的不足(如數據驗證,排名功能)等根據自己的能力與理解完成。
算法構造
流程圖:
總圖:
英中單詞測試:
中英測試:
增加單詞:
查詢單詞:
N-S圖:
英中測試:
中英測試:
添加單詞:
程序實現
#author:lyq #time:2019-04-03 #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_CHAR 20 // 最大字符 #define MAX_NUM 200 // 單詞的最大個數 #define MAX_MAN 1000 // 用戶最大個數 struct word //單詞的結構體 {char en[MAX_CHAR]; // 英文形式char ch[MAX_CHAR]; //中文形式} s[MAX_NUM]; //單詞數組 struct user { int d;//用戶正確次數 int c;//用戶錯誤次數 }users[MAX_MAN]; struct man//用戶結構體 {int no;int score; }; struct man mans[MAX_MAN];//用戶的結構體數組 struct man temp; //int score[MAX_MAN]={0}; //用戶得分數組 int num; //單詞個數 int select=1;//select 為是否退出系統的標記//返回0:無中文,返回1:有中文 int ifChinese(char *str) {int n = 0;char c;while(c=*str++){//如果字符高位為1且下一字符高位也是1則有中文字符if((c&0x80)&&(*str & 0x80)){n = 1;break;}} return n; } //返回0:無英文,返回1:有英文或者數字這些符號 int ifEnglish(char *str) {int n = 0;char c;while(c=*str++){//如果字符高位為1且下一字符高位也是1則有中文字符if('a'<=c&&c<='z'||'A'<=c&&c<='Z'||'0'<=c&&c<='9'){n = 1;break;}} return n; } //幫助 void help() {printf("\n本系統主要實現英語單詞學習的功能。用戶可對詞典文件中的單詞進行預覽,增刪改查。");printf("\n同時還可進行中英、英中測試。本系統還提供了測試單人成績,成績排行的顯示功能。\n"); }//向文件中輸入單詞信息 void readfile() {FILE *fp;int i=0;fp=fopen("E://data1.txt","r");if(!fp){printf("\n打開文件data1.txt失敗!");}while(fscanf(fp,"%s %s ",s[i].en,s[i].ch)==2){i++;}num=i;if(0==i)printf("\n文件為空,請選擇詞典維護!");elseprintf("\n");fclose(fp);} //從文件中讀取單詞的信息 void writefile()//輸出文件中單詞的信息 {FILE *fp;int i=0;fp=fopen("E://data1.txt","w");if(!fp){printf("\n打開文件data1.txt失敗!");}for(i=0;i<num;i++){fprintf(fp,"\n%s %s ",s[i].en,s[i].ch);}printf("\n");fclose(fp); } void vsort()/*按字典排序*/ {int i,j;char temp[MAX_CHAR];for(i=0;i<num-1;i++){for(j=num-1;j>i;j--)if(strcmp(s[j-1].en,s[j].en)>0){strcpy(temp,s[j-1].en);strcpy(s[j-1].en,s[j].en);strcpy(s[j].en,temp);strcpy(temp,s[j-1].ch);strcpy(s[j-1].ch,s[j].ch);strcpy(s[j].ch,temp);}} } //添加單詞信息 void add() {int i=num,j,flag=1;while(flag){flag=0;printf("\n請輸入單詞的英文形式:");scanf("%s",s[i].en);while(ifChinese(s[i].en)==1)//輸入中包含中文字符{printf("輸入錯誤!請重新輸入!\n");scanf("%s",s[i].en);}for(j=0;j<i;j++)if(strcmp(s[i].en,s[j].en)==0){printf("已有該單詞,請檢查后重新錄入!\n");flag=1;break; /*如有重復立即退出該層循環,提高判斷速度*/}}printf("\n請輸入單詞的中文形式:");scanf("%s",s[i].ch);while(ifEnglish(s[i].ch)==1)//輸入中包含英文字符和數字 {printf("輸入錯誤!請重新輸入!\n");scanf("%s",s[i].ch);}num++;printf("\n您輸入的信息為: 英文: %s 中文: %s ",s[i].en,s[i].ch);vsort(); } //刪除單詞信息 void del() {int i=0,j=0;char en[MAX_CHAR]; //英文形式printf("\n請輸入你要刪除的單詞英文形式:"); scanf("%s",en);for(i=0;i<num;i++)//先找到該英文形式對應的序號if(strcmp(s[i].en,en)==0){for(j=i;j<num-1;j++)s[j]=s[j+1];num--; //數量減少 1return;}printf("\n沒有這個單詞!");} //修改單詞信息 void modify() {int i=0,choose=0,flag=1;//chooses代表選項標識,flag代表是否找到單詞char en[MAX_CHAR]; //英文形式while(flag||choose){printf("\n請輸入你要修改的單詞英文形式:"); scanf("%s",en);for(i=0;i<num;i++)//先找到該英文形式對應的序號if(strcmp(s[i].en,en)==0){printf("\n請輸入單詞正確的英文形式:");scanf("%s",s[i].en);while(ifChinese(s[i].en)==1)//輸入中包含中文字符{printf("輸入錯誤!請重新輸入!\n");scanf("%s",s[i].en);}printf("\n請輸入此單詞正確的的中文形式:");scanf("%s",s[i].ch);while(ifEnglish(s[i].ch)==1)//輸入中包含英文字符{printf("輸入錯誤!請重新輸入!\n");scanf("%s",s[i].ch);}printf("\n繼續修改請選1,返回上一級請選0:");scanf("%d",&choose);if(choose==0) return; }flag=0;}if(!flag) printf("\n沒有這個單詞!"); } //單詞預覽 void show() {int i=0;printf("\n單詞: 英文 中文 ");for(i=0;i<num;i++)printf("\n %-12s%-12s",s[i].en,s[i].ch);printf("\n");} //查詢單詞 void search() {int i=0,flag=1;int choose; char ch[MAX_CHAR];printf("中文查詢請選1,英文查詢請按2\n");scanf("%d",&choose);while(choose||flag){switch(choose){case 1:{int eng[num]={0};//記錄對應的詞的對應下標序號 int d=0;printf("\n請輸入你要查詢的單詞中文形式:"); scanf("%s",ch);while(ifEnglish(s[i].ch)==1)//輸入中包含英文字符和數字 {printf("輸入錯誤!請重新輸入!\n");scanf("%s",s[i].ch);}for(i=0;i<num;i++)//先找到該中文形式對應的所有序號{if(strcmp(s[i].ch,ch)==0){ eng[d++]=i; }} printf("\n中文形式 %-12s",s[eng[i]].ch);for(int k=0;k<d;k++){printf("\n英文形式 %-12s",s[eng[k]].en);}printf("\n繼續中文查詢請選1,英文查詢請選2,返回上一級請選0:");for(int j=0;j<d;j++)//將數組eng[]置零 {eng[j]=0;}d=0;scanf("%d",&choose);if(choose==0) return; flag=0;break;}case 2:{printf("\n請輸入你要查詢的單詞英文形式:"); scanf("%s",ch);while(ifChinese(s[i].en)==1)//輸入中包含中文字符{printf("輸入錯誤!請重新輸入!\n");scanf("%s",s[i].en);}for(i=0;i<num;i++)//先找到該中文形式對應的序號if(strcmp(s[i].en,ch)==0){ printf("\n英文形式 中文形式 ");printf("\n %-12s%12s",s[i].en,s[i].ch);printf("\n繼續中文查詢請選1,英文查詢請選2,返回上一級請選0:");scanf("%d",&choose);if(choose==0) return; }flag=0;break;}default:break;}}if(!flag)printf("\n沒有這個單詞!"); } //做錯的測試單詞的重復記憶 void againrem(int *a,int &d) {printf("現在開始出錯單詞的重復記憶!\n");for(int i=0;i<d;i++){printf("中文: [%s]",s[a[i]].ch);printf("英文: [%s]",s[a[i]].en);printf("\n");a[i]=0;//將對應位置序列數置零. } } //中譯英測試 void zytest(int no) { users[no].c=users[no].d=0;int ifwrong=0;//1表示錯誤過,0表示一遍即正確測試通過 char b1[20];//輸入英語單詞答案的數組 int cuo[MAX_NUM]={0}; //記錄測試錯誤單詞的序號的數組 int z;int t=0;//記錄cuo數組的下標變化的變量 int choose=1;int i;while(choose){ i = rand()%num;//調用隨機函數,隨機取中文詞 printf("\n【%s】請輸入英文單詞:",s[i].ch);//針對顯示隨機選擇的中文詞 scanf("%s",b1);//對于選擇的單詞的中文意思,寫自己的答案 for(z=0;strcmp(b1,s[i].en)!=0;z=z){ifwrong=1; printf("\n輸入錯誤!!請重新輸入:");scanf("%s",b1);users[no].c=users[no].c+1;}if(ifwrong){cuo[t++]=i;ifwrong=0;} printf("\n恭喜你,回答正確,加10分!\n\n");users[no].d=users[no].d+1;printf("\n進行錯誤單詞復習請選2,繼續測試請選1,返回上一級請選0:");scanf("%d",&choose);if(choose==0||choose==2) {if(choose==2)//選擇了單詞復習 {againrem(cuo,users[no].d);t=0;} return;}} } //英譯中測試 void yztest(int no) {users[no].c=users[no].d=0;int ifwrong=0;//1表示錯誤過,0表示一遍即正確測試通過 char b1[20];//輸入英語單詞答案的數組 int cuo[MAX_NUM]={0}; //記錄測試錯誤單詞的序號的數組int z,x=41;int t=0;//記錄cuo數組的下標變化的變量 int choose=1;int i;i = rand()%num;//隨機選擇測試詞對應的序號 while(choose){ printf("【%s】請輸入中文意思:",s[i].en);scanf("%s",b1);for(z=0;strcmp(b1,s[i].ch)!=0;z=z){ifwrong=1;printf("輸入錯誤!!請重新輸入:");scanf("%s",b1);users[no].c=users[no].c+1;}if(ifwrong){cuo[t++]=i;ifwrong=0;} printf("\n恭喜你,回答正確,加10分!\n\n");users[no].d=users[no].d+1;printf("\n繼續測試請選1,返回上一級請選0:");scanf("%d",&choose);if(choose==0||choose==2) {if(choose==2)//單詞復習 {againrem(cuo,users[no].d);t=0;} return;} } } //單個用戶的成績查詢 void list(int no)//no為當前結構體數組序號 {printf("用戶:%d的得分情況如下: \n",no);printf("\n 本次測試共計輸入錯誤:%d次 **每次扣10分**\n",users[no].c);printf(" 本次測試共計輸入正確:%d次 **每次加10分**\n",users[no].d);printf(" 本次測試總得分為:%d分\n\n",10*users[no].d-10*users[no].c);mans[no-1].score=10*users[no].d-10*users[no].c;mans[no-1].no=no; // printf("用戶%d 總得分為:%d分\n\n",mans[no-1].no,mans[no-1].score); } //成績排行榜 void paihang(int no)//no是用戶總個數 {//進行排序 for(int j=0;j<no;j++){for(int k=1;k<no-j;k++){if(mans[k-1].score>mans[k].score){temp=mans[k-1];mans[k-1]=mans[k];mans[k]=temp;}}} for(int i=no-1;i>=0;i--)//按得分從高到低,依次輸出用戶情況 {printf("用戶: %d 得分為: %d\n",mans[i].no,mans[i].score);} } //詞典維護 void maintain() {int choose;//維護功能選擇printf(" ------------------\n");printf(" 1.增加單詞\n");printf(" 2.修改單詞\n");printf(" 3.刪除單詞\n");printf(" 4.查詢單詞\n");printf(" 5.退出本菜單\n");printf(" ------------------\n");while(1){ printf(" \n請輸入維護功能編號:");scanf("%d",&choose);switch(choose){case 1:add();writefile();break;case 2:modify();writefile();break;case 3:del();writefile();break;case 4:search();break;case 5: return;default: printf("\n請在1-5之間選擇");}} } int a[MAX_MAN]={0};//定義的數組 int t=0; int flag=1;// 判斷是否為重復的用戶ID的變量 //用戶界面 void menu() { int item; int no;//當前用戶的ID編號 printf("請輸入當前使用小助手的用戶編號為: \n"); scanf("%d",&no);//輸入相應的用戶編號 for(int i=0;i<MAX_MAN;i++){if(a[i]==0)continue;else if(a[i]==no){flag=0;//現在的用戶是以前出現過的。break;} }if(flag)//用戶ID非重復! a[t++]=no; printf("*********************************************************\n");printf("# #\n");printf("# 英語單詞小助手 #\n");printf("# #\n");printf("# 版本 : v1.0 #\n");printf("# #\n");printf(" *********************************************************\n");printf("# #\n");printf("# 0.詞庫維護 1.單詞預覽 #\n");printf("# #\n");printf("# 2.單詞背誦(中英) 3.單詞背誦(英中) #\n");printf("# #\n");printf("# 4.查詢成績 5.幫助 #\n");printf("# #\n");printf("# 6.查看成績排行 7.退出單詞小助手 #\n");printf("# #\n");printf(" **********************************************************\n"); printf("\n");printf(" 請選擇您需要的操作序號(0-7)按回車確認:");int sum;scanf("%d",&item);printf("\n");readfile();switch(item){case 0:maintain();break;case 1:show();break; case 2:{zytest(no);break;}case 3:{yztest(no);break;}case 4:{list(no);break;}case 5:help();break;case 6:{ printf("用戶總數為:%d\n",t);paihang(t);break;}case 7:select =0;break;default:printf("請在0-7之間選擇\n");}flag=1; } int main() { while(select){menu();}system("pause");return 0; }調試及測試
調試:
測試截圖:
增加單詞
修改單詞
刪除單詞
單詞預覽
進行單詞測試,并且查詢成績
幫助:
測試中出錯單詞的重復記憶:
查看成績排行
經驗歸納
總結:
這次的上機實驗,我選擇了第二個題目,對一個單詞小助手程序進行功能完善與提高。
針對做錯單詞的重復記憶,在進行單詞測試時,用一個int型數組記錄相應的錯誤單詞的在詞庫中的序號,同時用一個變量記錄錯誤單詞個數。在選擇錯誤單詞的重復記憶功能之后,用將上面保存錯誤單詞的數組拿出來進行單詞的重復記憶。
對于中文查詢功能的完善,即顯示同一中文意思,多個英文單詞。為實現這個功能,在進行詞庫的單詞添加時,添加中文相同,英文不同的單詞時,有幾個英文,就添加幾次,即讓每一個英文詞都有一個對應的單詞序號(即使它們的英文詞對應的中文相同),這樣,在相應的查詢時,對于詞庫中每個與輸入的中文相同的單詞,同樣用一個int數組記錄它們的序號,接下來在一個循環中輸出這些序號對應的英文詞即可得到相應的一個中文詞對應多個意思相同的英文詞的結果
對于提高要求中的數據驗證,在添加和查詢單詞等功能中,使用了字符判斷的方法,對于輸入字符的每一個字符,都進行判斷是否為不符合的字符,一旦判斷為非法字符,直接進行錯誤處理并重新輸入。如在輸入中文時,輸入中包含了英文字符,即為非法輸入了。
而對于相應的排名功能,我在原來的基礎上,添加了一個包含用戶ID號和用戶得分的用戶結構體。在使用單詞小助手時,會首先進行用戶選擇,對于每個用戶的測試成績,疾苦在上面定義的結構體數組中,成績排行即將分數降序排序并輸出。
這次的上機對于結構體的使用與理解在以前的基礎上有所加深與提高,但是程序仍有一些不足,希望自己在以后的實驗中能夠改進。
總結
- 上一篇: Pytorch推出fx,量化起飞
- 下一篇: 标题可降解塑料之现代医药材料应用