项目:基于链表的通信录管理

意义:对于一个通信录来说,要管理联系人的信息,包括编号,姓名,性别,电话。开发其系统主要为了帮助用户提高通讯录有管理效率,节约资源,提高信息的精确度

模块:
一级菜单内容
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;
}

运行结果:

思维导图:

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值