電子英漢詞典附帶背單詞功能C語言程序設計,附錄完整代碼

電子英漢詞典附帶背單詞功能C語言程序設計,附錄完整代碼

  1. 系統需求分析

本程模擬面對英語單詞有背誦和查詢需求的用戶。用戶在實際學習過程中可能會遇到學習單詞時實體單詞書體積大不方便的情況,這時就可以使用便攜PC設備來運行此程序方便學習。在本程序中,設計設計了自動背單詞的部分。每次給用戶輸出10個單詞,用戶自己進行背誦並且立即進行測試,在測試中本程序會記錄用戶對單詞的掌握程度,並且形成熟練度等級。

在用戶遇到新的單詞時可以根據跟程序內部提供的詞庫實現查單詞的功能。通過文件實現單詞的讀取,提供給用戶。用戶也可以直接訪問詞庫,從而方便用戶的使用。

本程序使用讀取文件至鏈表和結構體數組實現具體的功能,並且把程序進行分模塊進行設計,方便後期對程序的升級和改造。

  1. 總體設計

本程序包括三部分,第一部分是將txt文件讀取至程序鏈表內,第二部分實現了把txt文件按照結構體數據塊的形式讀取至程序內的結構體數組。第三部分是直接對txt文件的增刪改操作。

在第一部分可以實現儲存單詞和詞義的操作,並且把單詞和詞義的數據直接以鏈表的形式保存在程序中,在後期的一些具體功能可以直接根據鏈表的數據來實現。鏈表的建立方便了後期的更改,方便實現後期對程序的改造升級。

第二部分程序要實現把儲存有結構體數據快的文件內容讀取到內存中,並且根據序號實現對應的單詞熟練度的顯示。完成了單詞具體內容的讀取和儲存以及對單詞熟練度按照文件的方式的讀取,方便了用戶後期重複使用。

第三部分程序是直接更改儲存有單詞熟練度的文件,每次運行本程序的背單詞部分的功能時都會改變單詞的熟練。這是需要不停的更改文件的內容,在更改文件時是按照二進制的文件形式保存,用戶不能輕易自己更改。

  1. 結果分析

本系統實現了多個功能的設計,用戶不但可以查單詞還可以背單詞以及進行自己的小測試,實現了多功能的設計特點。

單詞以及單詞熟練度的數據儲存在文件裏,從而讓用戶下次再打開程序時可以直接使用。而儲存單詞的文件使用了txt文件,並且txt文件內的單詞和翻譯按照非常統一對齊的方式儲存,從而更方便的修改單詞文件。而儲存單詞熟練度的文件和單詞文件是兩個分開的文件,熟練度通過二進制數據塊的形式保存在文件中,用戶無法直接獲得和刪改,方便了使用管理。

在後期使用過程中發現,用戶自己增加詞庫時還要打開txt文件才能修改詞庫,後期可以改進實現通過單詞系統直接向文件內增加單詞。並且使用鏈表可能過分使用了內存資源,可以通過其他儲存方式來實現單詞儲存。後期改進可以升級成使用數據庫來儲存單詞,也可以使用網絡來儲存單詞數據。

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

**

在文章結尾還有百度網盤直接儲存的程序源碼文件和詞庫文件的資源,可以直接下載

**
i下面是完整代碼:

#include<stdio.h>
#include<string.h>
// 
#include<stdlib.h> //負責malloc函數來調用內存
#include<time.h>   //實現退出函數 
#include<conio.h>//輸出隨機數
//
#define total 5000  //定義了可以可以存放的單詞總數量爲5000個 
#define file_path_1 "A:\\word\\word.txt"  //使用宏定義定義兩個文件的路徑,方便更改 
#define file_path_2 "A:\\word\\word_number.txt"  
//
struct mation
{
 int test;//儲存是否考過 考過是1,沒考過是0
 int pfy;// 熟練等級 0沒背過,1沒背會,2考試未通過,3考試通過
}stu[total],array_stu;
//
struct word
{
 int n;  //單詞的序號 
 char ci[100];
 char yi[200];
 struct word *next;  //下一個節點 
};
//
int number; //表示和n相對應
int all_number;//代表了鏈表的長度,但是在函數中難以體現  Z是單詞的總數
//
//
int a_0[5000];  //熟練度爲0的單詞 
int a_1[5000];
int a_2[5000];
int a_3[5000];
//
typedef struct word str;
struct word*head;
//
void end_struct();  //對結構體數組修改後進行重新覆蓋保存
/*
*功  能:格式化輸出單詞 
*過  程:每個單詞的長度都不相同,因此按照每個單詞固定20個空格的位置
   輸出單詞後輸出剩下的空格來讓輸出的單詞和翻譯對其格式 
*輸  入:單詞的數組 
*輸  出:無 
*/ 
void print_word(char a_word[])  //以20個單位長度爲一個顯示單元來顯示單詞
{
 int l;
 int longs=strlen(a_word);
 if(longs<20)
 {
  l=20-longs;
  printf("%s",a_word);
  while(l>0)
  {
   l--;
   printf(" ");  //20剪掉單詞的長度得到要輸出的空格的數量 
  }
 }
}
/*
*功  能:產生在一定範圍內的隨機數 
*過  程:主要使用rand函數產生隨機數 
*輸  入:整數 
*輸  出:無 
*/ 
int random(int x)
{
 srand(time(NULL));  //初始化隨機數
 x=rand()%x;  //產生隨機數 
    return(x); 
}
/*
*功  能:把儲存單詞和詞義的鏈表按照輸入的序號輸出到屏幕上 
*過  程:遍歷鏈表,根輸入序號輸出單詞 
*輸  入:儲存單詞和翻譯數據的鏈表首地址 ,要顯示的單詞序號 
*輸  出:無 
*/ 
void find_xuhao(str*head,int i)//按照序號查找鏈表裏面的單詞是
{
 str*p;
// 
 if(head==NULL)
 {
  printf("鏈表  \n");
 }
// 
 p=head;
// 
 while(head!=NULL&&p!=NULL)  //循環整個鏈表,知道找到匹配的序號 
 {
   if (i == p->n)  //判斷序號 
   {
    printf("\t%d.單詞:",p->n);
   print_word(p->ci);  //按照格式化輸出 
   printf("解釋:%s\n",p->yi);
   }
  p = p -> next;  //循環節目 
 }
}
//////////////////////////////////////////////////////////////////////
/*
*功  能:測試用戶的單詞掌握程度,每次測試5個 
*過  程:首先遍歷結構體數組,把裏面所有元素清零,然後通過函數把空數組存入文件 
*輸  入:儲存單詞和翻譯數據的鏈表首地址 
*輸  出:無 
*/ 
void find_number(str*head)
{
//
 int x,i=10,k;  //i代表了單詞的總數
//
 while(1)
 {
  i++;     //爲了讓每次random輸出的隨機數都不一樣所以讓i++來維持爲此輸入的數據不同
  if(i>16)
  break;
//
  x=random(i);
  //爲了方式一次輸出的所有數字都不一樣,如果一樣就多循環一次
  if (k == x)//K相當於一個開關,起到了控制的作用
   i--;
  else
   find_xuhao(head,x); //每生成一個隨機數就數次一次
//
  k=x;
 }
}
//////////////////////////////////////////////////////////////////////
/*
*功  能:測試用戶的單詞掌握程度,每次測試5個 
*過  程:首先遍歷結構體數組,把裏面所有元素清零,然後通過函數把空數組存入文件 
*輸  入:儲存單詞和翻譯數據的鏈表首地址 
*輸  出:無 
*/ 
void function_3 (str*head)
{
 int i,j=0,k=0;
 char a_word[20];
 str*p;
 str*now;
 now = head;
//
 if (head == NULL)
 {
  printf("鏈表  \n");
 }
// 
 p = head;
//
 printf("\n\n\n   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
 printf("    \n");
 printf("       隨機輸出五個單詞,考察背過的單詞,答錯兩次將降低單詞熟練度 \n\n");
 while (1)  //使用隨機函數通過循環五次產生五個單詞進行測試 
 {
  printf("       \n按空格開始繼續測驗!!按0退出 \n");
  int x = getch();  //產生隨機數 
  if (x == ' ')
  {
   system("cls");
//
    for (i=0;i<5000;i++)  //在所有結構體數組裏面進行循環 
   {
//
    if (stu[i].pfy == 2)  //熟練度爲2等級的單詞纔會進行測試 
    {
//
     if (k >= 5)  //限定while循環只能循環五次 
     {
      k = 0;
      break;
     }
     k++;
//
     while (head!=NULL&&p!=NULL)  //如果循環到鏈表的結尾也退出 
     {
       if (i == p->n)  //根據結構體數組的序號和鏈表的序號進行匹配找到要要找到的的那次 
       {
        printf("\t第%d個  拼寫如下單詞\n\n",p->n);
       printf("  \t\t解釋:%s",p->yi);
       printf("\t->>> :") ;
       //       
       scanf("%s",&a_word);  //從鍵盤得到單詞 
//
       j = strcmp (a_word,p->ci);  //比較兩個單詞數組的值是否相同 
//
       if (j == 0)  //正確情況 
       {
        printf("正確");
        stu[i].pfy =3; //提高一次熟練等級
        printf("\n\n");
       }
       else  //錯誤的情況 
       {
        printf("錯誤");
        printf("\n\t\t\t正確答案:");
        print_word(p->ci);  //打印出單詞 
        printf("\n\n");
        stu[i].pfy =2; //降低一次熟練等級
       }
       end_struct();  //對結構體數組修改後進行重新覆蓋保存
           }
         p = p->next;  //循環鏈表 
     }
     p = head = now;   //把鏈表的頭重新找回來
    }
   }
  }
  else if (x=='0') return;  //如果測試準備是得到的是0不是空格就會停止測試並退出 
  else printf("       重新輸入 \n\n");
 }
}
//
///*************************************************************************第二部分功能
/*
*功  能:把所有的單詞的熟練度都清除,把文件裏面的熟練度也清除 
*過  程:首先遍歷結構體數組,把裏面所有元素清零,然後通過函數把空數組存入文件 
*輸  入:無 
*輸  出:無 
*/ 
void function_2_3()///把結構體數組的所有元素都化爲0
{
 int i;
 for(i=0;i<total;i++)
 {
  stu[i].test =stu[i].pfy =0;   ///把結構體數組的所有元素都化爲0
 }
 // 
 end_struct();  //對結構體數組修改後進行重新覆蓋保存
// 
 printf("\n\n\n   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
  printf("    \n");
  printf("       數據清楚完畢 \n");
}
// 
/*
*功  能:輸出最近背過的單詞和他們的熟練度 
*過  程:按照順序測試數組存放的序號對應的單詞。通過遍歷
   鏈表來找到要測試的單詞序號,比較變量得到新的單
   詞熟練度。 把新的單詞熟練度儲存到文件中 
*輸  入:儲存單詞和翻譯的鏈表頭結構體指針 ,十個存放單詞序號的的數組 
*輸  出:無 
*/
void function_2_2(str*head)  //第二個功能,輸出最近背過的單詞
{
 int i=0,j=0,k;
 int j1=0,j2=0,j3=0,j4=0;
 int a1[5000];
 int a2[5000];
 int a3[5000];
  printf("\n\n\n   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
  printf("    \n");
  printf("       以下是最近背過的單詞 \n");
// 
 printf("\n熟練度一般:\n");
 for(i=1;i<5000;i++)
 {
  if(stu[i].pfy ==1)
  find_xuhao(head,i);
// 
 }
 printf("\n熟練度中等:\n");
 for(i=1;i<5000;i++)
 {
  if(stu[i].pfy ==2)
  find_xuhao(head,i);
// 
 }
 printf("\n熟練度很好:\n");
 for(i=1;i<5000;i++)
 {
  if(stu[i].pfy ==3)
  find_xuhao(head,i);
// 
 }
// 
}
// 
/*
*功  能:測試一個單詞是不是已經掌握 
*過  程:按照順序測試數組存放的序號對應的單詞。通過遍歷
   鏈表來找到要測試的單詞序號,比較變量得到新的單
   詞熟練度。 把新的單詞熟練度儲存到文件中 
*輸  入:儲存單詞和翻譯的鏈表頭結構體指針 ,十個存放單詞序號的的數組 
*輸  出:無 
*/
void function_2_1_test(str*head,int ten_words[10] )  //把剛剛抽到的十個單詞進行測驗
{
 int i,j=0,k;
 char a_word[20];
 str*p;
 str*now;
 now=head;
// 
 if(head==NULL)  //首先判斷是不是空鏈表 
 {
  printf("鏈表  \n");
 }
// 
 p=head;
// 
 printf("\n\n\n   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
 printf("    \n");
 printf("       檢測是否背會  按空格鍵繼續 按 0 退出\n\n");
// 
 while(1)
 {
  int x=getch();
  if(x==' '){system("cls");break;}
  else if (x == '0'){system("cls");return;}
  else printf("       重新輸入 \n\n");
 }
// 
 for(i=0;i<10;i++)
 {
   while(head!=NULL&&p!=NULL)  //通過循環找到單詞 
  {
   k=ten_words[i];
    if(k==p->n)
    {
     printf("\t第%d個  拼寫如下單詞\n\n",p->n);
    printf("  \t\t解釋:%s",p->yi);
    printf("\t->>> :") ;
    scanf("%s",&a_word);
// 
    j=strcmp(a_word,p->ci);  //比較兩個變量得到是否是正確的 
    if(j==0)
    {
     printf("正確");
     stu[k].pfy =2; //提高一次熟練等級
     printf("\n\n");
// 
    }
    else
    {
     printf("錯誤");
     printf("\n\t\t\t正確答案:");
     print_word(p->ci);  //按照特定格式輸出一個單詞 
     printf("\n\n");
     stu[k].pfy =1; //降低一次熟練等級
    }
   end_struct();  //對結構體數組修改後進行重新覆蓋保存
    }
   p=p->next;  //進行鏈表的循環 
  }
  p=head=now;   //把鏈表的頭重新找回來
 }
}
//void shuchujiegouti(); ///把程序裏面的結構體輸出出來,,,在main函數附近
/*
*功  能:找到單詞熟練度在1到0的單詞進行背單詞訓練 
*過  程:遍歷列表,找到1和0熟練度的單詞,把這是個單詞的序號儲存在數組裏,並且傳遞個訓練函數進行檢測是否會被單詞的過程 
*輸  入:儲存單詞和翻譯的鏈表頭結構體指針 
*輸  出:無 
*/
void function_2_1(str*head)  //搜索結構體數組裏面的pfy元素,得到熟練度爲0的a_0【】數組
{
 int i,j=0;
 int ten_words[10];  //存放十個單詞的序號 
// 
 for(i=1;i<5000;i++)
 {
  if(stu[i].pfy ==0||stu[i].pfy ==1)
  {
   printf("第%d個",j+1);
   find_xuhao(head,i);  
   stu[i].pfy =1;  //找到這個單詞以後就讓這個單詞的熟練度變爲1 
   ten_words[j]=i;  //讓找到的單詞序號存放到數組裏面 
   j++;  //循環增加數組的位置 
   if(j>=10)
   {
    j=0;
    i=0;
    end_struct();  //對結構體數組修改後進行重新覆蓋保存
    function_2_1_test(head,ten_words ) ; //把剛剛抽到的十個單詞進行測驗
    return;
   }
  }
 }
}
// 
/*
*功  能:在屏幕上輸出第二部部分的功能界面 
*過  程:調用了三個函數來實現過程 
*輸  入:儲存單詞和翻譯的鏈表頭結構體指針 
*輸  出:第二部分功能的界面 
*/
void function_2(str*head)
{
 while(1)
 {
  printf("\n\n\n   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
  printf("    \n");
  printf("       1:開始背單詞 \n\n"); //按找篩選和順序輸出十個單詞加之檢測
  printf("       2:最近背過的單詞\n\n");
  printf("       3:清空所有背單詞歷史以及單詞的熟練度\n\n");
  printf("\n\t\t···按空格鍵返回  : \n");
// 
  int x=getch();
// 
  switch (x)
  {
   case '1':system("cls");function_2_1(head);break;
   case '2':system("cls");function_2_2(head); break;
   case '3':system("cls");function_2_3();break;
   case ' ':system("cls");end_struct();return;  //對結構體數組修改後進行重新覆蓋保存 
   default:system("cls");printf("\n輸入錯誤,請重新輸入!"); break;
  }
 }
}
// 
/*
*功  能:按照從鍵盤上輸入的單詞找到鏈表裏面的單詞 
*過  程:遍歷鏈表,同時使用 print_word 函數進行格式化輸出單詞,保證輸出時規範整齊 
*輸  入:儲存單詞和翻譯的鏈表頭結構體指針 
*輸  出:把所有單詞和翻譯以及單詞的數量輸出到屏幕上 
*/
void find_word(str*head)
{
 str*p;  //建立一個新的指針 
 char a_word[20];  //存放來自鍵盤後輸入的單詞數組 
 int sign;  //判斷標誌,判斷兩個數組是否相同 
// 
 system("cls");
 if (head == NULL)  //找之前先要判斷是不是一個空鏈表 
 {
  printf("是空鏈表\n");
 }
// 
 p = head;
// 
 printf("\n\n\n   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
 printf("\n\t\t···輸入單詞查找:");
// 
 scanf("%s",&a_word);
// 
 printf("\n\t\t···要找到是%s\n",a_word);
// 
 while (head!=NULL&&p!=NULL)  //遍歷鏈表 
 {
  sign=strcmp(a_word,p->ci);  //通過此函數比較兩個單詞是否完全相同 
// 
  if(sign == 0)  //如果單詞相同 
  {
   printf("\n\t%d.單詞:",p->n);
   print_word(p->ci);  //通過這個函數按照一定格式在屏幕上打印出單詞 
   printf("解釋:%s\n",p->yi);
   break;  //找到單詞後就退出循環  
  }
  p = p->next;
 }
 printf ("\n\t\t···本詞庫內無( %s)\n\n",a_word );
}
/*
*功  能:把所有單詞輸出到屏幕上 
*過  程:遍歷鏈表,同時使用 print_word 函數進行格式化輸出單詞,保證輸出時規範整齊 
*輸  入:儲存單詞和翻譯的鏈表頭結構體指針 
*輸  出:把所有單詞和翻譯以及單詞的數量輸出到屏幕上 
*/
void print(str*head)//對鏈表數據的讀取,可以用來向文件內輸入
{
 str*p;
 if(head==NULL)
 {
  printf("是空鏈表\n");
 }
 printf("\n\t\t···鏈表內容如下\n");
 p=head;
 if(head!=NULL)
 printf("\t\t···單詞鏈表的單詞數量:%d\n",all_number);
 while(head!=NULL&&p!=NULL)
 {
  printf("%d.單詞:",p->n);
  print_word(p->ci);
  printf("解釋:%s\n",p->yi);
  p=p->next;
// 
 }
}
/*
*功  能:第一部分查單詞界面功能 
*過  程:集合了兩個小功能,具體功能通過其他函數顯示,這裏只顯示界面 
*輸  入:儲存單詞詞義和翻譯的鏈表 
*輸  出:顯示在屏幕上的界面 
*/
void function_1(str*head)
{
 while(1)
 {
// 
  printf("\n\n\n   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
  printf("    \n\n");
  printf("       1:輸入單詞查找詞義 \n\n");
  printf("       2:輸出數據庫內所有單詞\n");
  printf("\n\t\t···按空格鍵返回  : \n");
//  
  int x=getch();  //使用此函數直接得到鍵盤上得到的值 
//    
  switch (x)
  {
   case '1': find_word(head);break;
   case '2': system("cls");print(head);break;
   case ' ': system("cls");return;
   default:system("cls");printf("\n輸入錯誤,請重新輸入!"); break;
  }
 }
}
// 
// 
// 
//**********************下面這些函數用來構造結構體鏈表來存儲單詞的拼寫*****************************************
/*
*功  能:建立存放單詞和翻譯的鏈表 
*過  程:此函數內有兩個過程,一個是建立函數的頭,一個處理除了頭以外的數據 
*輸  入:存放單詞和翻譯的數組以及全局變量的鏈表的頭指針 
*輸  出:改變後的指向鏈表的結構體指針 
*/
str*creat(str*head,char a_word[20],char a_Translation[100]) 
{
 str*p,*tail;  //在鏈表建立過程中使用到的用來循環的變量 
// 
 str*replace_head;  //建立替代鏈表頭的指針 
 replace_head=head;
// 
 static int selectable_2;//用來再兩個while循環之間進行跳躍循環的選擇標誌,
//       //定義爲static變量意義爲每次建立一個節點都會調用一次此函數,防止該變量在退出函數後失效 
// 
 if(selectable_2 == 0)//建立鏈表的頭節點,根據selectable_2判斷標誌只執行一次這個while循環 
 {
  printf("\t\t···開始建立鏈表的首位置\n");
  head=NULL;//刪除動作
  head=p=tail=(str*)malloc(sizeof(str));//給新head賦給新的內存空間。
  head->next=NULL;
  tail->next=p;  //建立了一個正向單鏈表 
  tail=p;
  while (1)
  {
   printf("\t\t···加載完成\n");
      // scanf("%d",&i);
   if (selectable_2==1)
   break;
   p = (str*) malloc (sizeof(str));  //爲欣節點開闢一個內存地址 
// 
   strcpy (p->yi,a_Translation);    //把儲存翻譯的數組通過函數直接複製到節點裏面的數組內
   strcpy (p->ci,a_word);   //把儲存單詞的數組通過函數直接複製到節點裏面的數組內
   p->n = number;  //記錄單詞的序號 
// 
   all_number  =all_number+1;  //記錄單詞的總量,是一個全局靜態變量 
//   
   if (all_number==1) head=p;
   else tail->next = p;
   tail = p;
   selectable_2 = 1;
  }
// 
 tail->next=NULL;
 selectable_2 = 1;
 printf("\t\t···新鏈表首位置完成\n");
 return (head);
 }
// 
 if (selectable_2 == 1)  //建立好鏈表的頭以後再調用此函數只會執行下面的語句 向已有的鏈表中輸入內容
 {
  p = (str*) malloc(sizeof(str));
// 
  strcpy (p->yi,a_Translation);    ////把儲存翻譯的數組通過函數直接複製到節點裏面的數組內
  strcpy (p->ci,a_word);
  p->n = number;
// 
  all_number = all_number+1;
  p->next = NULL;
  while (replace_head ->next != NULL)//找到鏈表的尾部
  replace_head = replace_head->next;
  replace_head -> next = p;//把尾部添加信息
// 
  return (head);
 }
// 
}
// 
/*
*功  能:把文件內的數據寫進程序內存鏈表中
*過  程:通過讀取word。txt文件,打開的文件是絕對路徑!方便程序以後進行個別更改 
*輸  入:指向鏈表的結構體指針 
*輸  出:改變後的指向鏈表的結構體指針 
*/
str*Extract_words(str*head)   //打開文件,word。txt然後向鏈表內傳輸
{
 FILE*fp;  //建立一個指向文件的文件指針 
 int i//作爲存放單詞和翻譯的過程中用來循環的變量 
  ,selectable//用來再兩個while循環之間進行跳躍循環的選擇標誌 
  ,k; //用來循環初始化數組  
 long file_place_1,file_place_2;  //建立指向讀取過程中記錄讀取地址的變量 
 char one_byte,//存放最去過程中的一個字節 
 filename[50]={file_path_1};  //文件絕對路徑 
 char a_word[20],a_Translation[100];
// 
 if((fp=fopen(filename,"r"))==NULL)  //在打開文件的過程前,首先對文件的路徑和文件內容進行判斷 
  {
   printf("源文件打開錯誤");
  }
 fseek(fp,file_place_1,1);  //用來將位置指針移動到任意位置
      //把位置指針移動到離文件開頭100個字節處:
 printf("\t\t···開始加載文檔\n");
 //讀取單詞和翻譯的過程通過直接判斷讀取過程中的每一個字節來進行判斷的 
 //單詞和翻譯通過空格和回車的方式進行隔開:回車-單詞-空格-翻譯-回車-單詞-空格···
 //使用兩個分別處理單詞和翻譯的錄入過程,以一組單詞和翻譯的形式存進鏈表的一個節目 
 while(1)
 {
  selectable=0; //每在鏈表裏存進一組單詞和翻譯都把選擇恢復到觸發儲存單詞的選擇標誌上 
  i=0; //每在鏈表裏存進一組單詞和翻譯都把數組的位置循環變量清零 
     file_place_1=ftell(fp);  //循環過程中不停的讀取當前讀取到的位置
//   
  for(k=0;k<20;k++)  //每在鏈表裏存進一組單詞和翻譯就把存放單詞和翻譯的數組清零 
  a_word[k]=0;
  for(k=0;k<100;k++)
  a_Translation[k]=0;
//  
  if(file_place_1!=0)  //file_place_1只在第一次循環中正常使用,在之後都是用file_place_2來存放文件位置 
  fseek(fp,file_place_2,0); 
  else fseek(fp,file_place_1,0);  //這裏存在bug,正常用一個file_place變量就可以,只能循環一次,因此第二次以後都用另一個變量來循環 
  // 
  while((one_byte=fgetc(fp))!=EOF)   //判斷文件書否已經讀取到結尾 
  {
   if(one_byte=='\n')  //如果一開始時是回車就會觸發單詞的儲存循環 
   selectable=1;
   if(one_byte==' '&&selectable==1)  //在這個循環裏如果沒有遇到空格就會一直執行 
   {
   //printf("%s\n",a);///////////從此處進入另一個函數,這個函數要儲存在結構體內,是一個入口
   //代表一個單詞的輸入成功 ,單詞數量增加一
   break;
   }
   if(selectable==1&&one_byte!='\n')
   {
    a_word[i]=one_byte;  //讀取單詞的過程,單詞數組的一個元素就是一個字節就是一個字母 
    i++;  //在循環的過程中不停的讓數組的位置向前移動 
   }
// 
// 
  }
  file_place_2=ftell(fp);  //讀取當前文件位置,退出上面的while循環以後直接進入
  //       //下面的while無法直接判斷該從哪開始循環,因此需要判斷 
  i=0;
  selectable=0;
  // 
  while((one_byte=fgetc(fp))!=EOF) //讀取翻譯的過程 
  {
   if(one_byte==' ')
   selectable=1;
   if(one_byte=='\n'&&selectable==1)
   {
   //printf("%s\n",b);///////////從此處進入另一個函數,這個函數要儲存在結構體內,是一個入口
    break;
   }
   if(selectable==1&&one_byte!=' ')
   {
    a_Translation[i]=one_byte;
    i++;
   }
  }
  number++;
 // printf("%s\n",a);///////////從此處進入另一個函數,這個函數要儲存在結構體內,是一個入口
 // printf("%s\n",b);///////////從此處進入另一個函數,這個函數要儲存在結構體內,是一個入口
  head=creat(head,a_word,a_Translation);  //每讀取完一組單詞個翻譯就會把得到的單詞共和翻譯慈
            //儲存到鏈表的一個節點內 
  if((one_byte=fgetc(fp))==EOF)  //判斷是否已經讀取到文件的末尾 
  break;
 }
 fclose(fp);  //關閉文件,保證安全 
 return(head);
}
// 
//
///**********************下面這些函數用來構造結構體數組來存儲單詞的數據*****************************************
/*
*功  能:用來進行測試程序內的單詞熟練度是否已經正確加載
*過  程:只遍歷機構提數組的前60個元素輸出到屏幕上
*輸  入:無 
*輸  出:無  
*/
void shuchujiegouti()///把程序裏面的結構體輸出出來
{
 int i;
 printf("\n把程序裏面的結構體輸出出來\n ");
 for(i=0;i<60;i++)
 {
  printf("\n(test): %d ,(fly): %d \n",stu[i].test ,stu[i].pfy );
 }
}
/*
*功  能:獲得單詞熟練度的統計
*實  現:通過遍歷數組,把每個單詞的熟練度都進行比較,
      並且對不同熟練度的單詞進行計數,最後得到不同的熟練度的總和 
*輸  入:無 
*輸  出:無 
*/
void fenlei()  ///把得到的機構體數組進一步進行細化,分類
{
 int i,j,k,l,m;
// 
 for(i=0;i<5000;i++)
 {
  if(stu[i].pfy==0)
  {a_0[j]=i;j++;}
  if(stu[i].pfy==1)
  {a_1[l]=i;l++;}
  if(stu[i].pfy==2)
  {a_2[k]=i;k++;}
  if(stu[i].pfy==3)
  {a_3[m]=i;k++;}
// 
// 
 }
// 
}
/*
*功  能:這是一個用來測的函數,在程序運行的過程並沒喲用到這個函數
         測試把文件讀取到結構體數組內並且把結構體數組打印到屏幕上
   目的是爲了測試文件的讀取和數組的匹配 
*輸  入:無 
*輸  出:無 
*/
void duwenjianjieguoti() //把文件裏面的結構體全讀出來
{
 FILE *pp;
 int i;
// 
 printf("開始讀文件\n");
// 
 pp=fopen(file_path_2,"rb");
 while(fread(&array_stu,sizeof(array_stu),1,pp))
 {
  printf("\n(test)zzzzzz: %d ,(fly): %d \n",array_stu.test ,array_stu.pfy );
  i++;
  if(i>50)
  break;
// 
 }
 fclose(pp);
}
/*
*功  能:在一開始建立程序的時候從文件裏面讀取單詞的熟練度,並且
         以結構體數組的方式進行儲存 
// 
*/
void begin_struct()  //結構體數組的初始化
{
 FILE *pp;
 int i,j,k;
 for(i=0;i<total;i++)
 {
  stu[i].test =stu[i].pfy =0;   ///把結構體數組的所有元素都化爲0
 }
// 
 printf("\n\t\t···初始化結構體數組完成\n");
// 
 printf("\t\t···開始讀文件\n");
 pp=fopen(file_path_2,"rb");  //以只讀取的形式打開文件
// 
 for(i=0;i<total;i++)
 {
  fread(&array_stu,sizeof(array_stu),1,pp);
  stu[i].test =array_stu.test ;
  stu[i].pfy =array_stu.pfy ;
 }
}
/*
*功  能:重新把改變的單詞的熟練度寫入到文件內
*輸  入:無 
*輸  出:無 
*/ 
void end_struct()  //對結構體數組修改後進行重新覆蓋保存
{
 FILE *pp;
 int i;
// 
 pp=fopen(file_path_2,"wb");//以覆蓋的方式寫到文件裏
// 
 for(i=0;i<total;i++)
 {
  if(fwrite(&stu[i],sizeof(struct mation),1,pp)!=1) //寫操作
  printf("寫入文件出錯");
 }
 fclose(pp);
 printf("······\n");
}
/*
*主函數,在數函數內會首先進行鏈表和結構體數組的初始化
*程序運行的過程中不會改變鏈表裏面的內容
*當程序運行到需要改變單詞的熟練度的時候會首先改變內存裏面的變量
*完成改變內存內的變量後會,再把內存裏面的變量重新放回文件內完成熟練度的更新
*/ 
main()
{
// 
 struct word*head;
 int x;
// 
 head=Extract_words(head);  //建立鏈表,初始化鏈表和文件 
// 
 begin_struct();  //結構體數組的初始化
// 
 printf("\n\t\t按空格鍵繼續···");
// 
 int l=getch();  //使用函數不用回車直接得到鍵盤值 
// 
 if(l==' ')
 system("cls");
 else return(0);
// 
// 
 while(1)
 {
 system("cls");
 printf("\n\n\n   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
 printf("    歡迎來到 小花背單詞 小程序\n\n");
 printf("       1: 查單詞\n\n");
 printf("       2:一起來背單詞\n\n");
 printf("       3:檢測\n\n");
 printf("       4:新功能");
 printf("\n\n      按下數字0退出程序  : ");
// 
// 
 int x=getch();
// 
     switch (x)
   {
    case '1':system("cls");function_1(head);break;
    case '2':system("cls");function_2(head);break;
    case '3':system("cls");function_3(head); break;
    case 4: break;
    case '0':end_struct();  //對結構體數組修改後進行重新覆蓋保存
     exit(0);
    default:system("cls");printf("\n輸入錯誤,請重新輸入!"); break;
// 
   }
 }
}

下面是按照模塊化多個.h文件進行設計的程序源碼以及程序需要用到的單詞庫:

百度網盤鏈接

提取碼爲 : fljs

鏈接:https://pan.baidu.com/s/1pDPyjLGcsM3G8TbF2PpmZg
提取碼:fljs

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章