C語言編程練習:通訊錄


一、目標描述:

1、建立一個通訊錄,按姓名字母排序存儲聯系人信息。

2、可顯示菜單提供顯示、新增、刪除、修改等功能。

3、顯示:(1)顯示聯系人數量及全部聯系人信息;(2)提供特定條件查詢指定聯系人信息。

4、新增:逐步提示對應信息輸入。

5、刪除:刪除指定聯系人信息。

6、修改:提供特定條件修改指定單個聯系人信息:先顯示原先信息,再提供選項修改對應條目。

7、通訊錄信息保存在文件中。

二、目標分析:

1、項目需要排序、新增,則考慮使用二叉搜索樹來建立數據堆模型。

2、該模型須提供以下具體功能模塊:(1)初始化(2)新增項目(3)刪除(4)查詢有無(5)修改

3、信息要保存到文件中,每一次更新信息都要對應到文件中;則上述功能模塊都要增加讀寫文件功能才能更新文件,這是一個復雜而且現階段我很難實現的工作,只考慮下面一種很笨拙但相對簡單的實現方式:在上述功能模塊中:(2)新增(3)刪除(5)修改功能后提供文件更新,同時文件更新不針對某條具體的(新增的或刪除的或修改的)信息,而是對應功能完成后文件按整個通訊錄重新寫入。因此增加功能模塊(6)將整個二叉樹信息依序寫入文件。

4、程序第一次運行,文件信息為空,通過程序新增錄入信息,並且文件得以更新,這沒有問題。可第二次,第三次運行呢?文件已經存在,而且已經有信息了,可程序運行之初二叉樹數據堆是空的,怎樣讀取文件中的信息,並寫入二叉樹模型呢?

如果在文件中聯系人信息如下設置:

"Name:""-Bir_Year:""-..."可通過文本字符串判斷然后寫入二叉樹的節點;另外一點,選擇按姓名比較建立二叉樹。同時,每個聯系人信息結尾用換行符進行標記。

三、功能模塊的具體思路

1、初始化

先讀取文本,建立二叉樹聯系人模型;若文本為空,則初始化空樹。

2、新增

提示輸入姓名,寫入相關信息,建立節點,依據姓名找到合適位置插入二叉樹。依據更新的二叉樹,重新寫入文本。

3、刪除

提示輸入被刪姓名,刪除該節點。依據更新的二叉樹,重新寫入文本。

4、查詢有無

提示輸入查詢條件,找到相關信息並顯示。該模塊為功能2、3、5提供支持。

5、修改

提示輸入被修改姓名,修改操作。依據更新的二叉樹,重新寫入文本。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void IniTree();
void AddNode();
void ChoiceAdd();
void ShowTree();
int SeekName();
void ChoiceDel();
void DeleteNode();
void Choicefind();
void Choicemod();
void ShowMainInterface();
void NodeWrite();



typedef struct member
{
   char name[20];
   char sex;
   char bir_year[5];
   char bir_month[3];
   char bir_day[3];
   char qq[15];
}Member;

typedef struct node
{
   Member *person;
   struct node *left;
   struct node *right;
}Node;

typedef struct tree
{
   Node *root;
   int numbers;
}Tree;



void ShowMainInterface()
{
  printf("Input your choice:\n");
  printf("a)show all friends.\n");
  printf("b)add a friend's information.\n");
  printf("c)modify a friend's information.\n");
  printf("d)delete a friend.\n");
  printf("e)look for a friend's information.\n");
  printf("q)Quit.\n");
}
void IniTree(Tree *ptree)
{
  FILE *fp;
  Node *newnode;
  int i=0;
  char name[20];
  char sex;
  char bir_year[5];
  char bir_month[3];
  char bir_day[3];
  char qq[15];
  char ch;
  fp=fopen("c.txt","r");
//如果文件不存在,則初始化二叉樹
  if(fp==NULL)
  {
     ptree->root=NULL;
     ptree->numbers=0;
     printf("FILE Error!\n");
  }
//文件存在,則讀入文件,創建二叉樹節點信息
  else
  {
  ch=getc(fp);
//每個換行符前為一個聯系人信息,每行建一個節點
//讀文件前,先初始化樹
  ptree->root=NULL;
  ptree->numbers=0;
  while(ch!=EOF)
  {
   while((ch!='\n')&&(ch!=EOF))
   {
     newnode=(Node*)malloc(sizeof(Node));
     while(ch!='-')
     { 
         newnode->person->name[i]=ch;
         i++;
         ch=getc(fp);
     }
     newnode->person->name[i]='\0';
//姓名信息錄入完畢,重置i,繼續讀取下一個字符
     i=0;
     ch=getc(fp);
     while(ch!='-')
     { 
         newnode->person->sex=ch;
         ch=getc(fp);
     }
//性別信息錄入完畢,重置i,繼續讀取下一個字符
     i=0;
     ch=getc(fp);
     while(ch!='-')
     { 
         newnode->person->bir_year[i]=ch;
     i++;
         ch=getc(fp);
     }
     newnode->person->bir_year[i]='\0';
//出生年信息錄入完畢,重置i,繼續讀取下一個字符
     i=0;
     ch=getc(fp);
     while(ch!='-')
     { 
         newnode->person->bir_month[i]=ch;
     i++;
         ch=getc(fp);
     }
     newnode->person->bir_month[i]='\0';
//出生月信息錄入完畢,重置i,繼續讀取下一個字符
     i=0;
     ch=getc(fp);
     while(ch!='-')
     { 
         newnode->person->bir_day[i]=ch;
     i++;
         ch=getc(fp);
     }
     newnode->person->bir_day[i]='\0';
//出生日信息錄入完畢,重置i,繼續讀取下一個字符
     i=0;
     ch=getc(fp);
     while(ch!='-')
     { 
         newnode->person->qq[i]=ch;
     i++;
         ch=getc(fp);
     }
     newnode->person->qq[i]='\0';
//qq信息錄入完畢,該聯系人所有信息錄入完畢,建立該聯系人節點信息,插入樹
     newnode->left=NULL;
     newnode->right=NULL;
     AddNode(newnode,ptree);
//此時ch到了行末,為'-'
//繼續讀取下一個字符
     ch=getc(fp);
    }
//單行節點信息錄入完畢,重置i
    i=0;
    ch=getc(fp);
  }
 }
}
     
//使用前須確保無相同節點
void AddNode(Node *node,Tree *ptree)
{
   Node *newnode,*fathernode;
   newnode=ptree->root;
   while(newnode!=NULL)     //找空位,並且定位空位的父節點
   {
         if(strcmp(node->person->name,newnode->person->name)<0)
         {
              fathernode=newnode;      
              newnode=newnode->left;
         }
     else
         {
              fathernode=newnode;      
              newnode=newnode->right;
         }
    } 
       
    if(ptree->root==NULL)  //如果樹為空
    {
           ptree->root=node;
           ptree->numbers++; 
    }
    else
    {
         if(strcmp(node->person->name,fathernode->person->name)<0)   //說明父節點左子節點為空
         {    
        fathernode->left=node;
        ptree->numbers++;
     }
         else
         {    
        fathernode->right=node;
        ptree->numbers++;
     }
     }
  
}

void ChoiceAdd(Tree *ptree)
{
  Node *newnode;
  char namex[20];
  printf("please input the name:\n");
  scanf("%s",namex);
  while(getchar()!='\n') continue;
  if(SeekName(namex,ptree->root)==1)
    printf("the person:%s is exist.\n",namex);
  else
  {
    newnode=(Node*)malloc(sizeof(Node));
    strcpy(newnode->person->name,namex);
    printf("\nplease input the sex(F or M):\n");
    scanf("%c",&(newnode->person->sex));while(getchar()!='\n') continue;
    printf("\nplease input the bir_year:\n");
    scanf("%s",newnode->person->bir_year);while(getchar()!='\n') continue;
    printf("\nplease input the bir_month:\n");
    scanf("%s",newnode->person->bir_month);while(getchar()!='\n') continue;
    printf("\nplease input the bir_day:\n");
    scanf("%s",newnode->person->bir_day);while(getchar()!='\n') continue;
    printf("\nplease input the QQ:\n");
    scanf("%s",newnode->person->qq);while(getchar()!='\n') continue;
  
    newnode->left=NULL;
    newnode->right=NULL;
    AddNode(newnode,ptree);
    printf("-----%s information recorded!---------\n",namex);
   }
}

void ShowTree(const Node *root)
{
  Node *newnode;
  newnode=root;
  if(newnode!=NULL)
  {
     ShowTree(newnode->left);
     printf("%s--%c--%s--%s--%s--%s.\n",root->person->name,root->person->sex, 
              root->person->bir_year,root->person->bir_month,
          root->person->bir_day,root->person->qq);
     ShowTree(newnode->right);
  }
}

//查找樹中有無指定姓名
//若有返回1,若無返回0
int SeekName(char name[20],const Node *root)
{
   Node *pnode;
   if(root==NULL)
      return 0;
   pnode=root;

   while(pnode!=NULL)
   {  
      if(strcmp(name,pnode->person->name)<0)
      {
     pnode=pnode->left;
      }
      else if(strcmp(name,pnode->person->name)>0)
      {
     pnode=pnode->right;
      }
      else
         return 1;
   }
   return 0;
}


void ChoiceDel(Tree *ptree)
{
  Node *nodef,*nodec;
  char namex[20];
  printf("please input the name:\n");
  scanf("%s",namex);
  if(SeekName(namex,ptree->root)==0)
  {
    printf("the person %s is not exist!\n",namex);
  }
  else
  {
    nodec=ptree->root;
    nodef=NULL;
    while(nodec!=NULL)
    {
       if(strcmp(namex,nodec->person->name)<0)
       {
      nodef=nodec;
      nodec=nodec->left;
       }
       else if(strcmp(namex,nodec->person->name)>0)
       {
      nodef=nodec;
      nodec=nodec->right;
       }
       else
      break;
     }//找到該節點及其父節點
     if(nodef==NULL)
          DeleteNode(&ptree->root);
     else if(nodef->left==nodec)
          DeleteNode(&nodef->left);
     else 
          DeleteNode(&nodef->right);
     ptree->numbers--;
     printf("--------%s is deleted!---------\n",namex);
     
   }
}

//刪除結點函數,參數如何描述?
//刪除操作后被刪除結點的父節點的“指向被刪結點的指針成員”要重新賦值
//所以要用指向“父節點指針成員”的指針去描述
//而父節點指針成員本身是一個Node*指針型,所以參數類型為Node **
//注意:這里的ptr是指向父節點指針成員(指向被刪結點)的指針類型
//*ptr描述的是父節點中指向被刪結點的指針成員,也即被刪結點的地址指針類型
//**ptr則是描述被刪除的結點類型
void DeleteNode(Node **ptr)
{
  Node *temp;
//*ptr為被刪結點父節點的指針成員,該成員指向被刪結點,
//(*ptr)->left即指向被刪結點的左子節點
//若其左子節點為空,將其右子節點鏈接到父節點原先指向被刪結點的指針成員
  if((*ptr)->left==NULL)   
  {
    temp=*ptr;
    *ptr=(*ptr)->right;
    free(temp);
  }
//若其右子節點為空,將其左子節點鏈接到父節點原先指向被刪結點的指針成員
  else if((*ptr)->right==NULL)
  {
    temp=*ptr;
    *ptr=(*ptr)->left;
    free(temp);
  }
  else  //被刪除結點有兩個子結點
  {
    for(temp=(*ptr)->left;temp->right!=NULL;temp=temp->right)
        continue;
    temp->right=(*ptr)->right;
    temp=*ptr;
    *ptr=(*ptr)->left;
    free(temp);
  }
} 

void Choicefind(Tree *ptree)
{
  Node *nodef,*nodec;
  char namex[20];
  printf("please input the name:\n");
  scanf("%s",namex);
  if(SeekName(namex,ptree->root)==0)
  {
    printf("the person %s is not exist!\n",namex);
  }
  else
  {
    nodec=ptree->root;
    nodef=NULL;
    while(nodec!=NULL)
    {
       if(strcmp(namex,nodec->person->name)<0)
       {
      nodef=nodec;
      nodec=nodec->left;
       }
       else if(strcmp(namex,nodec->person->name)>0)
       {
      nodef=nodec;
      nodec=nodec->right;
       }
       else
      break;
     }//找到該節點及其父節點
     printf("the person:%s information is followed:\n");
     printf("name:%s\n",nodec->person->name);
     printf("sex:%c\n",nodec->person->sex);
     printf("bir_year:%s\n",nodec->person->bir_year);
     printf("bir_month:%s\n",nodec->person->bir_month);
     printf("bir_day:%s\n",nodec->person->bir_day);
     printf("qq:%s\n",nodec->person->qq);
   }
   printf("input any key to continue...\n");
   getch();
} 


void Choicemod(Tree *ptree)
{
  Node *nodef,*nodec;
  char namex[20];
  char ch;
  printf("please input the name:\n");
  scanf("%s",namex);
  if(SeekName(namex,ptree->root)==0)
  {
    printf("the person %s is not exist!\n",namex);
  }
  else
  {
    nodec=ptree->root;
    nodef=NULL;
    while(nodec!=NULL)
    {
       if(strcmp(namex,nodec->person->name)<0)
       {
      nodef=nodec;
      nodec=nodec->left;
       }
       else if(strcmp(namex,nodec->person->name)>0)
       {
      nodef=nodec;
      nodec=nodec->right;
       }
       else
      break;
     }//找到該節點及其父節點
     printf("--------------------Please choose--------------------\n");
     printf("a)----------modify name----%s\n",nodec->person->name);
     printf("b)----------modify sex----%c\n",nodec->person->sex);
     printf("c)----------modify bir_year----%s\n",nodec->person->bir_year);
     printf("d)----------modify bir_month----%s\n",nodec->person->bir_month);
     printf("e)----------modify bir_day----%s\n",nodec->person->bir_day);
     printf("f)----------modify qq----%s\n",nodec->person->qq);
     printf("q)---------------quit to upperlevel------------------\n");
   
     ch=getch();
     printf("your choice is %c.\n",ch);
     while(getchar()!='\n') continue;
     while(ch!='q')
     {
       while(ch!='a'&&ch!='b'&&ch!='c'&&ch!='d'&&ch!='e'&&ch!='f'&&ch!='q')
       {
      printf("input a or b or c or d or e or f or q.\n"); 
          ch=getchar();
          printf("your choice is %c.\n",ch);
       }
       switch(ch)
       {
    case 'a':
            printf("input %s new name:",nodec->person->name);
            scanf("%s",nodec->person->name);
            while(getchar()!='\n') continue;
            break;
    case 'b':
            printf("input %s new sex:",nodec->person->name);
            scanf("%c",&(nodec->person->sex));
            while(getchar()!='\n') continue;
            break;
    case 'c':
            printf("input %s new bir_year:",nodec->person->name);
            scanf("%s",nodec->person->bir_year);
            while(getchar()!='\n') continue;
            break;
    case 'd':
            printf("input %s new bir_month:",nodec->person->name);
            scanf("%s",nodec->person->bir_month);
            while(getchar()!='\n') continue;
            break;
    case 'e':
            printf("input %s new bir_day:",nodec->person->name);
            scanf("%s",nodec->person->bir_day);
            while(getchar()!='\n') continue;
            break;
    case 'f':
            printf("input %s new QQ:",nodec->person->name);
            scanf("%s",nodec->person->qq);
            while(getchar()!='\n') continue;
            break;
    case 'q':
            break;
       }
       if(ch!='q')
       {
     printf("--------------------Please choose--------------------\n");
     printf("a)----------modify name----%s\n",nodec->person->name);
     printf("b)----------modify sex----%c\n",nodec->person->sex);
     printf("c)----------modify bir_year----%s\n",nodec->person->bir_year);
     printf("d)----------modify bir_month----%s\n",nodec->person->bir_month);
     printf("e)----------modify bir_day----%s\n",nodec->person->bir_day);
     printf("f)----------modify qq----%s\n",nodec->person->qq);
     printf("q)---------------quit to upperlevel------------------\n");
         ch=getch();
         printf("your choice is %c.\n",ch);
       }
       
       
     }
  }
} 


void NodeWrite(const Node *node)
{
   FILE *fp;
   fp=fopen("c.txt","a");
   fprintf(fp,"%s",node->person->name);
   putc('-',fp);
   putc(node->person->sex,fp);
   putc('-',fp);
   fprintf(fp,"%s",node->person->bir_year);
   putc('-',fp);
   fprintf(fp,"%s",node->person->bir_month);
   putc('-',fp);
   fprintf(fp,"%s",node->person->bir_day);
   putc('-',fp);
   fprintf(fp,"%s",node->person->qq);
   putc('-',fp);
   putc('\n',fp);
   fclose(fp);
}

void TreeWrite(const Node *root)
{
   Node *pnode;
   pnode=root;
   if(pnode!=NULL)
   {
     TreeWrite(pnode->left);
     NodeWrite(pnode);
     TreeWrite(pnode->right);
   }
}


int main(void)
{
//變量設置區----------------------------------------
  Tree *ctree;
  char ch;
//變量設置結束--------------------------------------
 
//程序信息區-----------------------------------------
  printf("*******************************************************************\n");
  printf("-----------------------------Address Book--------------------------\n");
  printf("------------------------------Version1.0---------------------------\n");
  printf("-----------------------------By TSEMBRACE--------------------------\n");
  printf("*******************************************************************\n");  
//程序信息結束---------------------------------------

//初始化數
  IniTree(ctree);

//主操作界面區---------------------------------------
  ShowMainInterface();
  
  ch=getch();
  while(ch!='q')
  {
    while((ch!='a')&&(ch!='b')&&(ch!='c')&&(ch!='d')&&(ch!='e'))
    {
       printf("choose a or b or c or d or e or q!\n");
       ch=getch();
       if(ch=='q')
     break;
    }
       
    
    switch(ch)
    {
      case 'a':
         if(ctree->root==NULL)
            printf("-----------There is no information.------------\n");
     else
     {printf("---------My Address List is followed:---------\n");
      ShowTree(ctree->root);
      printf("------------------My Address List end-------------------\n");
         }
         printf("Total number is %d.\n",ctree->numbers);
         ShowMainInterface();
         printf("please choose:\n");
         ch=getch();  
         printf("your choose is:%c\n",ch);     
     break;
      case 'b':ChoiceAdd(ctree);ShowMainInterface();
         printf("please choose:\n");
         ch=getch();
         printf("your choose is:%c\n",ch);        
     break;
      case 'c':Choicemod(ctree);ShowMainInterface();
         printf("please choose:\n");
         ch=getch(); 
         printf("your choose is:%c\n",ch);       
     break;
      case 'd':ChoiceDel(ctree);ShowMainInterface();
         printf("please choose:\n");
         ch=getch();
         printf("your choose is:%c\n",ch);        
     break;
      case 'e':Choicefind(ctree);ShowMainInterface();
         printf("please choose:\n");
         ch=getch();
         printf("your choose is:%c\n",ch); 
     break; 
      case 'q':
         printf("your choose is:q\n"); 
     break;
     }
  }
  
  TreeWrite(ctree->root);
  printf("GoodBye!\ninput any key to quit.");
     
//主操作界面結束-------------------------------------

  getch();
  return 0;
}

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM