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;
}

 

 

 

posted @ 2013-07-21 19:48  tsembrace  阅读(10587)  评论(0编辑  收藏  举报