【C语言】文件版&动态版通讯录

2024-03-01 09:06:53 浏览数 (1)

今天我们再改进一下之前的通讯录,现在可以把通讯录的信息保存在文件当中;

一、测试部分

本次保存和读取通讯录的内容都是以二进制的形式保存和读取;

对于测试部分,改动的地方在于销毁通讯录之前,需要把通讯录的内容保存到文件中,所以在销毁通讯录的函数前加了一个SaveContact函数保存通讯录;函数的具体实现看函数实现部分;

代码语言:javascript复制
		#include "C_File Dynamic Contact.h"
		
		void menu()
		{
			printf("******      1.Add         2.Del     ***********n");
			printf("******      3.Search      4.Modify  ***********n");
			printf("******      5.Show        6.Sort    ***********n");
			printf("******             0.exit           ***********n");
			printf("***********************************************n");
		}
		
		enum Option
		{
			EXIT,
			ADD,
			DEL,
			SEARCH,
			MODIFY,
			SHOW,
			SORT,
		};
		
		int main()
		{
			int input = 0;
			Contact con;
			InitContact(&con);
			do
			{
				menu();
				printf("请选择:n");
				scanf("%d", &input);
				switch (input)
				{
				case ADD:
					AddContact(&con);
					break;
				case DEL:
					DelContact(&con);
					break;
				case SEARCH:
					SearchContact(&con);
					break;
				case MODIFY:
					ModifyContact(&con);
					break;
				case SHOW:
					ShowContact(&con);
					break;
				case SORT:
					SortContact(&con);
					break;
				case EXIT:
					SaveContact(&con);
					DestoryContact(&con);
					printf("退出通讯录n");
					break;
				default:
					printf("输入错误。请重新输入:n");
					break;
				}
			} while (input);
			return 0;
		}

二、函数实现部分

现在我们在销毁通讯录前加了保存通讯录函数SaveContact,并实现了;

但是在保存之后的通讯录,我们在下一次打开时,是不是也最好可以把通讯录中的内容读取出来呢,所以我们在初始化通讯录函数中加了这么个函数-LoadContact,加载通讯录的内容,函数的具体实现如下;

代码语言:javascript复制
		#include "C_File Dynamic Contact.h"
		
		
		void CheakCapacity(Contact* pc);
		
		//加载文件的信息到通讯录
		void LoadContact(Contact* pc)
		{
			//以二进制的形式读取
			FILE* pf = fopen("Contact.txt", "rb");
			assert(pf);
		
			//读文件,创建一个临时变量储存读到的信息
			PeoInfo tmp = { 0 };
			//将读到的信息放在tmp中
			while (fread(&tmp, sizeof(PeoInfo), 1, pf))
			{
				//每次读取前判断容量是否够,不够就扩容
				CheakCapacity(pc);
				//将tmp中的信息放到内存中
				pc->data[pc->sz] = tmp;
				pc->sz  ;
			}
		
			fclose(pf);
			pf = NULL;
		}
		
		//动态版本初始化通讯录
		void InitContact(Contact* pc)
		{
			pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
			assert(pc->data);
			pc->sz = 0;
			pc->Capacity = DEFAULT_SZ;
		
			//加载通讯录信息
			LoadContact(pc);
		}
		
		//查找函数
		//加static修饰这个函数是为了这个函数只能在这个.c文件内用,出了这个文件就用不了
		static int FindByName(Contact* pc, char* name)
		{
			int i = 0;
			for (i = 0; i < pc->sz; i  )
			{
				//如果找到了就返回这个下标
				if (strcmp(pc->data[i].name, name) == 0)
				{
					return i;
				}
			}
			return -1;
		}
		
		
		//打印通讯录
		void ShowContact(Contact* pc)
		{
			int i = 0;
			//打印标题
			printf("%-10s %-4s %-5s %-12s %-30sn", "姓名", "年龄", "性别", "电话", "地址");
			for (i = 0; i < pc->sz; i  )
			{
				printf("%-10s %-4d %-5s %-12s %-30sn",
					pc->data[i].name,
					pc->data[i].age,
					pc->data[i].sex,
					pc->data[i].tele,
					pc->data[i].addr);
			}
			printf("n");
		}
		
		
		//检查Capacity的容量是否满
		void CheakCapacity(Contact* pc)
		{
			if (pc->Capacity == pc->sz)
			{
				PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->Capacity   INC_SZ) * sizeof(PeoInfo));
				assert(ptr);
		
				pc->Capacity  = INC_SZ;
				pc->data = ptr;
		
				printf("增容成功!n");
			}
		}
		
		//增加指定联系人
		void AddContact(Contact* pc)
		{
			CheakCapacity(pc);
		
			printf("请输入名字:");
			scanf("%s", pc->data[pc->sz].name);
			printf("请输入年龄:");
			scanf("%d", &(pc->data[pc->sz].age));
			printf("请输入性别:");
			scanf("%s", pc->data[pc->sz].sex);
			printf("请输入电话:");
			scanf("%s", pc->data[pc->sz].tele);
			printf("请输入地址:");
			scanf("%s", pc->data[pc->sz].addr);
		
			//添加完sz的长度  
			pc->sz  ;
			printf("添加成功n");
		}
		
		
		//删除指定联系人
		void DelContact(Contact* pc)
		{
			//通讯录为空
			if (pc->sz == 0)
			{
				printf("通讯录为空,无法删除n");
				return;
			}
			//不为空,删除
			char name[MAX_NAME];
			printf("请输入名字:");
			scanf("%s", &name);
			//一个查找函数,因为查找功能重复,所以写一个查找函数更好
			int pos = FindByName(pc, name);
			if (pos == -1)
			{
				printf("要删除的不存在n");
				return;
			}
			int i = 0;
			//将后面的数据往前挪
			for (i = pos; i < pc->sz; i  )
			{
				pc->data[i] = pc->data[i   1];
			}
			//挪完后有效数据的长度--
			pc->sz--;
			printf("删除成功n");
		}
		
		
		//在通讯录查找指定的人
		void SearchContact(Contact* pc)
		{
			printf("请输入要查找的人的名字:");
			char name[MAX_NAME];
			scanf("%s", &name);
			int pos = FindByName(pc, name);
			if (pos == -1)
			{
				printf("要查找的人不存在n");
				return;
			}
			printf("查找成功!nn");
			printf("%-10s %-4s %-5s %-12s %-30sn", "姓名", "年龄", "性别", "电话", "地址");
			//找到了打印数据
			printf("%-10s %-4d %-5s %-12s %-30sn",
				pc->data[pos].name,
				pc->data[pos].age,
				pc->data[pos].sex,
				pc->data[pos].tele,
				pc->data[pos].addr);
			printf("n");
		}
		
		
		//修改通讯录的数据
		void ModifyContact(Contact* pc)
		{
			printf("请输入需要修改的人的名字:");
			char name[MAX_NAME];
			scanf("%s", &name);
			int pos = FindByName(pc, name);
			if (pos == -1)
			{
				printf("不存在此人n");
				return;
			}
			//找到了就修改pos下标的数据
			printf("请重新输入TA的数据n");
			printf("请输入名字:");
			scanf("%s", pc->data[pos].name);
			printf("请输入年龄:");
			scanf("%d", &(pc->data[pos].age));
			printf("请输入性别:");
			scanf("%s", pc->data[pos].sex);
			printf("请输入电话:");
			scanf("%s", pc->data[pos].tele);
			printf("请输入地址:");
			scanf("%s", pc->data[pos].addr);
			printf("修改成功n");
		}
		
		
		//按照名字排序
		int cmp_by_name(void* e1, void* e2)
		{
			//强转成PeoInfo*类型
			return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
		}
		
		void SortContact(Contact* pc)
		{
			printf("按照名字排列:n");
			qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
			printf("排序成功nn");
		}
		
		
		//保存通讯录
		void SaveContact(Contact* pc)
		{
			//以二进制形式打开并写进去
			FILE* pf = fopen("Contact.txt", "wb");
			assert(pf);
		
			for (int i = 0; i < pc->sz; i  )
			{
				fwrite(pc->data   i, sizeof(PeoInfo), 1, pf);
			}
		
			fclose(pf);
			pf = NULL;
		}
		
		
		//销毁通讯录
		void DestoryContact(Contact* pc)
		{
			free(pc->data);
			pc->data = NULL;
			pc->Capacity = 0;
			pc->sz = 0;
			printf("释放内存n");
		}

三、函数声明部分

代码语言:javascript复制
		#include <stdio.h>
		#include <string.h>
		#include <stdlib.h>
		#include <assert.h>
		
		#define MAX_NAME 20
		#define MAX_SEX 5
		#define MAX_TELE 12
		#define MAX_ADDR 30
		
		//定义开始默认通讯录开辟空间的大小
		#define DEFAULT_SZ 3
		//定义每次
		#define INC_SZ 2
		
		//表示一个人的信息
		typedef struct PeoInfo
		{
			char name[MAX_NAME];
			int age;
			char sex[MAX_SEX];
			char tele[MAX_TELE];
			char addr[MAX_ADDR];
		}PeoInfo;
		
		//定义另外一个结构体,存放第一个结构体的数据和记录通讯录中有效信息的个数
		typedef struct Contact
		{
			PeoInfo* data;//data指向了存放数据的空间
			int sz;//记录通讯录中有效信息的个数
			int Capacity;//通讯录当前的容量
		}Contact;
		
		
		//初始化通讯录
		void InitContact(Contact* pc);
		
		//打印通讯录
		void ShowContact(Contact* pc);
		
		//增加指定联系人
		void AddContact(Contact* pc);
		
		//删除指定联系人
		void DelContact(Contact* pc);
		
		//在通讯录查找指定的人
		void SearchContact(Contact* pc);
		
		//修改通讯录的数据
		void ModifyContact(Contact* pc);
		
		//排序通讯录
		void SortContact(Contact* pc);
		
		//保存通讯录
		void SaveContact(Contact* pc);
		
		//销毁通讯录
		void DestoryContact(Contact* pc);

0 人点赞