1.1 需求概述
此软件为通讯录管理系统软件,用于管理用户通信联系人的名片信息。其中,名片信息包括,编号、姓名、性别、生日、联系电话、QQ、联系地址及备注等;通过名片信息可以清楚、直观地体现名片信息。
1.2 功能需求
此软件具有信息浏览,增删、查询、存读档等功能。其中可以通过姓名增删联系人,通过姓名、编号或者联系电话查询联系人,可以将联系人信息存档及通过文本文件读取联系人的信息。
1.3 功能结构图
1.4 软件设计
软件的实现牵涉到数据结构的设计问题,本程序选择链表作为各种操作的基础,当然,选择数组亦可,二者在操作上各有优缺点,在删除操作时前者更加方便,查找联系人时后者更方便。完整C代码如下:
/************************************************************************************
/////////////////////////////////////////////////////////////////////////////////////
说明:本文档为C语言版本的通讯录的基本功能实现的源程序,主要的操作为:结构体
链表的基本使用、读和写文件等。
作者:24K纯学渣
日期:2020/2/3
关注微信公众号“24K纯学渣”,
有更多详细的相关文档资料,另可于此可获取作者联系方式,帮助解决调试问题。
-------------------------------------------------------------------------------------
学海无涯,让我们一起学习,共同进步!
//////////////////////////////////////////////////////////////////////////////////////
*************************************************************************************/
/*头文件包含*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<windows.h>
/*定义新的结构体数据类型*/
typedef struct _Person
{
int code; //编号
char name[10]; //姓名
char sex[10]; //性别
char birthday[25]; //生日
char telphone[15]; //联系方式
char qqtouch[20]; //QQ号
char address[50]; //地址
char remark[50]; //备注
struct _Person *next; //指向下一个节点
}Person;
/*************************************************************
函数功能:打印单个链表节点的信息
形参解释:Person *nod 头指针
函数返回值:无
*************************************************************/
void printOne(Person *nod)
{
printf("Code:%d\n",nod->code);
printf("Name:%s\n",nod->name);
printf("Gender:%s\n",nod->sex);
printf("Birthday:%s\n",nod->birthday);
printf("Tel:%s\n",nod->telphone);
printf("QQ:%s\n",nod->qqtouch);
printf("Address:%s\n",nod->address);
printf("Note:%s\n",nod->remark);
return;
}
/*************************************************************
函数功能:添加联系人
形参解释:Person *per 头指针
函数返回值:返回头指针
*************************************************************/
Person *Add_contacts(Person *per)
{
Person *node, *rear;
node = (Person *)malloc(sizeof(Person)); //分配内存
printf("Code:");
scanf("%d",&(node->code)); //输入信息
printf("Name(Must be entered):");
scanf("%s",(node->name));
printf("Birthday(For example 2000-01-01):");
scanf("%s",node->birthday);
printf("(Female or Male):");
scanf("%s",node->sex);
printf("Telephone(Must be Enter):");
scanf("%s",node->telphone);
printf("QQ:");
scanf("%s",node->qqtouch);
printf("Address:");
scanf("%s",node->address);
printf("Remark:");
scanf("%s",node->remark);
node->next = NULL;
if(per == NULL) //如果头指针为空,新添加的节点为头节点
{
per = node;
return per;
}
else //否则添在后面
{
rear = per;
while((rear ->next)!=NULL)
{
rear = rear->next;
}
rear->next = node;
return per;
}
}
/*************************************************************
函数功能:在控制台输出联系人文档中的所有信息
形参解释:Person *h头指针
函数返回值:无
*************************************************************/
void Output_allf(Person *h) //从文档中输出所有联系人的所有信息
{
if(h==NULL)
printf("Error\n");
Person *nod;
nod = h;
while(nod!=NULL)
{
printOne(nod); //打印单个节点的信息
nod = nod->next;
}
return;
}
/*************************************************************
函数功能:查找联系人
形参解释:Person *per 头指针
函数返回值:返回查找到的节点指针
*************************************************************/
Person *Find_some(Person *per)
{
char s[20],co[10];
Person *node;
printf("Input the name(/code/Tel)to continue:\n");//支持按姓名、编号或电话查找
scanf("%s",s);
node = per;
if(node == NULL) //如果头指针为空,报错!
{
printf("Error!\n");
return NULL;
}
while(node != NULL)
{
itoa(node->code,co,10); //将int型的编号转化为字符串型的数据,便于比较
if(strcmp((node->name),s)==0) //比较节点信息
{
break;
}
else if(strcmp((node->telphone),s)==0)
{
break;
}
else if(strcmp(co,s)==0)
{
break;
}
node = node->next;
}
if(node != NULL)
{
printOne(node); //打印出查找到的节点信息
}
else{
printf("No such a guy!\n");
}
return node;
}
/*************************************************************
函数功能:删除联系人
形参解释:Person *per 头指针
函数返回值:头指针
*************************************************************/
Person *Delete_contact(Person *per) //删除单个联系人信息
{
char s[20];
Person *p,*q;
Output_allf(per); //打印出所有信息
printf("Please enter the name you want to delete:\n");
scanf("%s",s);
if(per == NULL)
{
printf("Error,can't find the target!\n");
return per;
}
p = per;
q = p->next;
if(strcmp((p->name),s)==0) //若待删除的节点首节点
{
free(p); //释放内存
printf("delete done\n");
return q;
}
else
{
while(q!=NULL)
{
if(strcmp((q->name),s)==0)
{
if(q->next==NULL) //若待删除的节点为尾节点
{
free(q);
p->next = NULL;
printf("Delete done!\n");
break;
}
else //若待删除的节点处于链表的中间位置
{
p->next = q->next;
free(q);
printf("Delete done!\n");
break;
}
}
p = q;
q = q->next;
}
return per;
}
}
/*************************************************************
函数功能:修改某一联系人的信息
形参解释:Person *per 头指针
函数返回值:无
*************************************************************/
void Modify_contact(Person *per)
{
Person *node;
node = Find_some(per); //先查找到该节点
printf("Code:"); //从头输入节点信息
scanf("%d",&(node->code));
printf("Name(Must be entered):");
scanf("%s",(node->name));
printf("Birthday(For example 2000-01-01):");
scanf("%s",node->birthday);
printf("(Female or Male):");
scanf("%s",node->sex);
printf("Telephone(Must be Enter):");
scanf("%s",node->telphone);
printf("QQ:");
scanf("%s",node->qqtouch);
printf("Address:");
scanf("%s",node->address);
printf("Remark:");
scanf("%s",node->remark);
return;
}
/*************************************************************
函数功能:以.txt格式保存结构体数组中的信息
形参解释:Person *per 头指针
函数返回值:无
*************************************************************/
void Save_txt(Person *per)
{
Person *nd;
FILE *fp;
if((fp=fopen("e:\\my_friends.txt","w"))==NULL) //若不存在该文件,将会重新创建
{
printf("Cannot open the file!\n");
return;
}
if(per == NULL) //首节点必须存在
{
printf("Error!\n");
return;
}
nd = per;
while(nd != NULL) //依次打印信息
{
fprintf(fp,"Code:");
fprintf(fp,"%d",nd->code);
fprintf(fp,"\n");
fprintf(fp,"Name:");
fprintf(fp,"%s",nd->name);
fprintf(fp,"\n");
fprintf(fp,"Gender:");
fprintf(fp,"%s",nd->sex);
fprintf(fp,"\n");
fprintf(fp,"Birthday date:");
fprintf(fp,"%s",nd->birthday);
fprintf(fp,"\n");
fprintf(fp,"Tel:");
fprintf(fp,"%s",nd->telphone);
fprintf(fp,"\n");
fprintf(fp,"QQ:");
fprintf(fp,"%s",nd->qqtouch);
fprintf(fp,"\n");
fprintf(fp,"Address:");
fprintf(fp,"%s",nd->address);
fprintf(fp,"\n");
fprintf(fp,"Remark:");
fprintf(fp,"%s",nd->remark);
fprintf(fp,"\n");
fprintf(fp,"---------------------------------------------------\n");
nd = nd->next;
}
fclose(fp);
printf("Save done\n");
return;
}
/*************************************************************
函数功能:主函数
形参解释:无
函数返回值:无意义
*************************************************************/
int main()
{
Person *head = NULL;
int mode; //工作模式
printf("\tWelcome!\n");
while(1) //循环菜单
{
printf("0 ----- Output all contacts information\n");
printf("1 ----- Find contacts\n");
printf("2 ----- Add contacts\n");
printf("3 ----- Delete contacts\n");
printf("4 ----- modify contacts\n");
printf("5 ----- Exit the program\n");
printf("6 ----- Save by .txt\n");
printf("Please choose the mode:\n");
scanf("%d",&mode);
switch(mode)
{
case 2: head = Add_contacts(head);break;
case 0: Output_allf(head);break;
case 3: head = Delete_contact(head); break;
case 1: Find_some(head); break;
case 4: Modify_contact(head); break;
case 6: Save_txt(head); break;
case 5: printf("\n Thanks for your using! Good bye!\n"); break;
}
if(mode==5)
break;
printf("Press any key to continue!\n");
fflush(stdin); //清空缓存区的保存的信息
getchar();
system("cls"); //这一句可以清空控制台信息
}
return 0;
}
另外,限于文章篇幅,数组版本的实现方式不再粘贴出,如有需要,请搜素微信公众号“24K纯学渣”,回复关键词“通讯录”,可获取完整的数组实现(两种方法实现)、链表实现的C源码等。