意义:对于一个通信录来说,要管理联系人的信息,包括编号,姓名,性别,电话。开发其系统主要为了帮助用户提高通讯录有管理效率,节约资源,提高信息的精确度
模块:
一级菜单内容
1> 注册模块:完成用户信息的注册用于登录管理系统,将注册信息存入文件
2> 登录模块:使用输入的登录账号和密码与文件存储信息对比
3> 退出系统
二级菜单内容:
3> 创建模块create:创建链表完成对通信录的存储
4> 添加数据add:添加通信录的信息放入链表中
5> 查找信息find:可以通过姓名进行查找
6> 修改信息update:可以修改联系人信息并保存,修改联系人信息有包括了对联系人编号,姓名,性别,电话号码的分别修改,也可以同时对编号,姓名,性别,电话号码修改;
7> 删除信息delete:可根据输入的姓名进行删除
8> 插入信息insert:将给定的信息以及插入位置信息完成插入
9> 展示信息show:将通讯录的所有信息进行展示
10> 导出信息export:将通讯录信息导出到文件中
11> 按照姓名将通讯录排序
12> 返回上一级
辅助功能:
13> 初始化链表init:将链表进行初始化
14> 获取链表长度getLength:
15> 统计性别;
代码
addbookmg.h:
#ifndef ADDBOOKMG_H
#define ADDBOOKMG_H
#include<myhead.h>
//定义联系人类型
typedef struct Contact
{
//数据域
int num;
char name[20];
char sex[20];
char phnum[20];
//指针域
struct Contact *next;
}Contact, *ContactPtr;
//定义通讯录类型
typedef struct Addbook
{
//存放联系人
ContactPtr cont;
//联系人数量
int size;
}Addbook, *AddbookPtr;
//创建一级菜单
void create_menu1();
//创建二级菜单
void create_menu2();
//创建辅助功能菜单
void create_menu3();
//注册
void Register(FILE *fp);
//登录
int Login(FILE *fp);
//创建通讯录
AddbookPtr Addbook_create();
//链表初始化
void Addbook_init(AddbookPtr A);
//链表判空
int empty(AddbookPtr A);
//申请结点封装数据函数
ContactPtr apply_node(int num, char *name, char *sex, char *phnum);
//头插
int Addbook_insert_head(AddbookPtr A, int num, char *name, char *sex, char *phnum);
//定义添加通讯录信息函数
void Addbook_add(AddbookPtr A);
//按姓名查找返回位置
int search_value(AddbookPtr A, char *Name);
//通过位置查找结点
ContactPtr search_pos(AddbookPtr A, int pos);
//查找通讯录信息
int Addbook_search(AddbookPtr A);
//修改通讯录信息
int Addbook_update(AddbookPtr A);
//删除学生信息
int Addbook_delete(AddbookPtr A);
//插入通讯录信息
int Addbook_insert(AddbookPtr A);
//展示通讯录信息
int Addbook_show(AddbookPtr A);
//导出通讯录信息
void Addbook_export(FILE *fpp,AddbookPtr A);
//按姓名将通讯录信息排序
void Addbook_sort(AddbookPtr *A);
//获取链表长度
int getLength(AddbookPtr A);
//统计性别
void sex_count(AddbookPtr A);
#endif
addbookmg.c:
#include"addbookmg.h"
//定义创建一级菜单函数
void create_menu1()
{
printf("\n\t\t======通信录管理系统=======\n");
printf("\t\t1、注册\n");
printf("\t\t2、登录\n");
printf("\t\t0、退出\n");
printf("\t\t=============================\n");
}
//定义创建二级菜单函数
void create_menu2()
{
printf("\n\t\t======通信录管理系统=======\n");
printf("\t\t1、创建通讯录\n");
printf("\t\t2、添加通讯录信息\n");
printf("\t\t3、查找通讯录信息\n");
printf("\t\t4、修改通讯录信息\n");
printf("\t\t5、删除通讯录信息\n");
printf("\t\t6、插入通讯录信息\n");
printf("\t\t7、展示通讯录信息\n");
printf("\t\t8、导出通讯录信息\n");
printf("\t\t9、按姓名将通讯录信息排序\n");
printf("\t\t10、辅助功能\n");
printf("\t\t0、返回上一级\n");
printf("\t\t=============================\n");
}
//定义注册函数
void Register(FILE *fp)
{
//打开一个文件
fp = fopen("./user.txt", "a");
if(NULL == fp)
{
printf("文件打开失败!\n");
return ;
}
char username[50] = {0}, password[50] = {0};
printf("请输入要注册的用户名: ");
scanf("%s", username);
printf("请输入要注册的密码: ");
scanf("%s", password);
//注册信息存入到文件中
fprintf(fp, "%s,%s\n", username, password);
printf("注册成功!\n");
fclose(fp);
}
int Login(FILE *fp)
{
char username[50], password[50];
char file_username[50], file_password[50];
fp = fopen("user.txt", "r");
if (fp == NULL)
{
perror("文件打开失败!\n");
return 0;
}
printf("请输入用户名: ");
scanf("%s", username);
printf("请输入密码: ");
scanf("%s", password);
//判断用户名和密码是否注册
while (fscanf(fp, "%[^,],%[^\n]\n", file_username, file_password) != EOF)
{
if (strcmp(username, file_username) == 0) {
if (strcmp(password, file_password) == 0) {
printf("登录成功!\n");
fclose(fp);
return 1;
}
}
}
printf("登录失败!请检查输入是否正确。\n");
fclose(fp);
return 0;
}
//创建通讯录
AddbookPtr Addbook_create()
{
//只需要在堆区申请一个结点
AddbookPtr A = (AddbookPtr)malloc(sizeof(Addbook));
if(NULL == A)
{
printf("通讯录创建失败!\n");
return NULL;
}
printf("通讯录创建成功!\n");
//程序执行至此,说明头结点创建结束
Addbook_init(A);
return A;
}
//链表初始化
void Addbook_init(AddbookPtr A)
{
if(NULL == A)
{
printf("初始化失败!\n");
return ;
}
A->size = 0; //链表长度为0
A->cont = NULL; //防止野指针
printf("初始化成功!\n");
}
//链表判空
int empty(AddbookPtr A)
{
return A->cont == NULL;
}
//申请结点封装数据函数
ContactPtr apply_node(int num, char *name, char *sex, char *phnum)
{
//在堆区申请一个结点的大小
ContactPtr p = (ContactPtr)malloc(sizeof(Contact));
if(NULL == p)
{
printf("结点申请失败!\n");
return NULL;
}
//给结点内容赋值
p->num = num; //数据域赋值
strcpy(p->name,name);
strcpy(p->sex,sex);
strcpy(p->phnum,phnum);
p->next = NULL; //指针域
return p;
}
//头插
int Addbook_insert_head(AddbookPtr A, int num, char *name, char *sex, char *phnum)
{
//判断逻辑
if(NULL==A)
{
printf("通讯录不存在!\n");
return -1;
}
//申请结点封装数据
ContactPtr p = apply_node(num,name,sex,phnum);
if(NULL==p)
{
return -1;
}
//头插逻辑
p->next = A->cont;
A->cont = p;
//通讯录大小变化
A->size++;
return 0;
}
//定义添加通讯录信息函数
void Addbook_add(AddbookPtr A)
{
if(NULL == A)
{
printf("添加失败!\n");
return ;
}
int len = 0;
printf("请输入添加个数:");
scanf("%d",&len);
getchar();
int num = 0;
char name[20] = {0};
char sex[20] = {0};
char phnum[20] = {0};
for(int i=0;i<len;i++)
{
printf("请输入第%d个联系人的编号:",i+1);
scanf("%d",&num);
getchar();
printf("请输入第%d个联系人的姓名:",i+1);
scanf("%s",name);
getchar();
printf("请输入第%d个联系人的性别:",i+1);
scanf("%s",sex);
getchar();
printf("请输入第%d个联系人的电话号码:",i+1);
scanf("%s",phnum);
getchar();
Addbook_insert_head(A,num,name,sex,phnum);
putchar(10);
}
printf("添加成功!\n");
}
//展示通讯录信息
int Addbook_show(AddbookPtr A)
{
//判断逻辑
if(NULL==A || empty(A))
{
printf("展示失败!\n");
return -1;
}
printf("通讯录信息如下:\n");
//遍历逻辑
ContactPtr q = A->cont; //定义遍历指针从第一个结点出发
printf("\t编号\t姓名\t性别\t电话号码\n");
while(q != NULL)
{
//输出数据域
printf("\t%d\t%s\t%s\t%s\n",\
q->num, q->name, q->sex, q->phnum);
q = q->next; //指针向后偏移一个
}
}
//按姓名查找返回位置
int search_value(AddbookPtr A, char *Name)
{
//判断逻辑
if(NULL==A || empty(A))
{
printf("查找失败!\n");
return -1;
}
//查找逻辑
//定义遍历指针从第一个结点出发
ContactPtr q = A->cont;
for(int index=0; index<A->size; index++)
{
//判断当前结点的值是否为要找的数据
if(strcmp(q->name,Name)==0)
{
return index;
}
q = q->next; //继续向后遍历
}
//程序执行至此,表示没找到
printf("没找到该联系人!\n");
return -1;
}
//通过位置查找结点
ContactPtr search_pos(AddbookPtr A, int pos)
{
//判断逻辑
if(NULL==A || empty(A) || pos<0 || pos>A->size)
{
printf("查找失败!\n");
return NULL;
}
//查找逻辑
//定义遍历指针从头结点出发
ContactPtr q = A->cont;
for(int i=0; i<pos; i++)
{
q = q->next;
}
return q; //将找到的结点地址返回
}
//查找通讯录信息
int Addbook_search(AddbookPtr A)
{
//判断逻辑
if(A==NULL||empty(A))
{
printf("查询失败!\n");
return -1;
}
char name[20] = {0};
printf("请输入要查询的联系人姓名:");
scanf("%s",name);
int pos = search_value(A,name);
if(pos == -1)
{
return -1;
}
ContactPtr p = search_pos(A,pos);
printf("你查询的联系人信息如下\n");
printf("\t编号\t姓名\t性别\t电话号码\n");
printf("\t%d\t%s\t%s\t%s\n",\
p->num,p->name, p->sex, p->phnum);
return 0;
}
//修改通讯录信息
int Addbook_update(AddbookPtr A)
{
//判断逻辑
if(NULL==A || empty(A))
{
printf("修改失败!\n");
return -1;
}
char name[20] = {0};
int num = 0, f = 0;
char newname[20] = {0}, sex[20] = {0}, phnum[20] = {0};
printf("请输入要修改的联系人姓名:");
scanf("%s",name);
putchar(10);
//按位置查找逻辑
int pos = search_value(A,name);
if(pos == -1)
{
return -1;
}
ContactPtr p = search_pos(A, pos);
//赋值
num = p->num;
strcpy(newname,p->name);
strcpy(sex,p->sex);
strcpy(phnum,p->phnum);
printf("请选择修改方式:1、修改编号\t2、修改姓名\t3、修改性别\t4、修改电话号码\t5、全部修改\n");
scanf("%d", &f);
getchar();
if(f==1)
{
printf("请输入修改后的联系人编号:");
scanf("%d",&num);
}
else if(f==2)
{
printf("请输入修改后的联系人姓名:");
scanf("%s",newname);
}
else if(f==3)
{
printf("请输入修改后的联系人性别:");
scanf("%s", sex);
}
else if(f==4)
{
printf("请输入修改后的联系人电话号码:");
scanf("%s",phnum);
}
else if(f==5)
{
printf("请输入修改后的联系人编号:");
scanf("%d",&num);
printf("请输入修改后的联系人姓名:");
scanf("%s",newname);
printf("请输入修改后的联系人性别:");
scanf("%s", sex);
printf("请输入修改后的联系人电话号码:");
scanf("%s",phnum);
}
else
{
printf("输入错误!");
return 0;
}
//修改逻辑
p->num = num;
strcpy(p->name,newname);
strcpy(p->sex,sex);
strcpy(p->phnum,phnum);
printf("修改成功!\n");
return 0;
}
//删除学生信息
int Addbook_delete(AddbookPtr A)
{
//判断逻辑
if(A == NULL || A->cont == NULL)
{
printf("删除失败!\n");
return -1;
}
char Name[20] = {0};
printf("请输入要删除的联系人姓名:");
scanf("%s",Name);
//找前驱结点
int pos = search_value(A,Name);
if(pos==0)
{
//删除逻辑
ContactPtr q = A->cont;
A->cont = q->next;
free(q);
q = NULL;
}
if(pos!=0)
{
ContactPtr q = search_pos(A,pos-1);
//删除逻辑
ContactPtr p = q->next; //标记
q->next = p->next; //p->next 孤立
free(p); //释放
p = NULL;
}
//通讯录大小变化
A->size--;
printf("删除成功!\n");
return 0;
}
//插入通讯录信息
int Addbook_insert(AddbookPtr A)
{
//判断逻辑
if(NULL==A)
{
printf("插入失败!\n");
return -1;
}
int res = 0;
printf("请选择你要插入的位置:");
scanf("%d",&res);
getchar();
//判断位置是否存在
if(res < 0 || res > A->size+1)
{
printf("该位置不存在!\n");
return 0;
}
int num = 0;
char name[20] = {0}, sex[20] = {0}, phnum[20] = {0};
printf("请输入插入的联系人编号:");
scanf("%d",&num);
printf("请输入插入的联系人姓名:");
scanf("%s",name);
printf("请输入插入的联系人性别:");
scanf("%s", sex);
printf("请输入插入的联系人电话号码:");
scanf("%s",phnum);
//封装结点
ContactPtr p = apply_node(num,name,sex,phnum);
//查找插入位置的前驱
ContactPtr q = search_pos(A,res-2);
//插入位置
p->next = q->next;
q->next = p;
//通讯录大小变化
A->size++;
printf("插入成功!\n");
return 0;
}
//导出通讯录信息
void Addbook_export(FILE *fpp,AddbookPtr A)
{
//打开一个文件
fpp = fopen("./AddressBook.txt", "a");
if(NULL == fpp)
{
printf("文件打开失败!\n");
return ;
}
fprintf(fpp, "编号\t姓名\t性别\t电话号码\n");
ContactPtr p = A->cont;
for(int i=0;p!=NULL;i++)
{
/* int num = 0;
char name[20] = {0}, sex[20] = {0}, phnum[20] = {0};
num = p->num;
strcpy(name,p->name);
strcpy(sex,p->sex);
strcpy(phnum,p->phnum);
*/
//通讯录信息存入到文件中
fprintf(fpp, "%d\t%s\t%s\t%s\n",\
p->num, p->name, p->sex, p->phnum);
p = p->next;
}
printf("导出成功!\n");
fclose(fpp);
}
//按姓名将通讯录信息排序
void Addbook_sort(AddbookPtr *A)
{
if(*A == NULL || (*A)->cont == NULL)
{
printf("通讯录不存在或无数据!\n");
return ;
}
ContactPtr sorted = NULL;
ContactPtr current = (*A)->cont;
while (current != NULL)
{
ContactPtr next = current->next;
ContactPtr *pre = &sorted;
// 找到合适的插入位置
while (*pre != NULL && strcmp((*pre)->name,current->name)>0)
{
pre = &(*pre)->next;
}
// 插入当前节点
current->next = *pre;
*pre = current;
current = next;
}
(*A)->cont = sorted;
printf("排序成功!\n");
}
//获取链表长度
int getLength(AddbookPtr A)
{
//判断逻辑
if(NULL == A)
{
printf("通讯录不存在!\n");
return -1;
}
return A->size;
}
//统计性别
void sex_count(AddbookPtr A)
{
//判断逻辑
if(NULL == A)
{
printf("通讯录不存在!\n");
return ;
}
ContactPtr p = A->cont;
int nan = 0, nv = 0;
//统计男女数量
while(p != NULL)
{
if((strcmp(p->sex,"男")==0) || (strcmp(p->sex,"男性")==0))
{
nan++;
}
if((strcmp(p->sex,"女")==0) || (strcmp(p->sex,"女性")==0))
{
nv++;
}
p = p->next;
}
printf("该通讯录中有%d名男性,%d名女性\n", nan, nv);
}
//创建辅助功能菜单
void create_menu3()
{
printf("\n\t\t======通信录管理系统=======\n");
printf("\t\t1、初始化通讯录\n");
printf("\t\t2、获取通讯录长度\n");
printf("\t\t3、统计性别\n");
printf("\t\t0、返回上一级\n");
printf("\t\t=============================\n");
}
main.c:
#include"addbookmg.h"
int main(int argc, const char *argv[])
{
//菜单
int menu1 = 0, menu2 = 0, menu3 = 0;
AddbookPtr A = NULL;
//定义文件类型的结构体以便于接受打开的文件地址
FILE * fp = NULL;
FILE * fpp = NULL;
One:
//循环
while(1)
{
//创建一级菜单
create_menu1();
printf("请输入操作码:");
scanf("%d",&menu1);
getchar();
switch(menu1)
{
case 1:
{
Register(fp);
}
break;
case 2:
{
int a = Login(fp);
Two:
while(a)
{
//创建二级菜单
create_menu2();
printf("请输入操作码:");
scanf("%d",&menu2);
getchar();
switch(menu2)
{
case 1:
{
//创建通讯录
A = Addbook_create();
}
break;
case 2:
{
//添加通讯录信息
Addbook_add(A);
}
break;
case 3:
{
//查找通讯录信息
Addbook_search(A);
}
break;
case 4:
{
//修改通讯录信息
Addbook_update(A);
}
break;
case 5:
{
//删除通讯录信息
Addbook_delete(A);
}
break;
case 6:
{
//插入通讯录信息
Addbook_insert(A);
}
break;
case 7:
{
//展示通讯录信息
Addbook_show(A);
}
break;
case 8:
{
//导出通讯录信息
Addbook_export(fpp,A);
}
break;
case 9:
{
//按姓名将通讯录信息排序
Addbook_sort(&A);
}
break;
case 10:
{
while(1)
{
//创建辅助功能菜单
create_menu3();
printf("请输入操作码:");
scanf("%d",&menu3);
getchar();
switch(menu3)
{
case 1:
{
//初始化通讯录
Addbook_init(A);
}
break;
case 2:
{
//获取通讯录长度
int len = getLength(A);
printf("通讯录长度为%d", len);
}
break;
case 3:
{
//统计性别
sex_count(A);
}
break;
case 0:goto Two;
default:printf("不存在该操作码!\n");
}
}
}
break;
case 0:goto One;
default:printf("不存在该操作码!\n");
}
}
}
break;
case 0:goto End;
default:printf("不存在该操作码!\n");
}
}
End:
return 0;
}
运行结果:
思维导图: