通讯录——文件读写版本

通讯录最终版本——文件读写

  前面在暴躁小猿给大家分享了通讯录的静态版本和动态版本,但是这两个版本都不能实现文件的读写,每次运行程序都不能保存和读取数据,这样的通讯录是不完善的,根本没有办法去使用,所以为了满足需求,我们需要用对文件可以读写的通讯录,出于这个原因,通讯录最终版本就来了


在这里插入图片描述


一、头文件

代码如下(示例):

#define  _CRT_SECURE_NO_WARNINGS 1
#define max 3
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include <windows.h>

//初始化通讯录
void inicontact(struct contact* pc);
//添加联系人
void addpeople(struct contact* pc);
//删除联系人
void delpeople(struct contact* pc);
//展示联系人
void showpeople(struct contact* pc);
//查找联系人
void searchpeople(struct contact* pc);
//修改联系人
void revisepeople(struct contact* pc);
//联系人排序
void sortpeople(struct contact* pc);
//清除联系人
void deadpeople(struct contact* pc);
//保存联系人到文件
void savecontact(struct contact* pc);
//加载联系人从文件到内存
void Loadcontact(struct contact* pc);
//判断是否通讯录已满
void check(struct contact* pc);
//比较函数
int cmp(struct contact* pc);

struct PeoInfo
{
    
    
	char name[10];
	char sex[5];
	int age;
	char tel[15];
	char address[20];
};
struct contact
{
    
    
	struct PeoInfo* date;
	int sz;
	int max;
};



  我们这个版本的通讯录是在动态版本通讯录的基础上实现的,所以在头文件中我们就只是多了保存联系人信息到文件和读取联系人信息这个两个函数的声明,其余的代码和动态版本通讯录大同小异,如果有不解的地方可以看小猿之前动态版本通讯录的博客,里面有详细讲解。

二、功能实现模块

#define  _CRT_SECURE_NO_WARNINGS 1
#include "FILE.h"
void menu()
{
    
    
	printf("------------------------------------\n");
	printf("--------请选择你要实现的功能--------\n");
	printf("--------1.添加联系人信息------------\n");
	printf("--------2.删除指定联系人信息--------\n");
	printf("--------3.查找指定联系人信息--------\n");
	printf("--------4.修改指定联系人信息--------\n");
	printf("--------5.显示所有联系人信息--------\n");
	printf("--------6.以名字排序所有联系人------\n");
	printf("--------0.      退出         ------\n");
}
void check(struct contact* pc)
{
    
    
	if ((pc->sz) >= (pc->max))
	{
    
    
		pc = (struct PeoInfo*)realloc(pc->date, (pc->max + 2) * sizeof(struct PeoInfo));
		printf("扩容成功\n");
		pc->max += 2;
	}
}
void Loadcontact(struct contact* pc)
{
    
    
	FILE* pf = fopen("contacts.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	struct PeoInfo tmp = {
    
     0 };
	while (fread(&tmp, sizeof(struct PeoInfo), 1, pf))
	{
    
    
		check(pc);
		pc->date[pc->sz] = tmp;
		pc->sz++;
	}
	fclose(pf);
	pf = NULL;
}
	void inicontact(struct contact* pc)
	{
    
    
		pc->sz = 0;
		pc->max = 3;
		pc->date = (struct PeoInfo*)calloc(3, sizeof(struct PeoInfo));
		 Loadcontact(pc);
	}
	

	void addpeople(struct contact* pc)
	{
    
    
		 check(pc);
		printf("请输入姓名\n");
		scanf("%s", &(pc->date[pc->sz].name));
		printf("请输入性别\n");
		scanf("%s", &(pc->date[pc->sz].sex));
		printf("请输入年龄\n");
		scanf("%d", &(pc->date[pc->sz].age));
		printf("请输入电话\n");
		scanf("%s", &(pc->date[pc->sz].tel));
		printf("请输入住址\n");
		scanf("%s", &(pc->date[pc->sz].address));
		printf("添加联系人完毕\n");
		pc->sz++;
	}
	void delpeople(struct contact* pc)
	{
    
    
		char name1[10];
		int input1;
		printf("请输入你要删除的联系人\n");
		scanf("%s", &name1);
		int i;
		for (i = 0; i < (pc->sz); i++)
		{
    
    
			if (strcmp(pc->date[i].name, name1) == 0)
			{
    
    
				printf("查到到联系人%s是否确认删除\n", name1);
				scanf("%d", &input1);
				if (input1 == 1)
				{
    
    
					for (int j = i; j < ((pc->sz) - 1); j++)
					{
    
    
						(pc->date[j]) = (pc->date[j + 1]);
						pc->sz--;
					}
					printf("删除成功\n");
				}
				else
				{
    
    
					printf("成功取消\n");
				}
			}
		}
		if (i >= (pc->sz))
		{
    
    
			printf("联系人%s不存在\n", name1);
		}
	}
	void searchpeople(struct contact* pc)
	{
    
    
		char name1[10];
		printf("请输入你要查找的联系人\n");
		scanf("%s", &name1);
		int i;
		for (i = 0; i < (pc->sz); i++)
		{
    
    
			if (strcmp(pc->date[i].name, name1) == 0)
			{
    
    
				printf("%-10s\t %-15s\t %-3s\t %-15s\t %-20s\t\n",
					"name", "sex", "age", "tel", "address");
				printf("%-10s\t %-15s\t %-3d\t %-15s\t %-20s\t\n",
					pc->date[i].name,
					pc->date[i].sex,
					pc->date[i].age,
					pc->date[i].tel,
					pc->date[i].address);
			}
		}
		if (i > pc->sz)
		{
    
    
			printf("不存在此联系人%s\n", name1);
		}
	}

	void revisepeople(struct contact* pc)
	{
    
    
		char name1[10];
		printf("请输入你要修改的联系人\n");
		scanf("%s", &name1);
		int i;
		for (i = 0; i < (pc->sz); i++)
		{
    
    
			if (strcmp(pc->date[i].name, name1) == 0)
			{
    
    
				printf("请输入姓名\n");
				scanf("%s", &(pc->date[i].name));
				printf("请输入性别\n");
				scanf("%s", &(pc->date[i].sex));
				printf("请输入年龄\n");
				scanf("%d", &(pc->date[i].age));
				printf("请输入电话\n");
				scanf("%s", &(pc->date[i].tel));
				printf("请输入住址\n");
				scanf("%s", &(pc->date[i].address));
				printf("修改联系人完毕\n");
			}
		}
		if (i > pc->sz)
		{
    
    
			printf("不存在此联系人%s\n", name1);
		}
	}

	void showpeople(struct contact* pc)
	{
    
    
		int i;
		printf("%-10s\t %-15s\t %-3s\t %-15s\t %-20s\t\n",
			"name", "sex", "age", "tel", "address");
		for (i = 0; i < (pc->sz); i++)
		{
    
    
			printf("%-10s\t %-15s\t %-3d\t %-15s\t %-20s\t\n",
				pc->date[i].name,
				pc->date[i].sex,
				pc->date[i].age,
				pc->date[i].tel,
				pc->date[i].address);
		}

	}
	int cmp(void* e1, void* e2)
	{
    
    
		return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
	}

	void sortpeople(struct contact* pc)
	{
    
    
		qsort(pc, pc->sz, sizeof(struct PeoInfo), cmp);
	}
	void savecontact(struct contact* pc)
	{
    
    
		FILE* pf = fopen("contacts.txt", "w");
		if (pf == NULL)
		{
    
    
			perror("fopen");
			return;
		}
		int i = 0;
		for (i = 0; i < pc->sz; i++)
		{
    
    
			fwrite(pc->date + i, sizeof(struct PeoInfo), 1, pf);
		}

		fclose(pf);
		pf = NULL;
	}

	void deadpeople(struct contact* pc)
	{
    
    
		free(pc->date);
		pc->date = NULL;
		pc->max = 0;
		pc->sz = 0;
	}


  这是我们功能实现总体的代码,也是在动态通讯录上改造的,我们多了两个功能就是保存联系人信息到文件和读取文件中联系人的信息到内存,我们用两个独立的函数来实现这两个功能。

1.保存联系人到文件

代码如下(示例):

	void savecontact(struct contact* pc)
	{
    
    
		FILE* pf = fopen("contacts.txt", "w");
		if (pf == NULL)
		{
    
    
			perror("fopen");
			return;
		}
		int i = 0;
		for (i = 0; i < pc->sz; i++)
		{
    
    
			fwrite(pc->date + i, sizeof(struct PeoInfo), 1, pf);
		}

		fclose(pf);
		pf = NULL;
	}

  我们先对一个contacts.txt文件进行只写操作,如果我们之前没有这个文件系统就会自动创建一个文件,然后我们需要判断一下fopen函数返回的FILE结构的指针是否为NULL,如果为NULL我们就用perror函数显示fopen函数打开错误,如果返回的指针不为NULL,我们就将pc->date内的数据写入到pf这个FILE结构的指针所指向的文件信息区,然后达到写入文件的目的,最后别忘了关闭文件并且将pf指针置为NULL。

2.对文件联系人信息的读取

代码如下(示例):

void check(struct contact* pc)
{
    
    
	if ((pc->sz) >= (pc->max))
	{
    
    
		pc = (struct PeoInfo*)realloc(pc->date, (pc->max + 2) * sizeof(struct PeoInfo));
		printf("扩容成功\n");
		pc->max += 2;
	}
}
void Loadcontact(struct contact* pc)
{
    
    
	FILE* pf = fopen("contacts.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	struct PeoInfo tmp = {
    
     0 };
	while (fread(&tmp, sizeof(struct PeoInfo), 1, pf))
	{
    
    
		check(pc);
		pc->date[pc->sz] = tmp;
		pc->sz++;
	}
	fclose(pf);
	pf = NULL;
}
	void inicontact(struct contact* pc)
	{
    
    
		pc->sz = 0;
		pc->max = 3;
		pc->date = (struct PeoInfo*)calloc(3, sizeof(struct PeoInfo));
		 Loadcontact(pc);
	}

  在这里我们为了实现从文件中读取联系人的信息到内存涉及到了三个函数,分别是check函数,它的功能是查询通讯录是否已满,inicontact函数,它的功能是对通讯录进行初始化,我们之前的两个版本都是将创建的空间置为0,但是这里我们要将文件中的信息读入内存中,所以我们要在初始化的时候实现这一功能,Loadcontact函数就是我们加载联系人信息的实现函数,由它来控制加载文件中联系人的信息。
这里的难点在于fread函数,我们先来看一下fread函数的定义:
在这里插入图片描述
  fread函数的作用就是读取文件类型指针所指向空间的count个大小为size的二进制数据放入到ptr的指针所指向的空间中,函数的返回值类型是size_t,也就是无符号整型的数据,如果我们读到一个数据就返回1,两个数据就返回2,所以我们把它写在while循环中作为while循环条件,如果读取结束就返回0,自然会跳出循环。
这就最终实现了通讯录的最终版本——文件读写版本通讯录。

三、测试文件

代码如下(示例):

#define _CRT_SECURE_NO_WARNINGS
#include "FILE.h"
int main()
{
    
    
	struct contact c1;
	inicontact(&c1);
	int input = 1;
	do
	{
    
    
		menu();
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			system("cls");
			addpeople(&c1);
			break;
		case 2:
			system("cls");
			delpeople(&c1);
			break;
		case 3:
			system("cls");
			searchpeople(&c1);
			break;
		case 4:
			system("cls");
			revisepeople(&c1);
			break;
		case 5:
			system("cls");
			showpeople(&c1);
			break;
		case 6:
			system("cls");
			sortpeople(&c1);
			break;
		case 0:
			system("cls");
			savecontact(&c1);
			free(c1.date);
			exit(1);
			break;
		default:
			break;
		}
	} while (input);
	return 0;
}



总结

  写到这里通讯录的三个版本也就都结束了,后一个版本都是在前一个版本的基础上改进的,逐步让功能完善,成为可以真正满足需求的通讯录,再大的程序我们都可以大而化小,分而治之,逐步实现它的一个一个功能,希望我的博客对大家有所帮助,我们明天见~

猜你喜欢

转载自blog.csdn.net/MDLYB/article/details/127231836
今日推荐