C语言通讯录(附有完整代码)

本文提供了一个使用C语言编写的通讯录管理系统的代码分析,包括Contact.h、main.c和Contact.c三个主要部分。系统实现了添加、删除、查找、修改、显示、排序、保存和加载联系人信息等功能,同时涉及动态内存管理和结构体操作。代码中还包含了错误处理和用户交互界面。
摘要由CSDN通过智能技术生成

在这里插入图片描述

前言

通讯录对于C语言学习有着重大的意义,是一次非常综合性质的练习,囊括了C语言大多数知识,并且可以根据自身能力写出不同难度的通讯录。

代码解析

Contact.h

#pragma once
#include<stdio.h>
#include<stdlib.h>//动态内存的函数的头问题
#include<assert.h>//断言头文件
#include<string.h>//字符操作的头文件

#define Init 3 //设定一个通讯录容量的初始值
#define Bigger 2 //每次扩容扩大的值

#define MAX_NAME 20//名字的最大容量
#define MAX_SEX 10//性别的最大容量
#define MAX_TEL 15//电话的最大容量
#define MAX_ADDR 30//地址的最大容量

typedef struct PeoInfo //人的信息
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char tel[MAX_TEL];
	char addr[MAX_ADDR];
}PeoInfo;


typedef struct Contact //通讯录整体的结构体
{
	PeoInfo* data;
	int capacity;//最大容量
	int size;//实际存储的人数
}Contact;

void menu();//目录
void ContactInit(Contact* peo);//初始化
void ContactDestroy(Contact* peo);//销毁
void ContactAdd(Contact* con);//添加联系人信息
void check_capacity(Contact* con);//检查容量
void ContactDel(Contact* con);//删除指定联系人
void ContactSearch(Contact* con);//查找指定联系人信息
void ContactModify(Contact* con);//修改指定联系人信息
void ContactShow(Contact* con);//显示所有联系人信息
void ContactClear(Contact* con);//清空所有联系人
void ContactSort(Contact* con);//以名字排序所有联系人
void ContactSave(Contact* con);//保存信息
void ContactLoad(Contact* con);//导入信息

main.c

main.c中存储了整体的大框架,基本都是一些外部逻辑,以及函数调用

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"

int main()
{
	int input = 0;
	Contact con;
	ContactInit(&con);
	do
	{
		menu();
		printf("请进行你的选择>>>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactSearch(&con);
			break;
		case 4:
			ContactModify(&con);
			break;
		case 5:
			ContactShow(&con);
			break;
		case 6:
			ContactClear(&con);
			break;
		case 7:
			ContactSort(&con);
			break;
		case 8:
			ContactSave(&con);
			break;
		case 0:
			ContactSave(&con);
			ContactDestroy(&con);
			printf("通讯录已保存,退出成功!\n");
			break;
		default:
			printf("输入错误,请重新输入>>>\n");
			continue;
		}
	} while (input);
	return 0;
}

Contact.c

这一部分是每个函数的具体实现,是通讯录的核心

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"

void menu()//目录
{
	printf("********************************\n");
	printf("***  1、添加联系人           ***\n");
	printf("***  2、删除指定联系人       ***\n");
	printf("***  3、查找指定联系人       ***\n");
	printf("***  4、修改指定联系人信息   ***\n");
	printf("***  5、显示所有联系人信息   ***\n");
	printf("***  6、清空所有联系人       ***\n");
	printf("***  7、以名字排序所有联系人 ***\n");
	printf("***  8、保存通讯录           ***\n");
	printf("***  0、退出通讯录           ***\n");
	printf("********************************\n");
}

void ContactLoad(Contact* con)//导入信息
{
	assert(con);
	FILE* pf = fopen("Contact.txt", "rb");
	if (pf == NULL)//防止fopen失败
	{
		perror("ContactLoad::fopen");//perror是打印错误信息
		return;//如果fopen失败,就直接退出函数
	}
	int i = 0;
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))//fread如果读不到数据,返回0
	{
		check_capacity(con);//每次读取数据后,都需要检查容量
		con->data[i] = tmp;//检查容量后,将tmp赋给通讯录
		con->size++;//赋给通讯录后,实际存储量就con->size++
		i++;
	}
	fclose(pf);
	pf = NULL;
}

void ContactInit(Contact* con)//初始化
{
	assert(con);
	con->capacity = Init;
	con->size = 0;
	PeoInfo* ptr = (PeoInfo*)calloc(Init, sizeof(PeoInfo));//动态开辟内存
	if (ptr == NULL)
	{
		perror("InitContact::calloc");
		return;
	}
	con->data = ptr;

	//导入之前通讯录的信息
	ContactLoad(con);
}

void check_capacity(Contact* con)//检查容量
{
	assert(con);
	/如果容量不足,增容,如果容量充足,什么也不做
	if (con->capacity == con->size)
	{
		//增容,先用new作为指针变量接收,这是为了防止增容失败
		PeoInfo* new = (PeoInfo*)realloc(con->data, (con->capacity + Bigger) * sizeof(PeoInfo));
		if (new == NULL)
		{
			perror("check_capacity::realloc");
			return;
		}
		con->data = new;
		con->capacity += Bigger;//增容后,需要将new赋值,最大容量+Bigger
		printf("增容成功\n");
	}
}

void ContactAdd(Contact* con)//添加联系人信息
{
	assert(con);
	check_capacity(con);//添加之前需要检查容量
	printf("请输入姓名>>");
	scanf("%s", con->data[con->size].name);
	printf("请输入性别>>");
	scanf("%s", con->data[con->size].sex);
	printf("请输入年龄>>");
	scanf("%d", &(con->data[con->size].age));
	printf("请输入电话>>");
	scanf("%s", con->data[con->size].tel);
	printf("请输入住址>>");
	scanf("%s", con->data[con->size].addr);
	
	con->size++;
	printf("添加成功!\n");
}

void ContactDel(Contact* con)//删除指定联系人
{
	assert(con);
	if (!con->size)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	printf("请输入指定联系人的姓名>>");
	char Delname[MAX_NAME] = { 0 };
	scanf("%s", Delname);
	int i = 0;
	while(i < con->size)
	{
		if (!strcmp(Delname, con->data[i].name))
		{
			//删除信息
			//这里可以用覆盖的方式con->data[i] = con->data[i + 1];把data[i+1]中的数据整体赋值给data[i]
			memmove(&(con->data[i]), &(con->data[i + 1]), (con->size - i - 1) * sizeof(PeoInfo));
			con->size--;
			printf("删除成功!\n");
			return;
		}
		else
		{
			//查找下一个人
			i++;
		}
	}
	printf("此人不存在,无法删除\n");
}

void ContactSearch(Contact* con)//查找指定联系人信息
{
	assert(con);
	printf("请输入查找指定联系人的姓名>>");
	char Checkname[MAX_NAME] = {0};
	scanf("%s", Checkname);
	int i = 0;
	while (i < con->size)
	{
		if (!strcmp(Checkname, con->data[i].name))
		{
			
			printf("姓名:%-10s 性别:%-4s 年龄:%-4d 电话:%-15s 住址:%-20s\n", con->data[i].name, con->data[i].sex, con->data[i].age, con->data[i].tel, con->data[i].addr);
			return;
		}
		else
		{
			i++;
		}
	}
	printf("查无此人!\n");

}

void ContactModify(Contact* con)//修改指定联系人信息
{
	assert(con);
	printf("您想要修改的联系人>>");
	char Modifyname[MAX_NAME] = { 0 };
	scanf("%s", Modifyname);
	int i = 0;
	while (i < con->size)
	{
		if (!strcmp(Modifyname, con->data[i].name))
		{
			printf("请输入新的姓名>>");
			scanf("%s", con->data[i].name);
			printf("请输入新的性别>>");
			scanf("%s", con->data[i].sex);
			printf("请输入新的年龄>>");
			scanf("%d", &(con->data[i].age));
			printf("请输入新的电话>>");
			scanf("%s", con->data[i].tel);
			printf("请输入新的住址>>");
			scanf("%s", con->data[i].addr);
			printf("修改成功\n");
			return;
		}
		else
		{
			i++;
		}
	}
	printf("查无此人!\n");
	
}

void ContactShow(Contact* con)//显示所有联系人信息
{
	assert(con);
	if (!con->size)
	{
		printf("通讯录内无联系人\n");
		return;
	}
	int i = 0;
	for (i = 0; i < con->size; i++)
	{
		printf("姓名:%-10s 性别:%-4s 年龄:%-4d 电话:%-15s 住址:%-20s\n", con->data[i].name, con->data[i].sex, con->data[i].age, con->data[i].tel, con->data[i].addr);
	}
}

void ContactClear(Contact* con)//清空所有联系人
{
	assert(con);
	int i = 0;
	for (i = 0; i < con->size; i++)
	{
		memset(con->data[i].name, 0, MAX_NAME);
		memset(con->data[i].sex, 0, MAX_SEX);
		memset(&(con->data[i].age), 0, 4);
		memset(con->data[i].tel, 0, MAX_TEL);
		memset(con->data[i].addr, 0, MAX_ADDR);
	}
	con->capacity = Init;
	con->size = 0;
	printf("清空成功!\n");
}

int Com_name(const void* e1, const void* e2)
{
	assert(e1 && e2);
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void ContactSort(Contact* con)//以名字排序所有联系人
{
	assert(con);
	if (!con->size)
	{
		printf("通讯录内无联系人\n");
		return;
	}
	qsort(con->data, con->size, sizeof(PeoInfo), Com_name);
	printf("排序成功!\n");
}

void ContactSave(Contact* con)//保存信息
{
	assert(con);
	FILE* pf = fopen("Contact.txt", "wb");
	if (NULL == pf)
	{
		perror("ContactSave::fopen");
		return;
	}
	int i = 0;
	for (i = 0; i < con->size; i++)
	{
		fwrite(&con->data[i], sizeof(PeoInfo), 1, pf);
	}
	fclose(pf);
	pf = NULL;
	printf("保存成功\n");
}

void ContactDestroy(Contact* peo)//销毁
{
	assert(peo);
	peo->capacity = 0;
	peo->size = 0;
	free(peo->data);
	peo->data = NULL;
	peo = NULL;
}

代码链接

这里附上我的Gitee上的完整代码,以供大家使用
https://gitee.com/grass-without-dream/learning_-c/tree/master/Contact

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

失去梦想的小草

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

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

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

打赏作者

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

抵扣说明:

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

余额充值