大一c语言程序设计——电话簿管理

题目要求

电话簿管理
设计一个学生通信录,学生通迅录数据信息构成内容可自行设计(如:姓名、家庭地址、邮政编码、电话号码等等)。该学生通信录电管理程序具有加入、删除、显示和查询等功能。

  1. 能建立、修改和增删学生通讯录;
  2. 具有群组工能,可以增加群组和记录;
  3. 删除可以删除一条、一个群组、全部记录;
  4. 查询包含模糊查询;
  5. 显示可以以页面和列表方式显示;
  6. 有自动排序的功能;
  7. 界面友好,易于操作,采用文件存储数据。

代码实现

头文件 fun.h

//头文件的包含
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//宏定义

//学生信息结构的定义
typedef struct student
{
	int num;//以学号排序
	char logo[20];//群组分类功能——标签
	char name[20];
	char address[50];
	int PostalCode;
	char PhoneCode[12];
	struct student* next;
}STU;

//函数的声明

//创建学生信息链表
STU* create();

//添加学生的信息
STU* append(STU* head, STU* new);

//修改学生的信息
STU* modify(STU* head, char name[]);

//删除一条、一个群组、全部记录
STU* delete(STU* head, int choice);

//对数据进行保存
void save(FILE* fp, STU* head);

//查找
void find(STU* head, int choice);

//显示通讯录信息
void output(STU* head);

fun.c

#define _CRT_SECURE_NO_WARNINGS
#include"fun.h"

STU* create()
{
	STU* head = NULL;//头指针——NULL表示表为空
	STU* p;//用来创建结点的
	while (1)
	{
		//对创建一个学生的结点动态分配空间
		if ((p = (STU*)malloc(sizeof(STU))) == NULL)
		{
			printf("No space available.Create failed.\n");
			exit(1);
		}
		printf("请输入一位学生的学号(输入0退出):");
		scanf("%d", &p->num);
		if (p->num == 0)
		{
			break;
		}
		printf("该学生分组为:");
		scanf("%s", p->logo);
		printf("姓名为:");
		scanf("%s", p->name);
		printf("家庭地址为:");
		scanf("%s", p->address);
		printf("邮政编号为:");
		scanf("%d", &p->PostalCode);
		printf("电话号码为:");
		scanf("%s", p->PhoneCode);
		head = append(head, p);   //创建一个学生的结点后,以学号为标准进行插入,从而实现排序功能
	}
	return head;
}
STU* append(STU* head, STU* new)
{
	STU* p = head, *q=NULL;
	if (head == NULL)//原表为空
	{
		new->next = NULL;
		return new;
	}
	else
	{
		//查找关键结点
		while (p->num < new->num)//学号从小到大排序
		{
			q = p;
			p = p->next;
			if (p == NULL)
			{
				break;
			}
		}
		//把新结点插到表头前
		if (p == head)
		{
			new->next = head;
			return new;
		}
		//把新结点插入表尾
		else if (p == NULL)
		{
			q->next = new;
			new->next = NULL;
		}
		//从中间插入新结点
		else
		{
			q->next = new;
			new->next = p;
		}
	}
	return head;
}

//修改学生的信息
STU* modify(STU* head, char name[])
{
	STU* p = head;
	while (strcmp(p->name, name) != 0)//寻找该学生
	{
		p = p->next;
		if (p == NULL)
			break;
	}
	if (p == NULL)
	{
		printf("要修改的学生不存在!\n");
	}
	else
	{
		while (1)
		{
			int choice;
			printf("要修改信息:1.组别 2.学号 3.电话 4.邮政编号 5.家庭地址\n");
			printf("请选择要修改的操作,输入0退出修改:\n");
			scanf("%d", &choice);
			switch (choice)
			{
			case 1:
				printf("修改成:");
				scanf("%s", p->logo);
				break;
			case 2:
				printf("修改成:");
				scanf("%d", &p->num);
				break;
			case 3:
				printf("修改成:");
				scanf("%s", p->PhoneCode);
				break;
			case 4:
				printf("修改成:");
				scanf("%d", &p->PostalCode);
				break;
			case 5:
				printf("修改成:");
				scanf("%s", p->address);
				break;
			case 0:
				return head;
			default:
				printf("输入数据非法,请重新输入\n");
			}
		}
	}
}

//删除一条、一个群组、全部记录
STU* delete(STU* head, int choice)
{
	STU* p = head, * q = NULL;
	if (choice == 1)
	{
		char name[20];
		printf("请输入要删除学生的姓名:");
		scanf("%s", name);
		while (strcmp(p->name, name) != 0)//寻找该学生
		{
			q = p;
			p = p->next;
			if (p == NULL)
				break;
		}
		if (p == NULL)
		{
			printf("要删除的学生不存在!\n");
		}
		//要删除的学生是表头
		else if (p == head)
		{
			head = head->next;
			free(p);
			p = NULL;
		}
		else
		{
			q->next = p->next;
			free(p);
			p = NULL;
		}
	}
	else if (choice == 2)
	{
		p = head->next;
		char logo[20];
		printf("请输入要删除的群组名:");
		scanf("%s", logo);
		while (p != NULL)//遍历除了表头的整个通讯录
		{
			//找到组别为要删除的群组名就执行
			if (strcmp(p->logo, logo) == 0)
			{
				q = p;
				p = p->next;
				free(q);
				q = p;
				p = p->next;
			}
			else
			{
				q = p;
				p = p->next;
			}
		}
		if (strcmp(head->logo, logo) == 0)//对表头进行判断
		{
			free(head);
			head = NULL;
		}
	}
	else if (choice == 3)
	{
		while (head != NULL)
		{
			q = head->next;
			free(head);
			head = q;
		}
		head = NULL;
	}
	else
	{
		printf("输入数据错误,无法实现删除操作\n");
	}
	return head;
}

//数据保存
void save(FILE* fp, STU* head)
{
	//以写的方式打开文件
	if ((fp = fopen("student_contract.txt", "w")) == NULL)
	{
		printf("打开文件错误!\n");
		return;
	}
	//对数据保存
	STU* p = head;
	fprintf(fp,"组别\t学号\t姓名\t电话号码\t\t邮政编码\t家庭住址\n");
	while (p != NULL)
	{
		fprintf(fp,"%s\t%d\t%s\t%s\t%d\t\t%s\n", p->logo, p->num, p->name, p->PhoneCode, p->PostalCode, p->address);
		p = p->next;
	}
	fclose(fp);
}

//查找

//模糊查找子函数实现
int is_have_same_key(char input[],char name[])
{
	char* p = input, * q = name;
	while (*p != '\0')//从输入的名字的第一个汉字开始遍历整个名字
	{
		q = name;//确保每次遍历名字的指针从头开始
		while (*q != '\0')
		{
			if (*p == *q)
			{
				return 1;//但凡找到有和输入名字相同的关键字,返回值1,查找成功
			}
			q++;
		}
		p++;
	}
	return 0;//没有找到,返回值0,查找失败
}

void find(STU* head, int choice)
{
	if (choice == 1)//精准查找
	{
		STU* p = head;
		char name[20];
		printf("请输入查找的学生的确切名字:");
		scanf("%s", name);
		while (p != NULL)
		{
			if ((strcmp(p->name, name)) == 0)
			{
				printf("找到了,详细信息如下\n");
				printf("\n组别:%s\n", p->logo);
				printf("学号:%d\n", p->num);
				printf("姓名:%s\n", p->name);
				printf("电话号码:%s\n", p->PhoneCode);
				printf("邮政编码:%d\n", p->PostalCode);
				printf("家庭住址:%s\n", p->address);
				break;
			}
			p = p->next;
		}
		if (p == NULL)
		{
			printf("很抱歉,该学生的信息不存在\n");
			return;
		}
	}
	else if (choice == 2)//模糊查找
	{
		STU* p = head, * q = NULL;
		char name[20];
		int i = 0;
		printf("请输入所知名字信息:");
		scanf("%s", name);
		//遍历整个链表
		while (p != NULL)
		{
			if (is_have_same_key(name, p->name))
			{
				printf("\n(模糊查询)学生%d信息\n", ++i);
				printf("\n组别:%s\n", p->logo);
				printf("学号:%d\n", p->num);
				printf("姓名:%s\n", p->name);
				printf("电话号码:%s\n", p->PhoneCode);
				printf("邮政编码:%d\n", p->PostalCode);
				printf("家庭住址:%s\n", p->address);
			}
			p = p->next;
		}
		if (i == 0)
		{
			printf("很抱歉,该学生的信息不存在\n");
		}
	}
	else
		printf("输入数据错误,该操作无法实行\n");
}


//显示通讯录信息
void output(STU* head)
{
	if (head == NULL)
	{
		printf("没有信息,请创建并输入信息吧!\n");
		return;
	}
	int choice;
	STU* p = head;
	char logo[20];//用来输出特定的组别的
	int juge = 0;//用来判断特定组别是否信息
	while (1)
	{
		printf("1.以列表的形式显示。2.以页面的形式显示。3.显示特定群组。0.退出显示。\n");
		printf("请选择:");
		scanf("%d", &choice);
		p = head;
		switch (choice)
		{
		case 1:
			printf("组别\t学号\t姓名\t电话号码\t邮政编码\t家庭住址\n");
			while (p != NULL)
			{
				printf("%s\t%d\t%s\t%s\t%d\t\t%s\n", p->logo, p->num, p->name, p->PhoneCode, p->PostalCode, p->address);
				p = p->next;
			}
			break;
		case 2:
			while (p != NULL)
			{
				printf("\n组别:%s\n", p->logo);
				printf("学号:%d\n", p->num);
				printf("姓名:%s\n", p->name);
				printf("电话号码:%s\n", p->PhoneCode);
				printf("邮政编码:%d\n", p->PostalCode);
				printf("家庭住址:%s\n", p->address);
				p = p->next;
			}
			break;
		case 3:
			printf("请输入想要输入的组别:");
			scanf("%s", logo);
			printf("组别\t学号\t姓名\t电话号码\t\t邮政编码\t家庭住址\n");
			while (p != NULL)
			{
				if ((strcmp(logo, p->logo)) == 0)
				{
					printf("%s\t%d\t%s\t%s\t%d\t%s\n", p->logo, p->num, p->name, p->PhoneCode, p->PostalCode, p->address);
					juge = 1;
				}
				p = p->next;
			}
			if (juge == 0)
			{
				printf("不存在该组别\n");
			}
			break;
		case 0:
			return;
		default:
			printf("输入数据违法,请重新输入。\n");
			break;
		}
	}
}

text.c

#define _CRT_SECURE_NO_WARNINGS 
#include "fun.h"

void menu()
{
	printf("******************************\n");
	printf("*****    电话簿管理系统    ***\n");
	printf("************0.退出************\n");
	printf("************1.创建************\n");
	printf("************2.增加************\n");
	printf("************3.修改************\n");
	printf("************4.删除************\n");
	printf("************5.保存************\n");
	printf("************6.查看************\n");
	printf("************7.找人************\n");
	printf("*****    电话簿管理系统    ***\n");
	printf("******************************\n");
}
int main()
{
	STU* head = NULL,*p;
	char name[20];
	FILE* fp=NULL;
	int choice;//操作选择
	while (1)
	{
		menu();
		printf("请输入要进行的操作(0~5):");
		scanf("%d", &choice);
		switch (choice)
		{
		case 0:
			goto end;
			break;
		case 1:
			head=create();
			break;
		case 2://添加学生信息——建立通讯录
			//对创建一个学生的结点动态分配空间
			if ((p = (STU*)malloc(sizeof(STU))) == NULL)
			{
				printf("No space available.Create failed.Please select again.\n");
			}
			else
			{
				printf("请输入新学生的学号:");
				scanf("%d", &p->num);
				printf("该学生分组为:");
				scanf("%s", p->logo);
				printf("姓名为:");
				scanf("%s", p->name);
				printf("家庭地址为:");
				scanf("%s", p->address);
				printf("邮政编号为:");
				scanf("%d", &p->PostalCode);
				printf("电话号码为:");
				scanf("%s", p->PhoneCode);
				head = append(head, p);
			}
			break;
		case 3://修改学生中的信息
			printf("请输入要修改信息学生的名字:");
			scanf("%s", name);
			head=modify(head,name);
			break;
		case 4://删除一条、一个群组、全部记录
			printf("1.删除一条记录 2.删除一个群组记录 3.删除全部记录\n");
			printf("请选择删除操作:");
			scanf("%d", &choice);
			head=delete(head,choice);
			break;
		case 5://对数据进行保存
			save(fp,head);
			break;
		case 6://多种形式的显示
			output(head);
			break;
		case 7://查找——精准查找和模糊查找
			printf("1.精准查找 2.模糊查找\n");
			printf("请选择:");
			scanf("%d", &choice);
			find(head,choice);
			break;
		default:
			printf("输入数据非法,请重新输入\n");
			break;
		}
	}
end:
	//释放动态内存空间
	{
		STU* q=NULL;
		while (head != NULL)
		{
			q = head->next;
			free(head);
			head = q;
		}
		head = NULL;
	}
	return 0;
}