使用c语言实现简单通讯录,利用动态内存分配,和文件操作

 第一段代码是通讯录实现所需要的函数声明和一些值的定义,结构体的创建,详细见代码

#pragma once
//这个头文件包括一些库函数的头文件,结构体的创建,还有一些值的定义,还有自定义函数的声明
#define _CRT_SECURE_NO_WARNINGS  1
#pragma warning(disable:6031)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 3
#define NAME 20
#define SEX 10
#define ADDR 20
struct sb {
	char name[NAME];
	int age;
	char sex[SEX];
	long long int tele;
	char addr[ADDR];
	
};
struct contact {
	struct sb*data;
	int contain;
	int size;
}con;
int csh(struct contact* ps);
void addcontact(struct contact* ps);
void menu();
void delcontact(struct contact* ps);
void modifycontact(struct contact* ps);
void searchcontact(const struct contact* ps);
void showcontact(const struct contact* ps);
void sortcontact(struct contact* ps);
int savecontact(struct contact* ps);
void sfnc(struct contact* ps);

第二段代码是整个通讯录实现的逻辑,主要功能等,详细见代码

#include"contact.h"
//枚举:增加代码的可读性
enum u {
	EXIT,//0
	ADD,//1
	DEL,//2
	MODIFY,//3
	SEARCH,//4
	SHOW,//5
	SORT//6
};
//整个通讯录的实现过程
int main() {
	int input = 0;
	struct contact con;
	//初始化函数:把上次运行时输入的数据,继承过来,进行判断是防止文件打开有问题,有问题则直接停止
	if (csh(&con)) {
		return 0;
	}
	do
	{
		menu();
		scanf("%d", &input);
		switch(input) {
		//使用枚举代替数字,增加可读性:
		case ADD://1
			addcontact(&con);
			break;
		case DEL://2
			delcontact(&con);
			break;
		case MODIFY://3
			modifycontact(&con);
			break;
		case SEARCH://4
			searchcontact(&con);
			break;
		case SHOW://5
			showcontact(&con);
			break;
		case SORT://6
			sortcontact(&con);
			break;
		case EXIT://0
			//在通讯录结束时自动保存输入的数据,if语句防止保存失败。
			if (savecontact(&con))
				continue;
			//释放内存,以免泄露。
			sfnc(&con);
			printf("以退出程序\n");
			break;
		default:
			printf("选择错误:>\n");
			break;
		}
	} while (input);
	return 0;
}

 第三段是实现通讯录所需函数的定义,也是最重要的部分,里面涉及了动态内存的分配,内存申请,文件的操作等,详细见代码

#pragma warning(disable:6031)
//该文件用于对使用的自定义函数定义
#include"contact.h"
//菜单:
void menu() {
	printf("*********************************\n");
	printf("***1.add              2.del   ***\n");
	printf("***3.modify           4.search***\n");
	printf("***5.show             6.sort  ***\n");
	printf("***********  0.exit  ************\n");
	printf("*********************************\n");
}
//这个函数用于查找函数和删除函数,加是static可以使这个函数只能在这个源文件使用,在其他的源文件中不能用,以免干扰其他源文件
static int findbyname(const struct contact* s, char name[NAME]) {
	for (int i = 0; i < s->size ; i++) {
		if (0 == strcmp(s->data[i].name, name)) {
			return i;
		}
	}
	return -1;
}
//内存增加,原始内存为3,超过3就加2个空间,再超过则再加2,以此类推
void pdcontact(struct contact *ps) {
	if (ps->size == ps->contain) {
		ps->contain += 2;
		struct sb* pr = (struct sb*)realloc(ps->data, ps->contain * sizeof(struct sb));
		if (pr != NULL) {
			ps->data = pr;
			printf("增容成功\n");
		}
		else
			printf("增容失败\n");
	}
}
//判断是否联系人已经重复有了
int cfcontact(struct contact* ps,int count) {
	for (int i = 0; i < count; i++) {
		if (strcmp(ps->data[i].addr , ps->data[count].addr)==0 && ps->data[i].age == ps->data[count].age
			&& strcmp(ps->data[i].name, ps->data[count].name) == 0 && strcmp(ps->data[i].sex, ps->data[count].sex) == 0 &&
			ps->data[i].tele == ps->data[count].tele) {
			return 1;
		}
	}
	return 0;
}
//把创建的结构体初始化:
int csh(struct contact* ps) {
	struct sb* pr = (struct sb*)calloc(MAX, sizeof(struct sb));
	if (pr != NULL) {
		ps->data = pr;
	}
	//打开文件,读取上次输入的内容,
	FILE* ptr = fopen("test.txt", "rb");
	if (ptr == NULL) {
		//如果打开失败,告诉原因,并结束。
		perror("open file error");
		return 1;
	}
	ps->size = 0;
	ps->contain = MAX;
	//读取
	while (fread(&(ps->data[ps->size]), sizeof(struct sb), 1, ptr)) {
		ps->size++;
		//判断是否需要增容。
		pdcontact(ps);
	}
	//关闭文件
	fclose(ptr);
	ptr = NULL;
}
//添加联系人:
void addcontact(struct contact* ps) {
	//动态内存增加,以免造成空间的浪费
	pdcontact(ps);
	printf("请输入联系人信息:>\n");
	printf("姓名:>");
	scanf("%s",&ps->data[ps->size].name);
	printf("年龄:> ");
	scanf("%d", &ps->data[ps->size].age);
	printf("性别:> ");
	scanf("%s", &ps->data[ps->size].sex);
	printf("电话号码:> ");
	scanf("%lld", &ps->data[ps->size].tele);
	printf("地址:> ");
	scanf("%s", &ps->data[ps->size].addr);
	//判断用户新增的联系人是否重复。
	int ret=cfcontact(ps,ps->size);
	if (ret) {
		//如果重复了,把刚刚输入的数据初始化,并且ps->size不用加1.
		memset(&(ps->data[ps->size]), 0, sizeof(struct sb));
		printf("该联系人以存在,添加失败:>\n");
	}
	//没重复则继续
	else {
		ps->size++;
		printf("添加成功\n");
	}
}
//删除联系人:
void delcontact(struct contact* ps) {
	if (ps->size == 0) {
		printf("该通讯录目前无联系人:>\n");
		return;
	}
	char name[NAME];
	printf("请输入要删除的姓名:>\n");
	scanf("%s", &name);
	int ret = findbyname(ps, name);
	if (ret == -1)printf("该成员不存在\n");
	else {
		for (int i = ret; i < ps->size - 1; i++) {
			ps->data[i] = ps->data[i + 1];
		}
		ps->size--;
		printf("删除成功:>\n");
	}
}
//修改其中的联系人数据:
void modifycontact(struct contact* ps) {
	if (ps->size == 0) {
		printf("该通讯录目前无联系人:>\n");
		return;
	}
	char name[NAME];
	printf("请输入你将修改的姓名:>\n");
	scanf("%s", &name);
	int ret=findbyname(ps, name);
	if (ret == -1)printf("该成员不存在\n");
	else {
		printf("请重新输入联系人信息:>\n");
		printf("姓名    :>");
		scanf("%s", &ps->data[ret].name);
		printf("年龄    :> ");
		scanf("%d", &ps->data[ret].age);
		printf("性别    :> ");
		scanf("%s", &ps->data[ret].sex);
		printf("电话号码:> ");
		scanf("%lld", &ps->data[ret].tele);
		printf("地址    :> ");
		scanf("%s", &ps->data[ret].addr);
		printf("修改成功:>\n");
	}
}
//查找联系人:
void searchcontact(const struct contact* ps) {
	if (ps->size == 0) {
		printf("该通讯录目前无联系人:>\n");
		return;
	}
	char name[NAME];
	printf("请输入你想查找的联系人姓名:>\n");
	scanf("%s", &name);
	int ret=findbyname(ps,name);
	if (ret == -1) {
		printf("该成员不存在\n");
	}
	else {
		printf("%-20s\t%-20s\t%-20s\t%-20s \t%-20s\t\n", "姓名", "年龄", "性别", "电话号码", "地址");
		printf("%-20s\t%-20d\t%-20s\t%-20lld\t%-20s\t\n", ps->data[ret].name, ps->data[ret].age, ps->data[ret].sex, ps->data[ret].tele, ps->data[ret].addr);
	}
}
//打印已经添加的通讯录
void showcontact(const struct contact* ps) {
	if (ps->size == 0) {
		printf("该通讯录目前无联系人:>\n");
		return;
	}
	printf("%-20s\t%-20s\t%-20s\t%-20s \t%-20s\t\n", "姓名", "年龄", "性别", "电话号码", "地址");
	for (int i = 0; i < ps->size; i++) {
		printf("%-20s\t%-20d\t%-20s\t%-20lld\t%-20s\t\n", ps->data[i].name, ps->data[i].age, ps->data[i].sex,ps->data[i].tele, ps->data[i].addr);
	}
}
//选择年龄升序
void sortcontact(struct contact* ps) {
	if (ps->size == 0) {
		printf("该通讯录目前无联系人:>\n");
		return;
	}
	for (int i = 0; i < ps->size; i++) {
		for (int j = i+1; j < ps->size; j++) {
			//这里不能只改年龄,建立一个临时结构体变量(必须和data类型一样),
			if (ps->data[i].age > ps->data[j].age) {
				struct sb t = ps->data[i];
				ps->data[i] = ps->data[j];
				ps->data[j] = t;
			}
		}
	}
	//重新打印排序后的通讯录
	showcontact(ps);
}
void sfnc(struct contact* ps) {
	free(ps->data);
	//free会释放掉内存但是ps->data的指针依然会保留,为了防止非法访问,将ps->data变成空指针
	ps->data = NULL;
}
int savecontact(struct contact* ps) {
	//创建一个二进制文件
	FILE* ptr = fopen("test.txt", "wb");
	//进行判断是否创建成功
	if (ptr == NULL) {
		//如果失败了,说明失败原因
		perror("save error");
		return 1;
	}
	//保存
	for (int i = 0; i < ps->size; i++) {
		fwrite(&(ps->data[i]), sizeof(struct sb), 1, ptr);
	}
	printf("保存成功\n");
	//关闭文件
	fclose(ptr);
	ptr = NULL;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shshajsjs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值