当前位置:网站首页>C语言版——通讯录进阶(文件版本)

C语言版——通讯录进阶(文件版本)

2022-08-11 05:16:00 云逸943

前言

        在之前,我讲解了通讯录管理系统的项目程序,分别是:

普通版通讯录项目(静态开辟内存版): C语言版通讯录操作系统_

和进阶版通讯录项目(动态内存开辟版): C语言版通讯录——动态存储(进阶版)

        接下来,我再来讲一讲文件版本的通讯录,文件版本有个好处就是可以将调试过的程序的信息保存下来,就像一个小型简单版数据库一样。

一.代码实现:

1.保存调试信息写入文件中

        首先需要将程序被调试时填写的信息保存下来,写入到文件中,需要用到一个函数SaveContact();它的位置是在结束调试的分支语句中:

 在Contact.c函数实现中:

void SaveContact(Contact* pc) {
    //创造文件并打开,
	FILE* fw = fopen("Contact.txt", "wb");
	if (fw == NULL) {
		printf("%s\n", strerror(errno));
		return 1;
	}
	//写文件
	else {
		int i = 0;
		for (i = 0; i < pc->count; i++) {
			fwrite(pc->data + i, sizeof(PeoInf), 1, fw);
		}
	}

	//关闭文件
	fclose(fw);
	fw = NULL;
}

        代码讲解: 先创建文件指针接收fpoen函数创建出来的Contact.txt文件返回值,文件的打开模式是"wb","wb"是二进制写文件方式。然后通过if语句去判断指针是否打开文件成功,若成功,则继续下一步:将信息写入到文件中。写入文件的步骤是通过循环的方式,将PeoInf结构体类型的成员数据一个一个往进放,最后关闭文件。

        注:使用"wb"文件打开方式,打开时每次打开文件时会生成一个新的空文件覆盖原有的文件,则每次保存的时候都会重新录一遍信息,这样就可以通讯录的实时性,即删除联系人时再保存会把删除之后的联系人信息重新录进文件(原有的信息全部擦除)

增加两个成员:

           

 

 显示成员:

    

按0结束调试: 

 

 

文件内容: 

 

        如上图,通过程序调试填写的信息经过fwrite函数就可以写入文件Contact.txt中了,因为是二进制形式往里面存入,所以会有一些乱码情况(这个不打紧)。

2. 加载信息到通讯录程序中

在Contact.c中:

//扩容
void check_key(Contact* pc) {
	assert(pc);
	if (pc->count == pc->capacity) {
		PeoInf* str = realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInf));
		if (str == NULL) {
			printf("%s\n", strerror(errno));
			return 1;
		}
		else {
			pc->data = str;
			pc->capacity += 2;
			printf("增容成功\n");
		}
	}
}

//加载文件信息到通讯录中
void LoadContact(Contact* pc) {
	FILE* fr = fopen("Contact.txt", "rb");
	if (fr == NULL) {
		printf("%s\n", strerror(errno));
		return -1;
	}
	//读取文件信息
	PeoInf tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInf), 1, fr) == 1) {
		check_key(pc);
		pc->data[pc->count] = tmp;
		pc->count++;
	}

		//关闭文件
	fclose(fr);
	fr = NULL;
}


int InitContact(Contact* pc) {
	assert(pc);
	pc->capacity = CA_begin;
	pc->count = 0;
	pc->data =(PeoInf*)calloc(CA_begin, sizeof(PeoInf));
	if (pc->data == NULL) {
		printf("%s\n", strerror(errno));
		return -1;
	}
	//加载文件信息到通讯录中
	LoadContact(pc);
	return 0;
}

        LoadContact函数是用来实现加载信息到通讯录程序中的作用,它需要被放在初始化通讯录函数InitContact()中,LoadContact()函数的实现也是通过文件指针打开之前创建好的Contact.txt文件,使用fread函数读取文件中每个人的信息数据,需要调用扩容函数。

调试结果:

 

二.完整代码实现:

test.c:

#define _CRT_SECURE_NO_WARNINGS 1
# include<stdio.h>
#include"Contact.h"

enum {
	EXIT,
	ADD,
	DELETE,
	MODIFY,
	SEARCH,
	SHOW,
	QSORT,
	TOTAL,
	CLEAN
};


void menu() {
	printf("**************通讯录管理系统界面***************\n");
	printf("********************0.Exit.********************\n");
	printf("********************1.Add. ********************\n");
	printf("********************2.Delete.******************\n");
	printf("********************3.Mod. ********************\n");
	printf("********************4.Search.******************\n");
	printf("********************5.Show.********************\n");
	printf("********************6.Sqort.*******************\n");
	printf("********************7.Total.*******************\n");
	printf("********************8.Clean.*******************\n");
}
int main() {
	int input = 0;
	Contact con;
	//初始化通讯录
	InitContact(&con);
	do {
		menu();
		printf("请输入你的选择:\n");
		scanf("%d", &input);
		switch (input) {
		case EXIT:
			SaveContact(&con);//文件保存
			FreeContact(&con);
			printf("即将退出程序\n");
			break;
		case ADD:
			AddContact(&con);
			break;
		case DELETE:
			DelContact(&con);
			break;
		case MODIFY:
			ModContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case QSORT:
			QsortContact(&con);
			break;
		case TOTAL:
			TotalContact(&con);
			break;
		case CLEAN:
			CleanContact(&con);
			break;
		default:
			printf("输入错误\n");
			break;
		}
	} while (input);
	return 0;
}

Contact.c:

#include"Contact.h"

//扩容
void check_key(Contact* pc) {
	assert(pc);
	if (pc->count == pc->capacity) {
		PeoInf* str = realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInf));
		if (str == NULL) {
			printf("%s\n", strerror(errno));
			return 1;
		}
		else {
			pc->data = str;
			pc->capacity += 2;
			printf("增容成功\n");
		}
	}
}

//加载文件信息到通讯录中
void LoadContact(Contact* pc) {
	FILE* fr = fopen("Contact.txt", "rb");
	if (fr == NULL) {
		printf("%s\n", strerror(errno));
		return -1;
	}
	//读取文件信息
	PeoInf tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInf), 1, fr) == 1) {
		check_key(pc);
		pc->data[pc->count] = tmp;
		pc->count++;
	}

		//关闭文件
	fclose(fr);
	fr = NULL;
}




int InitContact(Contact* pc) {
	assert(pc);
	pc->capacity = CA_begin;
	pc->count = 0;
	pc->data =(PeoInf*)calloc(CA_begin, sizeof(PeoInf));
	if (pc->data == NULL) {
		printf("%s\n", strerror(errno));
		return -1;
	}
	//加载文件信息到通讯录中
	LoadContact(pc);
	return 0;
}
	



//添加
void AddContact(Contact* pc){
	assert(pc);
	check_key(pc);
		printf("正在准备添加功能验证:\n");
		printf("开始添加:\n");
		printf("请输入成员姓名:\n");
		scanf("%s", pc->data[pc->count].name);
		printf("请输入成员年龄:\n");
		scanf("%d", &(pc->data[pc->count].age));
		printf("请输入成员性别:\n");
		scanf("%s", pc->data[pc->count].sex);
		printf("请输入成员电话:\n");
		scanf("%s", pc->data[pc->count].tale);
		printf("请输入成员地址:\n");
		scanf("%s", pc->data[pc->count].addr);
		pc->count++;
		printf("添加成功\n");
	}

//显示
void ShowContact(Contact* pc) {
	assert(pc);
	if (pc->count == 0) {
		printf("通讯录为空,无法查看成员\n");
		return;
	}
	else {
		printf("%-20s\t %-4s\t %-5s\t %-12s\t %-20s\n", "姓名", "年龄", "性别", "电话", "地址");
		int i = 0;
		for (i = 0; i < pc->count; i++) {
			printf("%-20s\t %-4d\t %-5s\t %-12s\t %-20s\n", pc->data[i].name,
				pc->data[i].age,
				pc->data[i].sex,
				pc->data[i].tale,
				pc->data[i].addr
			);
		}
		
	}
}

//查找函数
int Find_name(Contact* pc, char name[]) {
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++) {
		if (strcmp(pc->data[i].name, name) == 0) {
			return i;
		}
	}
	return -1;
}


//删除
void DelContact(Contact* pc) {
	assert(pc);
	char name[MAX_NAME] = { 0 };
	if (pc->count == 0) {
		printf("通讯录为空,无法进行删除\n");
		return;
	}
	else {
		printf("请输入要删除人的名字:\n");
		scanf("%s", name);
		int ret = Find_name(pc, name);
		if (ret == -1) {
			printf("该成员不存在\n");
			return;
		}
		else {
			printf("正在准备删除功能验证:\n");
			int i = 0;
			for (i = ret; i < pc->count - 1; i++) {
				pc->data[i] = pc->data[i + 1];
			}
			pc->count--;
			printf("删除成功\n");
		}
	}
}

void ModContact(Contact* pc) {
	assert(pc);
	char name[MAX_NAME] = { 0 };
	if (pc->count == 0) {
		printf("通讯录为空,无法进行修改\n");
		return;
	}
	else {
		printf("请输入要修改的人员名单:\n");
		scanf("%s", name);
		int ret = Find_name(pc, name);
		if (ret == -1) {
			printf("该成员不存在\n");
			return;
		}
		else {
			printf("正在进行修改功能验证:\n");
			printf("修改开始:\n");
			printf("请输入成员姓名:\n");
			scanf("%s", pc->data[ret].name);
			printf("请输入成员年龄:\n");
			scanf("%d", &(pc->data[ret].age));
			printf("请输入成员性别:\n");
			scanf("%s", pc->data[ret].sex);
			printf("请输入成员电话:\n");
			scanf("%s", pc->data[ret].tale);
			printf("请输入成员地址:\n");
			scanf("%s", pc->data[ret].addr);
			printf("\n修改成功\n");
		}
	}
}

//查找功能
void SearchContact(Contact* pc) {
	assert(pc);
	char name[MAX_NAME] = { 0 };
	if (pc->count == 0) {
		printf("通讯录为空,无法进行查找\n");
		return;
	}
	else {
		printf("请输入要查找的人员名单:\n");
		scanf("%s", name);
		int ret = Find_name(pc, name);
		if (ret == -1) {
			printf("该成员不存在\n");
			return;
		}
		else {
			printf("%-20s\t %-4s\t %-5s\t %-12s\t %-20s\n", "姓名", "年龄", "性别", "电话", "地址");
			printf("%-20s\t %-4d\t %-5s\t %-12s\t %-20s\n", pc->data[ret].name,
				pc->data[ret].age,
				pc->data[ret].sex,
				pc->data[ret].tale,
				pc->data[ret].addr
			);
			printf("\n查找成功\n");

		}
	}
}

int cmp_by_name(const void* e1, const void* e2) {
	return strcmp(((PeoInf*)e1)->name, ((PeoInf*)e2)->name);
}

int cmp_by_age(const void* e1, const void* e2) {
	return ((PeoInf*)e1)->age-((PeoInf*)e2)->age;
}


//排序功能
void QsortContact(Contact* pc) {
	assert(pc);
	int i = 0;
	printf("1.按姓名排序            2.按年龄排序       \n");
	printf("请输入你要进行哪种排序方法?\n");
	scanf("%d", &i);
	if (i == 1) {
		qsort(pc->data, pc->count, sizeof(PeoInf), cmp_by_name);
	}
	else if (i == 2) {
		qsort(pc->data, pc->count, sizeof(PeoInf), cmp_by_age);
	}
	printf("排序成功\n");
}

//统计
void TotalContact(Contact* pc) {
	assert(pc);
	if (pc->count == 0) {
		printf("通讯录为空,人员为0\n");
		return;
	}
	int count = pc->count;
	printf("此时通讯录内共有%d个成员\n", count);
}


	int Clean(Contact * pc) {
		assert(pc);
		pc->capacity = CA_begin;
		pc->count = 0;
		pc->data = (PeoInf*)calloc(CA_begin, sizeof(PeoInf));
		if (pc->data == NULL) {
			printf("%s\n", strerror(errno));
			return -1;
		}
		return 0;
	}

//一键清空
void CleanContact(Contact* pc) {
	assert(pc);
	if (pc->count == 0) {
		printf("通讯录已为空,无法再执行此操作\n");
		return;
	}
	int i=0;
	printf("请问您确定要清空通讯录吗?确认请按9,否则按9以外的任意键\n");
	scanf("%d",&i);
	if (i == 9) {
		Clean(pc);
		printf("清空成功\n");
	}
	else if (i == 8) {
		return;
	}
}

void SaveContact(Contact* pc) {
	FILE* fw = fopen("Contact.txt", "wb");
	if (fw == NULL) {
		printf("%s\n", strerror(errno));
		return 1;
	}
	//写文件
	else {
		int i = 0;
		for (i = 0; i < pc->count; i++) {
			fwrite(pc->data + i, sizeof(PeoInf), 1, fw);
		}
	}

	//关闭文件
	fclose(fw);
	fw = NULL;
}



void FreeContact(Contact* pc) {
	free(pc->data);
	pc->data = NULL;
}

Contact.h:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
# include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<errno.h>

#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TALE 12
#define MAX_ADDR 20

#define  CA_begin 3
#define Add_every 2


typedef struct PeoInf {
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tale[MAX_TALE];
	char addr[MAX_ADDR];
}PeoInf;

typedef struct Contact {
	 PeoInf* data;
	int count;
	int capacity;
}Contact;


int InitContact(Contact* pc);
void AddContact(Contact* pc);
void ShowContact(Contact* pc);
void DelContact(Contact* pc);
void ModContact(Contact* pc);
void SearchContact(Contact* pc);
void QsortContact(Contact* pc);
void TotalContact(Contact* pc);
void CleanContact(Contact* pc);
void FreeContact(Contact* pc);


//文件保存
void saveContact(Contact* pc);

 

原网站

版权声明
本文为[云逸943]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_69283129/article/details/126165384