//用链表实现背单词系统
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>

/*
    背单词系统
    实现的功能
   1.支持单词的录入
   2.支持英查汉
   3.支持汉查英
   4.支持背单词
   5.支持单词的持久化保存
   6.有生词本功能  
   7.统计背单词的相关信息
   8.可以读全部保存的单词
*/

typedef struct node{
  char eng[50];
  char chi[20];
  struct node* next;
}Node;

//代码中用了两个链表两个文件,一个用于存放单词,一个用于生词本

int createlink();//将字典文件中的数据导入到链表
Node* list_init(); //初始化链表
void print_list(Node* head);//打印所有单词
int search_chi(Node* head);//英查汉
int print_list1(Node* head);//返回单词个数
void tail_insert(Node* head);//尾插
int search_eng(Node* head);//汉查英
Node* rem_word(Node*head,int count,Node* un_head);//背单词
//char* fin_word(Node*head,int count);

Node* unknow_list_init();//初始化生词的链表
int createlink1(Node* un_head);//将生词文件中的数据打印到链表
void tail_insert_un(Node* unhead,Node* p);//尾插生词
int print_list_un(Node* un_head);//打印生词表

//初始化链表
Node* list_init()
{
  Node* head = (Node*)malloc(sizeof(Node));//申请一个头节点空间
  
  //判断是否申请成功
  assert(head);

  //初始化
  strcpy(head->eng,"0");
  strcpy(head->chi,"0");
  head->next=NULL;
  
  return head;//返回头节点

}

//尾插法向链表中放入单词
void tail_insert(Node* head)
{
  createlink();

  //开辟一个新的节点,向尾部链接
  Node* new_node = (Node*)malloc(sizeof(Node));
  assert(new_node);
  
  //初始化新节点
  char new_word[40]="0";
  char new_chi[20]="0";
  
  printf("请输入录入单词\n");
  scanf("%s",new_word);
 
  getchar();
  printf("请输入录入单词的意思\n");
  scanf("%s",new_chi);
  getchar();

  
  strcpy(new_node->eng,new_word);
  strcpy(new_node->chi,new_chi);
  new_node->next = NULL;

  assert(head);//判断头指针是否为空
  
  //定义一个临时变量p,来代替head移动
  Node* p = head;
  
  //找到尾节点
  while(p->next!=NULL)
  {
    p=p->next;
  }
  
  //将添加到节点的元素追加到fp文件中
  FILE* fp=fopen("/mnt/hgfs/share/Sep/dictionary.txt","a+");
  fprintf(fp,"%s %s",new_node->eng,new_node->chi);
  fprintf(fp,"\n"); 
  fclose(fp);

  //尾插,连接节点
  p->next = new_node;
}

//汉查英
int search_eng(Node* head)
{
  createlink();//将文件中的内容读到链表中

  assert(head);
  Node* p = head;
  printf("请输入汉语:\n");
  char chinese[50]="0";
  scanf("%s",chinese);

  while(p->next!=NULL)
  {
   p=p->next;
   if(strcmp(p->chi,chinese)==0)
   {
     printf("%s\n",p->eng);
   }

  }
 // printf("还没录入此单词!\n");
  return -1;

}

//英查汉
int search_chi(Node* head)
{
  createlink();//将文件中的内容读到链表中

  assert(head);
  Node* p = head;
  printf("请输入英文:\n");
  char english[50]="0";
  scanf("%s",english);

  while(p->next!=NULL)
  {
   p=p->next;
   if(strcmp(p->eng,english)==0)
   {
     printf("%s\n",p->chi);
   }

  }
 // printf("还没录入此单词!\n");
  return -1;
}

//遍历并打印整个链表
void print_list(Node* head)
{
  createlink();

  Node* p=head;
  assert(p);
 
  while(p->next!=NULL)
  {
    p=p->next;
//    count++;
    printf("%s %s\n",p->eng,p->chi);
  }
  //printf("%d\n",count);
  //return count;
}

//计算单词个数
int print_list1(Node* head)
{
  createlink();

  Node* p=head;
  assert(p);
  int count=0;
  while(p->next!=NULL)
  {
    p=p->next;
    count++;
    //printf("%s %s\n",p->eng,p->chi);
  }
  //printf("%d\n",count);
  return count;
}

//从文件中读取数据存入链表 
int createlink(Node*head)
{
    //创建新的链表,将读到的数据存入链表中
    //Node *head =(Node*)malloc(sizeof(Node));
    Node* h = head;
    char new_eng[50];
    char new_chi[40];

    Node *p=h;
    Node *q=h;
    FILE * r= fopen("/mnt/hgfs/share/Sep/dictionary.txt","r");
    if(r==NULL)
    {
        printf("打开文件失败!");
        return -1; 
    }
     
    while(fscanf(r,"%s %s",new_eng,new_chi)!=EOF)
    {  
       q= (Node*)malloc(sizeof(Node));
       strcpy(q->eng,new_eng);
       strcpy(q->chi,new_chi);
       p->next=q;
       p=q;
    }
    p->next=NULL;
    fclose(r);
   // return h;

}

//背单词功能
Node* rem_word(Node*head,int count,Node* un_head)
{
   
 
    int error = 0;//计数
 
    int i = 0;
    for(i=0;i<10;i++)
    {
      Node* p = head;
      int num=0;//记录随机拿出节点的索引,利用索引找到出单词
 
      int s=rand()%count+1;//rand产生一个1~count间的

      //随机生成一个单词
      while(p->next!=NULL)
      {
        p=p->next;
        num++;
        if(num==s)
        {
          printf("%s",p->eng);//生成p->eng
          break;        
        }
     
    
      }
   
      char ch[20]={0};
      scanf("%s",ch);
      if(strcmp(ch,p->chi)==0) //比较
      {
        printf("拼写成功\n");
      }
      else
      {
        printf("拼写失败\n");
        error++;
        tail_insert_un(un_head,p);

      }
      
    }
  
  //正确/全部 算出正确率
  double result =((10-error)/10.0)*100;
  printf("正确:%d  ",10-error);
  printf("错误:%d\n",error);
  printf("您的正确率是:%lf\n",result);
  
 
 }
 
 
//初始化链表来存放生词
Node* unknow_list_init()
{
  Node* un_head = (Node*)malloc(sizeof(Node));//申请一个头节点空间
  
  //判断是否申请成功
  assert(un_head);

  //初始化
  strcpy(un_head->eng,"0");
  strcpy(un_head->chi,"0");
  un_head->next=NULL;
  
  return un_head;//返回头节点
 
}
 
 
//还原链表,从生词本文件中读取数据到链表
int createlink1(Node* un_head)
{
    //创建新的链表,将读到的数据存入链表中
    //Node *head =(Node*)malloc(sizeof(Node));
    Node* h = un_head;
    char new_eng[50];
    char new_chi[40];

    Node *p=h;
    Node *q=h;
    FILE * r= fopen("/mnt/hgfs/share/Sep/dictionary1.txt","r");
    if(r==NULL)
    {
        printf("打开文件失败!");
        return -1; 
    }
     
    while(fscanf(r,"%s %s",new_eng,new_chi)!=EOF)
    {  
       q= (Node*)malloc(sizeof(Node));
       strcpy(q->eng,new_eng);
       strcpy(q->chi,new_chi);
       p->next=q;
       p=q;
    }
    p->next=NULL;
    fclose(r);
   // return h;

}

//尾插法向链表中放入单词
void tail_insert_un(Node* un_head,Node* p)
{
  createlink1(un_head);

  //开辟一个新的节点,向尾部链接
  Node* new_node = (Node*)malloc(sizeof(Node));
  assert(new_node);
  
  
 
  strcpy(new_node->eng,p->eng);
  strcpy(new_node->chi,p->chi);
  new_node->next = NULL;
  
  assert(un_head);//判断头指针是否为空
  
  //定义一个临时变量p,来代替head移动
  Node* pp = un_head;
  
  //找到尾节点
  while(pp->next!=NULL)
  {
    pp=pp->next;
  }
  
  //将添加到节点的元素追加到fp文件中
  FILE* fp=fopen("/mnt/hgfs/share/Sep/dictionary1.txt","a+");
  fprintf(fp,"%s %s",new_node->eng,new_node->chi);
  fprintf(fp,"\n"); 
  fclose(fp);
  
  //尾插,连接节点
  pp->next = new_node;
}
 
 
//遍历并打印整个生词本链表
int print_list_un(Node* un_head)
{
  createlink1(un_head);
 
  Node* p=un_head;
  assert(p);
  int count=0;
  while(p->next!=NULL)
  {
    p=p->next;
    count++;
    printf("%s %s\n",p->eng,p->chi);
  }
  printf("%d\n",count);
  return count;
}

int main()
{
 
  Node* head = list_init();
  int count = print_list1(head);
  Node* un_head = unknow_list_init();//返回新建生词本链表的头指针
  //createlink1(un_head);
 

  printf("\n");

  while(1)
  {
    printf("----------------请输入对应的功能--------------------\n");
    printf("----------------1. 根据汉语查英语 ------------------\n");
    printf("----------------2. 根据英语查汉语 ------------------\n");
    printf("----------------3. 查看生词本-----------------------\n");
    printf("----------------4. 向系统中添加单词 ----------------\n");
    printf("----------------5. 背单词---------------------------\n");
    printf("----------------6. 查看所有单词---------------------\n");
    printf("----------------7. 退出-----------------------------\n");
   
    printf("请输入您的操作:\n");
    int input=0;
    scanf("%d",&input);
    switch(input)
    {
      case 1:search_eng(head);break;
      case 2:search_chi(head);break;
      case 3:print_list_un(un_head);break;
      case 4:tail_insert(head);break;
      case 5:rem_word(head,count,un_head);break;
      case 6:print_list(head);break;
      case 7:return -1;break;
      default:printf("输入有误\n");
      return -1;
    }
  }
  return 0;
}