数据结构课程设计 班级通讯录

题目描述:以文本的方式保存用户录入的数据,并提供查询的功能共用户查询和使用通信录信息。

功能要求及说明:

通讯录要求实现最基本的功能,包括录入、删除、查找和修改,为此需要首先定义记录项的格式,其基本属性包括编号、姓名、性别、住址、联系电话等。整个系统由如下几大功能模块组成:

(1)通讯录的建立;该模块主要完成将数据存储工作。记录可以从文本文件中读入,也可以从键盘逐条输入记录。

(2)通讯录查询;用户可以按照联系人的姓名或电话号码查询。若查到,则显示该记录的信息;否则,显示查找失败的提示信息。

(3)通讯录的维护;实现对记录的修改、删除、插入和排序等操作。

(4)通讯录的输出;实现屏幕显示和将记录信息写入文本文件中.

(5)采用模块化设计。

以上功能请以菜单形式与用户进行交互

1、数据类型的定义及含义:

(1)结构体类型data,用来描述每个学生的基本属性(学号、姓名、性别、地址、电话号码)。

(2)链表类型Link *L,表示以L为头结点的单链表,用来描述整个通讯录学生之间的关系,用单链表来存储数据元素信息。

(3)文件指针类型 FILE *fp;用来操作文件,指向文件中的字符。

2、主函数调用的函数的定义:

(1)void CreatLink(Link *L);  //创建通讯录,调用了2个函数,

(2)void CreateLInk_from_file(Link*L);   //从文本文件中读入

(3)voidCreatLink_fromkeybord(Link* L);  //从键盘逐条输入记录

(4)voidSearchLink(Link *L);     //查询通讯录

(5)voidFind_SNum(Link *L);     //按编号查询

(6)voidFind_SName(Link *L);  //按姓名查询

(7)voidFind_STel(Link *L);  //按电话号码查询

(8)void ChangeLink(Link*L);//修改通讯录

(9)voidDeleteLink(Link *L);//删除通讯录

(10)voidDestoryLink(Link *L);//销毁线性表

 (11)voidInsertLink(Link *L);//插入通讯录

(12)voidSort_Link(Link *L);  //通讯录排序,按照编号,冒泡法

(13)voidDeletesameSum(Link *L);  //删除通讯录相同的编号的结点

(14)voidPrintLink(Link *L);//显示到显示器上                            

(15)voidSave(Link *L);//保存到文件telbook.txt

(16)void Clear();//清屏函数

2、简要的主程序流程:

 

 

 

 

 

 

 

 

 

 

 

 


CreateLInk_from_file(L)

 

四 详细设计

1、流程图:

 

 

 


InsertLink(L)

 

            

        

 

 

 

 

 

 

 

 

 

 

 

 

 


2、数据的实现及定义:

struct node  

{  //通讯录结点数据域

    charSnum[20]; //编号 

    charSname[10];//姓名

       charSsex[10];  //性别

    charSaddr[20];//地址 

    charStelenum[20];//电话号码 

}; 

typedef struct node telebook; 

struct Lnode 

    telebookdata; //结点数据域

    structLnode *next;  //结点指针域

}; 

typedef struct Lnode Link; 

Link *L;//创建头节点

3、函数的实现

(1)在mian函数中先建立一个空表,链表的表头为L,显示菜单到窗口,提示用户输入choice,通过choice进入各个子菜单,进而对通讯录进行相关操作:

main()

{

char chioce;  //进入子菜单

L=(Link*)malloc(sizeof(Link));

L->next=NULL;  //先建立一个空表,通讯录建立就是尾插法

    …Menu();//调用Menu()函数

    …CreateLink(L);

   //通过chioce   

}

        (2)Menu函数就是将此通讯录管理系统的所有功能显示到窗口,便于用户更好的和此系统进行交互:

void Menu()//菜单

             {

              printf(…);

              …

}

(3)CreateLink通讯录的建立,两种方式建立通讯录:直接从键盘输入、从文本文件中读入。通讯录的建立不管是从键盘直接输入还是从文本输入;都可以看成在单链表的尾部插入新的结点:

void CreateLink(Link*L)       //通讯录的建立,传递的是链表的头结点

     {…

      if(n==1) {CreatLink_fromkeybord(L); …  //调用CreatLink_fromkeybord函数

      if(n==2) {CreateLInk_from_file(L);…     //调用CreateLInk_from_file函数

     }

(4)CreateLink函数传递的是单链表的头结点,L是不可以改变的;从文本文件中读入建立通讯录,首先找到单链表的尾结点,然后将新的结点插入到链表的最后。将文本文件内容读入到相应的链表中去,使用的是fscanf函数,之所以能够依次读入到相应的结点中去是因为fscanf函数字符串读出函数,遇到空格或者换行就会写入到相应的结点的数据域中:

void CreateLink (Link*L)     //从文本文件中读入,建立通讯录

     {

       p=L;  //头结点赋值给点P,头结点是不可以移动的

      q=(Link*)malloc(sizeof(Link));  //指向链表的任意一个结点

       while(p->next!=NULL )

       {

              p=p->next;

} //找到链表的尾,利用尾插法

 while(fscanf(fp,"%s %s%s %s%s\n",q->data.Snum,q->data.Sname,q->data.Ssex,q->data.Stelenum,q->data.Saddr)!=EOF)     //文件读入到链表

       {

              q->next=NULL;

              p->next=q;

              p=q;             //P为链表的尾

              q=(Link *)malloc(sizeof(Link));

       }

}

(5)CreatLink_fromkeybord从键盘中输入建立通讯录,尾插法,先遍历单链表找到此单链表的尾结点,然后将新的结点插入到链表的最后:

voidCreatLink_fromkeybord(Link* L)//从键盘中逐条输入,建立通讯录

     {…       //也是用的尾插法,链表的头结点始终不能变

       q->next=NULL;  //尾结点

}

(6)void InsertLink,通讯录的插入,系统会提示用户输入要插入的位置i,然后遍历单链表,找到i-1位置为结点P;然后将新的结点插入到P的后面,然后修改指针:

void InsertLink(Link*L)//通讯录的插入

     {//通讯录的插入,先找到插入位置的指针和它前一个结点的指针,然后修改指针指向

      …p->next=q->next; 

           q->next=p; 

     …

}

        (7)PrintLink通讯录的显示,就是将链表所有信息输出到屏幕,所以实现的思想就是遍历整个单链表并且将每个结点的信息输出到屏幕:

void PrintLink(Link *L)//通讯录的显示

             {…

              p=L->next;  //头结点可以不储存任何信息

             while(p!=NULL) 

             { 

              p=p->next; //将每个结点的信息输出到屏幕

              } 

}

(8)Save,保存通讯录到文件中去,就是将整个单链表保存到文件中去,实现的思想就是,先遍历整个单链表,遍历的同时将每个结点的数据域输出到文件中去,使用fptintf函数将每个结点的数据域保存到文件中:

void Save(Link *L)  //保存通讯录到文件 "F:\\telebook.txt "

     {…

      fprintf(fp,"%s   ",p->data.Saddr);  //写入到文件中

     …

}

(9)DeleteLink,删除通讯录,如果删除整个通讯录,就是  free掉每个指向结点的指针;删除某个结点就是,系统提示用户要删除结点的位置i,找到i-1位置的结点q,然后修改指针,删除p指针:

void DeleteLink(Link*L)//删除通讯录   1.删除整个通讯录  2.删除某个联系人 

     {…

     …DestoryLink(L);//函数调用

          while(j

              { 

                     j++; 

                     q=q->next; 

              } 

       …q->next=p->next;//删除了p指针

      

}

(10)DestoryLink,销毁整个单链表,彻底删除整个通讯录,free掉每个指向结点的指针:

void DestoryLink(Link*L)//销毁单链表表  ,彻底删除整个通讯录,free掉每个指向结点的指针

{  …

       p=L->next; 

      while(p!=NULL) 

      { 

        L->next=p->next; 

        free(p);//释放节点的内存 

        p=L->next; 

     } 

     free(p); 

(11)ChangeLink遍历单链表,字符串匹配找到所要修改的编号,电话号码,姓名,然后再修改相应的结点的数据域:

void ChangeLink(Link*L)     //修改通讯录

 {//遍历单链表,字符串匹配所要修改的编号,电话号码,姓名

      …

          while(q!=NULL) 

            { 

               if(strcmp(q->data.Stelenum,s)==0) 

                { 

                                   printf("输入修改的信息:\n"); 

                                   printf("电话号码:\n"); 

                                   scanf("%s",q->data.Stelenum); 

                                   printf("电话号码已经修改成功");

                                   break; 

                            } 

                            q=q->next;  //修改链表中所有的要修改的电话号码

            } 

      …

 

}

(12)SearchLink查询通讯录,有三种方式:按编号查询、按姓名查询、按电话号码查询;三种方式的思想都是差不多的,遍历单链表的同时,字符串匹配,找到就输出所满足要求的学生的所有信息:

void SearchLink(Link*L)    //查询通讯录

     {…

      if(n==1) {Find_SNum(L);return;}     // 调用按编号查询

if(n==2){Find_SName(L);return;}  //调用按姓名查询

      if(n==3) {Find_STel(L);return;}      //调用按电话号码查询

}

(13)voidFind_SName(Link *L)//按姓名查询

     {…

while(q!=NULL&&strcmp(q->data.Sname,p->data.Sname)!=0) 

     { 

        q=q->next;  //遍历单链表,字符串匹配

     }  …

}

(14)voidFind_SNum(Link *L) //按编号查询

     {…

     while(q!=NULL&&strcmp(q->data.Snum,p->data.Snum)!=0) 

     { 

        q=q->next;  //遍历单链表,字符串匹配

     } …

}

(15)voidFind_STel(Link *L)//按电话号码查询

     {…

     while(q!=NULL&&strcmp(q->data.Stelenum,p->data.Stelenum)!=0) 

     { 

        q=q->next;  //遍历单链表,字符串匹配

     }  …

}

(16)Sort_Link通讯录的排序,采用的是冒泡法,按照编号由小到大进行排序:

void Sort_Link(Link*L)  //通讯录排序,按照编号由小到大,冒泡法

{…

     if(strcmp(p->next->data.Snum,q->next->data.Snum)<0)

     if(q->next==p)

                {

                    temp1=p->next;

                   p->next=p->next->next;

                    temp1->next=q->next;

                    q->next=temp1;

                    p=temp1;

                }…        

}

(17)DeletesameSum,删除通讯录中相同编号的结点,cur指针的移动用于遍历整个链表,find用于查找与cur相同的结点,用字符串比较函数,编号不相等就继续查找,否则就删除该结点:

void DeletesameSum(Link*L)  //删除通讯录中相同编号的结点

{…

       Link *cur =L;  //用于遍历整个链表

       Link *find = NULL; //用于查找与cur相同的结点

     …

      if (strcmp(find->next->data.Snum ,cur->data.Snum)!=0)    //不相等继续查找是否有与cur相同的结点                             

 //相等则删除该结点

           tmp = find->next;                       //tmp指向与cur相等的结点               

            find->next =find->next->next;   //将结点从链表中剔除

           free(tmp);                                 //释放该结点

         …

        cur = cur->next;                              //查找完成则向后移动

     }

}

C语言源代码如下:

#include   
#include   
#include   
#include               //屏幕操作函数库  
struct node  
{  //通讯录结点数据域
    char Snum[20]; //编号  
    char Sname[10];//姓名
	char Ssex[10];  //性别
    char Saddr[20];//地址  
    char Stelenum[20];//电话号码  
};  
typedef struct node telebook;  
struct Lnode  
{  
    telebook data; //结点数据域 
    struct Lnode *next;  //结点指针域
};  
typedef struct Lnode Link;  
Link *L;//创建头节点 
void Menu();  //主菜单
void CreatLink(Link *L);//创建通讯录
void CreateLInk_from_file(Link *L);   //从文本文件中读入
void CreatLink_fromkeybord(Link* L);  //从键盘逐条输入记录
void SearchLink(Link *L);     //查询通讯录      
void Find_SNum(Link *L);     //按编号查询  
void Find_SName(Link *L);  //按姓名查询 
void Find_STel(Link *L);  //按电话号码查询 
void ChangeLink(Link *L);//修改通讯录
void DeleteLink(Link *L);//删除通讯录
void DestoryLink(Link *L);//销毁线性表 
void InsertLink(Link *L);//插入通讯录 
void Sort_Link(Link *L);  //通讯录排序,按照编号,冒泡法 
void DeletesameSum(Link *L);  //删除通讯录相同的编号的结点
void PrintLink(Link *L);//显示
void Save(Link *L);//保存
void Clear();//清屏函数

void CreateLink(Link *L)       //通讯录的建立
{
	int n,flag=1;
	printf("你想通过什么方式建立通讯录?\n"); 
	printf("1.从键盘逐条输入\t\t2.从文本文件读入\t\t3.返回\n"); 
	scanf("%d",&n);
	do{  
		if(n==1) {CreatLink_fromkeybord(L);return ;}  
		if(n==2) {CreateLInk_from_file(L);return ;}  
		if(n==3) {  
			system("cls");  
			return ;}  
		else{  
			flag=0;  
			printf("输入不正确,请重新输入:");  
			scanf("%d",&n);  
		}  
	}  while(flag==0);   
	return ;
	
}

void CreateLInk_from_file(Link *L)     //从文本文件中读入,建立通讯录
{
	Link *q,*p;
	FILE *fp;
	p=L;
    q=(Link *)malloc(sizeof(Link));  
	if((fp=fopen("F:\\telebook.txt","r"))==NULL)   
	{  
		printf("打开文件有误!");  
		exit(0);  
	}
	while(p->next!=NULL )
	{
		p=p->next;
		
	}
	while(fscanf(fp,"%s%s%s%s%s\n",q->data.Snum,q->data.Sname,q->data.Ssex,q->data.Saddr,q->data.Stelenum)!=EOF)
	{
		q->next=NULL;
		p->next=q;
		p=q;
		q=(Link *)malloc(sizeof(Link)); 
	}
	printf("从文件导入成功!");
	fclose(fp); 
}


void CreatLink_fromkeybord(Link* L)//从键盘中逐条输入,建立通讯录
{  
    Link *q,*p;  
    //FILE *fp;  
    char flag='y';  
    int i=0;  
	// L=(Link *)malloc(sizeof(Link)); //创建头节点,Link *L;
    q=L;//尾指针指向头指针 
    //if((fp=fopen("F:\\telebook.txt","ab"))==NULL)  // 追加打开一个二进制文件,并在文件末尾写数据   
	// {  
	//     printf("打开文件有误!");  
	//     exit(0);  
	// }  
    while(q->next!=NULL )
	{
		q=q->next;
		
	}
    while(flag=='y')  
    {  
        p=(Link *)malloc(sizeof(Link));  
        printf("录入信息:\n");  
        printf("编号:\n");  
        scanf("%s",p->data.Snum);  
        printf("姓名:\n");  
        scanf("%s",p->data.Sname); 
		printf("性别:\n");  
        scanf("%s",p->data.Ssex); 
        printf("地址:\n");  
        scanf("%s",p->data.Saddr);  
        printf("电话号码:\n");  
        scanf("%s",p->data.Stelenum);  
        q->next=p; 
		//	p->next=q->next;
		//	q->next=p;	
        q=p; 
        printf("继续添加?(y/n)\n");  
        scanf("%s",&flag);  
        while(flag!='y'&&flag!='n')  
        {  
            printf("输入错误,请重新输入\n");  
            scanf("%s",&flag);  
            i++;  
            if(i>2)  
                break;
			//	p=p->next;
        }  
    } 
	
    //fwrite(q,sizeof(Link),1,fp);  
    //fclose(fp);  
    q->next=NULL;  
    return ;  
}  


void SearchLink(Link *L)    //查询通讯录  
{  
	int n,flag=1;  
	Link *q;  
	q=L;  
	if(q==NULL||q->next==NULL) //链表为空  
		printf("您的操作有误,请确保您的通讯录不为空!\n");  
	else  
	{  
		PrintLink(L);  
		printf("你想通过什么方式查找?\n");  
		printf("1.编号\t\t2.姓名\t\t3.电话号码\t4.返回\n");  
		scanf("%d",&n);  
		do{ //调用函数void Find_SNum(Link *L) 按编号查询  
			//void Find_SName(Link *L)  按姓名查询 
			//void Find_STel(Link *L) 按电话号码查询 
            if(n==1) {Find_SNum(L);return;}      
			
			if(n==2) {Find_SName(L);return;}  
            if(n==3) {Find_STel(L);return;}  
            if(n==4) {  
				system("cls");  
				return ;}  
			else{  
				flag=0;  
				printf("输入不正确,请重新输入:");  
				scanf("%d",&n);  
			}  
		}  
		while(flag==0);  
	}  
}  

void Find_SNum(Link *L) //按编号查询  
{  
    Link *q,*p;  
    q=L->next;  
    printf("输入要查询的编号:\n");  
    p=(Link*)malloc(sizeof(Link));  
    scanf("%s",p->data.Snum);  
    while(q!=NULL&&strcmp(q->data.Snum,p->data.Snum)!=0)  
    {  
        q=q->next;  
    }  
    if(q==NULL)  
    {  
        printf("通讯录中没有这个编号!\n");  
    }  
    else  
    {   printf("已经找到此联系人!\n");
	printf("|  编号       |   姓名      |   性别    |     地址       |   电话号码     \n");  
	printf("|--------—— |----------— |-----------|----------------|----------------\n");
	//printf("%-10d%-20s%-20s%-20s%-20s%\n",p->data.Snum,p->data.Sname,p->data.Ssex,p->data.Stelenum,p->data.Saddr); 
	printf("%-10s%-20s%-20s%-20s%-20s%\n",q->data.Snum,q->data.Sname,q->data.Ssex,q->data.Stelenum,q->data.Saddr);  
	
    }  
}  


void Find_STel(Link *L)//按电话号码查询  
{  
    Link *q,*p;  
    q=L->next;  
    p=(Link*)malloc(sizeof(Link));  
    printf("输入要查询的电话号码:\n");  
    scanf("%s",p->data.Stelenum);  
    while(q!=NULL&&strcmp(q->data.Stelenum,p->data.Stelenum)!=0)  
    {  
        q=q->next;  
    }  
    if(q==NULL)  
    {  
        printf("通讯录中没有这个电话号码!\n");  
    }  
    else  
    {   printf("已经找到此联系人!\n");
	printf("|  编号       |   姓名      |   性别    |     地址       |   电话号码     \n");  
	printf("|--------—— |----------— |-----------|----------------|----------------\n"); 
	//printf("%-10d%-20s%-20s%-20s%-20s%\n",p->data.Snum,p->data.Sname,p->data.Ssex,p->data.Stelenum,p->data.Saddr); 
	printf("%-10s%-20s%-20s%-20s%-20s%\n",q->data.Snum,q->data.Sname,q->data.Ssex,q->data.Stelenum,q->data.Saddr);  
    }  
}  


void Find_SName(Link *L)//按姓名查询  
{  
    Link *q,*p;  
    q=L->next;  
    p=(Link*)malloc(sizeof(Link));  
    printf("输入要查询的姓名:\n");  
    scanf("%s",p->data.Sname);  
    while(q!=NULL&&strcmp(q->data.Sname,p->data.Sname)!=0)  
    {  
        q=q->next;  
    }  
    if(q==NULL)  
    {  
        printf("通讯录中没有这个姓名!\n");  
    }  
    else  
    {   printf("已经找到此联系人!\n");
	printf("|  编号       |   姓名      |   性别    |     地址       |   电话号码     \n");  
	printf("|--------—— |----------— |-----------|----------------|----------------\n"); 
	//printf("%-10d%-20s%-20s%-20s%-20s%\n",p->data.Snum,p->data.Sname,p->data.Ssex,p->data.Stelenum,p->data.Saddr); 
	printf("%-10s%-20s%-20s%-20s%-20s%\n",q->data.Snum,q->data.Sname,q->data.Ssex,q->data.Stelenum,q->data.Saddr);  
    }  
}  

void ChangeLink(Link *L)     //修改通讯录  
{  
    Link *q; 
	char s[20];
    int n;  
    q=L;  
    if(L==NULL||q->next==NULL) //链表为空  
		printf("您的操作有误,请确保您的通讯录不为空!\n");  
    else  
    {  
        PrintLink(L);  
        printf("1.要修改的编号为:\t2.要修改的名字为:\t3.要修改的电话号码为:\n");  
        printf("输入您的选择:\n");  
        scanf("%d",&n);  
        if(n==1)  
		{  
			printf("输入要修改的编号:\n");  
			scanf("%s",s);  
			while(q!=NULL)  
			{  
				if(strcmp(q->data.Snum,s)==0)  
				{  
					printf("输入修改的信息:\n");  
					printf("编号:\n");  
					scanf("%s",q->data.Snum); 
					printf("编号已经修改成功");
					break;  
				}  
				q=q->next;  
            }  
            if(q==NULL)  
                printf("您要修改的信息不存在!修改失败!\n");  
		}  
		else if(n==2)  
		{  
			printf("输入要修改的姓名:\n");  
			scanf("%s",s);  
			while(q!=NULL)  
            {  
                if(strcmp(q->data.Sname,s)==0)  
                {  
					printf("输入修改的信息:\n");  
					printf("姓名:\n");  
					scanf("%s",q->data.Sname);
					printf("姓名已经修改成功");
					break;  
				}  
				q=q->next;  
            }  
			if(q==NULL)  
                printf("您要修改的信息不存在!修改失败!\n");  
		}  
		else if(n==3)  
		{  
			printf("输入要修改的电话号码:\n");  
			scanf("%s",s);  
			while(q!=NULL)  
            {  
                if(strcmp(q->data.Stelenum,s)==0)  
                {  
					printf("输入修改的信息:\n");  
					printf("电话号码:\n");  
					scanf("%s",q->data.Stelenum);  
					printf("电话号码已经修改成功");
					break;  
				}  
				q=q->next;  
            }  
			if(q==NULL)  
                printf("您要修改的信息不存在!修改失败\n");  
		}
		
		else  
		{  
			printf("输入错误,请重新输入\n");  
			scanf("%d",&n);  
			getchar();  
		}  
    }  
}  


void DeleteLink(Link *L)//删除通讯录   1.删除整个通讯录  2.删除某个联系人  
{  
	Link *q,*p;int j=0,i,n;   
	q=L;    
	printf("1.删除整个通讯录\t\t2.删除某一个元素:\n");  
	printf("请输入您的选择:\n");  
	scanf("%d",&n);  
	if(n==1)  
	{  
        if(q==NULL||q->next==NULL) //链表为空  
			printf("您的操作有误,请确保您的通讯录不为空!\n");  
        else  
			DestoryLink(L);    //销毁线性表
	}  
	else if(n==2)  
	{  
		printf("输入要删除的位置:\n");  
		scanf("%d",&i);  
		while(jnext;  
		}  
		if(q==NULL) 
		{ 
			printf("没有找到要删除的位置!\n"); 
		}
		
		else  
		{  
			p=(Link *)malloc(sizeof(Link));  
			p=q->next;  
			if(p==NULL)  
			{
				printf("没有找到要删除的位置!\n");  
			}
			else{
				q->next=p->next;  
				free(p);  
				printf("删除元素成功!\n"); } 
		}  
	}  
	else  
	{  
        printf("输入错误,请重新输入\n");  
        scanf("%d",&n);  
	}
	return ;
}  

void DestoryLink(Link *L)//销毁线性表  ,彻底删除整个通讯录
{  
    Link *p;  
    p=L->next;  
    while(p!=NULL)  
    {  
        L->next=p->next;  
        free(p);//释放节点的内存  
        p=L->next;  
    }  
    free(p);  
}  





void InsertLink(Link *L)//通讯录的插入
{  
	Link *q,*p,*r; 
	int j=0,i,k=0; 
	q=L; 
	r=L;
	printf("输入要插入的位置:\n");  
	scanf("%d",&i); 
	while(r->next!=NULL )
	{
		r=r->next;
		k++;
		
	}  //k用来记录链表的总的结点数目
	while(jnext!=NULL)//查找第i-1个元素  
	{  
		j++;  
		q=q->next;  
	}  
	if(i<1||i>k+1)//没有找到第i-1个元素 
	{
		printf("没有找到要插入的位置!\n");  
        printf("插入失败!\n"); 
	}
	else  
	{  
		p=(Link *)malloc(sizeof(Link));  
		printf("输入要插入的信息:\n");  
		printf("编号:\n");  
		scanf("%s",p->data.Snum);  
		printf("姓名:\n");  
		scanf("%s",p->data.Sname);
		printf("性别:\n");  
		scanf("%s",p->data.Ssex);
		printf("地址:\n");  
		scanf("%s",p->data.Saddr);  
		printf("电话号码:\n");  
		scanf("%s",p->data.Stelenum);  
		p->next=q->next;  
		q->next=p;  
		printf("插入成功!\n");  
	}  
}  

void PrintLink(Link *L)//通讯录的显示 
{  
    Link *p;  
    p=L;  
    if(p==NULL||p->next==NULL) //链表为空  
		printf("您的操作有误,请确保您的通讯录不为空!\n");  
    else  
    {  
        p=L->next;  
        while(p!=NULL)  
        {  
            printf("|  编号       |   姓名      |   性别 |     地址   |   电话号码     |\n");  
            printf("|--------—— |----------— |--------|------------|----------------|\n");  
            printf("%-20s%-10s%-10s%-10s%-10s%\n",p->data.Snum,p->data.Sname,p->data.Ssex,p->data.Saddr,p->data.Stelenum);   
            p=p->next;  
        }  
		printf("通讯录显示成功!\n"); 
    }  
}  



void Sort_Link(Link *L)  //通讯录排序,按照编号由小到大,冒泡法
{
	
    Link *temp1,*temp2,*q,*p;
    for(q=L;q->next!=NULL;q=q->next)
        for(p=q->next;p->next!=NULL;p=p->next)
        {
            if(strcmp(p->next->data.Snum,q->next->data.Snum)<0)
                if(q->next==p)
                {
                    temp1=p->next;
                    p->next=p->next->next;
                    temp1->next=q->next;
                    q->next=temp1;
                    p=temp1;
                }
                else
                {
                    temp1=p->next;
                    temp2=q->next;
                    p->next=p->next->next;
                    q->next=q->next->next;
                    temp1->next=q->next;
                    q->next=temp1;
                    temp2->next=p->next;
                    p->next=temp2;
                }
        }
		
		printf("通讯录排序成功!\n");
		
		
}




void Save(Link *L)  //保存通讯录到文件 "F:\\telebook.txt "
{  
    FILE*fp;  
    Link *p;  
    p=L;
	//if((fp=fopen("F:\\telebook.txt","at"))==NULL)     // 追加打开一个二进制文件,并在文件末尾写数据
    if((fp=fopen("F:\\telebook.txt","wt"))==NULL)     // "wt"方式打开文件时,如果源文件中有内容,追加
		
    {  
        printf("cannot open this file\n");  
        exit(0);  
    }  
    if(p==NULL||p->next==NULL) //链表为空  
		printf("您的操作有误,请确保您的通讯录不为空!\n");  
	else  
	{  
		p=p->next;
		while(p!=NULL)  
		{    //printf("%s",p->data.Sname);
			//fputs("编号:",fp);
			fprintf(fp,"%s   ",p->data.Snum);
			//fputs("姓名:",fp);
			fprintf(fp,"%s   ",p->data.Sname);
			//fputs("性别:",fp);
			fprintf(fp,"%s   ",p->data.Ssex);
			//fputs("地址:",fp);
			fprintf(fp,"%s   ",p->data.Saddr);
			//fputs("电话号码:",fp);
			fprintf(fp,"%s   ",p->data.Stelenum);
			fprintf(fp,"\n");
			//fprintf(fp,"%d%s%s%s%s\n",p->data.Snum,p->data.Sname,p->data.Ssex,p->data.Saddr,p->data.Stelenum);   
			p=p->next;  
			
			
		}  
		fclose(fp);
        printf("通讯录已保存到F:\\telebook.txt!\n");  
	}  
}  

void Clear()//清屏函数  
{  
    system("pause");//输入任意键继续  
    system("cls");//清屏  
}  



void Menu()//菜单  
{  
	printf("\t      ★☆★☆★【欢迎进入通讯录管理系统】★☆★☆★\n");  
	printf("\t\t******************menu********************\n");  
	printf("\t\t┌───────────────────┐\n");  
	printf("\t\t\t ●a、    通讯信息建立\n");
	printf("\t\t\t    ◆1、从键盘逐条输入记录\n");  
	printf("\t\t\t    ◆2、从文本文件中读入\n");  
	printf("\t\t\t    ◆3、返回\n");
	printf("\t\t\t ●b、    通讯信息插入\n");  
	printf("\t\t\t ●c、    通讯信息显示\n");  
	printf("\t\t\t ●d、    通讯信息保存\n");  
	printf("\t\t\t ●e、    通讯信息删除\n");  
	printf("\t\t\t ●f、    通讯信息修改\n");  
	printf("\t\t\t ●g、    通讯信息查询\n");  
	printf("\t\t\t    ◆1、按编号查询\n");  
	printf("\t\t\t    ◆2、按姓名查询\n");  
	printf("\t\t\t    ◆3、按电话号码查询\n"); 
	printf("\t\t\t ●h、    通讯信息排序\n");
	printf("\t\t\t ●i、    删除通讯录重复\n");
	printf("\t\t\t ●j、    退出系统\n"); 
	printf("\t\t└───────────────────┘\n");  
	printf("\t\t******************************************\n");  
	printf("请输入您的选择\n");  
}  
void Quit()//退出  
{  
    exit(0);  
}  


void DeletesameSum(Link *L)  //删除通讯录中相同编号的结点
{
	
	Link *cur =L;  //用于遍历整个链表
	Link *find = NULL; //用于查找与cur相同的结点
	Link *tmp;
	cur=L->next;
    while(cur != NULL)
    {
        find = cur;
        while (find->next != NULL)                   //从cur的下一个结点开始比较
        {
            if (strcmp(find->next->data.Snum , cur->data.Snum)!=0)    //不相等继续查找是否有与cur相同的结点
				find = find->next;
            else {                                              //相等则删除该结点
                
				tmp = find->next;                       //tmp指向与cur相等的结点                
				find->next = find->next->next;   //将结点从链表中剔除
				free(tmp);                                 //释放该结点
            }
        }
        cur = cur->next;                              //查找完成则向后移动
    }
	
	
	printf("已经删除重复!\n");	
	
}



int main()  
{   
	char choice;
	L=(Link *)malloc(sizeof(Link));
	L->next=NULL;
   	while(1)  
    { 
	Menu(); 
	scanf("%s",&choice); 
	switch(choice)  
	{  
	case 'a':  
		system("cls");  
		CreateLink(L);
		Clear();  
		break;  
	case 'b':  
		system("cls");  
		InsertLink(L);  
		Clear();  
		break;  
	case 'c':  
		system("cls");  
		PrintLink(L);  
		Clear();  
		break;  
	case 'd':  
		system("cls");  
		Save(L);  
		Clear();  
		break;  
	case 'e':  
		system("cls");  
		DeleteLink(L);  
		Clear();  
		break;  
	case 'f':  
		system("cls");  
		ChangeLink(L);  
		Clear();  
		break;  
	case 'g':  
		system("cls");  
		SearchLink(L);  
		Clear();  
		break;
	case 'h':  
		system("cls");  
		Sort_Link(L);  
		Clear();  
		break;
	case 'i':  
		system("cls");  
		DeletesameSum(L); 
		Clear();  
		break;	
	case 'j':  
		system("cls");  
		Quit();  
		break;  
	default :  
		printf("您的输入有误,请重新输入:\n");  
		Clear();  
		break;  
	}  
	}
    return 0;  
}  



你可能感兴趣的:(数据结构课程设计 班级通讯录)