C语言实现通讯录

该代码实现了一个动态内存管理的通讯录系统,包括初始化、添加、删除、查询、修改、打印、排序和文件保存等功能。使用了结构体数组存储联系人信息,并通过动态内存分配和realloc进行扩容。程序支持从文件读取和保存数据,以及多种排序方式。
摘要由CSDN通过智能技术生成

目录

游戏声明部分

游戏实现部分

主要逻辑部分


游戏声明部分

#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_CALL 12
#define MAX_ADDR 30
#define MAX_CON 100
#define MAX_SPACE 3 //初始化动态内存开辟空间大小

//一个人的信息
typedef struct ProInfo   //使用typedef进行重命名
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char call[MAX_CALL];
	char addr[MAX_ADDR];
}ProInfo;
//静态版本
//typedef struct Contact   //使用typedef进行重命名
//{
//	ProInfo data[MAX_CON];
//	int sz;
//}Contact;
//动态版本
typedef struct Contact
{
	ProInfo* data;//使用动态内存开辟的空间 由于存放联系人信息
	int sz;//用于记录联系人数量
	int capacity;//用于记录动态内存开辟空间的容量大小
}Contact;

//初始化
void initialize(Contact* pc);

//添加联系人
void AddContact(Contact* pc);

//打印联系人
void PrintContact(Contact* pc);

//删除联系人
void DelContact(Contact* pc);

//查询联系人
void QweryContact(Contact* pc);

//修改联系人
void ModfiyContact(Contact* pc);

//排序联系人
void SortContact(Contact* pc);

//退出程序时将数据保存到文件
void SaveContact(Contact* pc);

检查是否要扩容
void checkContact(Contact* pc);

//销毁通讯录
void destroycontact(Contact* pc);

游戏实现部分

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"

//静态版本
//void initialize(Contact* pc)
//{
//	memset(pc->data, 0, sizeof(pc->data)); //内存设置函数,以字节为单位将目标内存设置为想要的值
//	pc->sz = 0;
//	
//}
//动态版本
void initialize(Contact* pc)
{
	pc->sz = 0;
	ProInfo* p=(ProInfo*)calloc(MAX_SPACE,sizeof(ProInfo));//使用动态内存开辟一块空间,不把大小固定,方便后期修改大小
	if (p == NULL)//判断是否成功开辟空间
	{
		perror("initialize");//若开辟失败进行报错
		return;
	}
	pc->data = p;
	pc->capacity = MAX_SPACE;
	//读入数据--从文件中输入数据
	FILE* pf = fopen("contact.dat", "r");
	if (pf == NULL)
	{
		perror("initialize:fopen");
		return;
	}
	while (fread(pc->data + (pc->sz), sizeof(ProInfo), 1, pf))
	{
		checkContact(pc);
		pc->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

//检查是否要扩容
void checkContact(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		pc->capacity += 2;
		ProInfo* p = (ProInfo*)realloc(pc->data, pc->capacity * sizeof(ProInfo));//使用realloc函数进行扩容
		if (p == NULL)//判断是否成功开辟空间
		{
			perror("checkContact");//若开辟失败进行报错
			return;
		}
		pc->data = p;
		printf("扩容成功\n");
	}
}

//将数据保存到文件
void SaveContact(Contact* pc)
{
	//打开文件
	FILE* pf = fopen("contact.dat", "w");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	//写入数据--将数据输出至文件中
	int i;
	for (i = 0; i<pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(ProInfo), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

//销毁通讯录
void destroycontact(Contact* pc)
{
	free(pc->data);//释放之前动态开辟的内存
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}
//静态版本
//void AddContact(Contact* pc)
//{
//	printf("请输入姓名:");
//	scanf("%s", pc->data[pc->sz].name);
//	printf("请输入性别:");
//	scanf("%s", pc->data[pc->sz].sex);
//	printf("请输入年龄:");
//	scanf("%d", &pc->data[pc->sz].age);
//	printf("请输入电话:");
//	scanf("%s", pc->data[pc->sz].call);
//	printf("请输入地址:");
//	scanf("%s", pc->data[pc->sz].addr);
//	printf("输入成功\n");
//	pc->sz++;
//}
//动态版本
void AddContact(Contact* pc)
{
	//检查是否要扩容
	checkContact(pc);

	printf("请输入姓名:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入年龄:");
	scanf("%d", &pc->data[pc->sz].age);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->sz].call);
	printf("请输入地址:");
	scanf("%s", pc->data[pc->sz].addr);
	printf("输入成功\n");
	pc->sz++;
}

void PrintContact(Contact* pc)
{
	int i = 0;
	printf("%-5s\t%-5s\t%-5s\t%-15s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-5s\t%-5s\t%-5d\t%-15s\t%-30s\n"
			, pc->data[i].name
			, pc->data[i].sex
			, pc->data[i].age
			, pc->data[i].call
			, pc->data[i].addr);
	}
}

static int FindContact(const 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 DelContact(Contact* pc)
{
	printf("请输入删除人姓名:");
	char Name[20] = { 0 };
	scanf("%s", Name);
	int ret=FindContact(pc,Name);//返回下标,若无此联系人返回-1
	if (ret == -1)
	{
		printf("无此联系人,请重新选择\n");
		return;
	}
	int i = 0;
	for (i = ret; i < pc->sz-1; i++)  //将要删除联系人之后的下标向前移动一位,将要删除联系人覆盖
	{
		pc->data[i] = pc->data[i + 1];
	}
	printf("删除成功\n");
	pc->sz--; //移动完后,将sz--使得无法访问打印最后一位联系人即可,无需删除
}

void QweryContact(Contact* pc)
{
	printf("请输入查找人姓名:");
	char Name[MAX_NAME] = { 0 };
	scanf("%s", Name);
	int ret = FindContact(pc, Name);
	if (ret == -1)//若无则返回,重新选择
	{
		printf("无此联系人,请重新选择\n");
		return;
	}
	//若有则打印
	printf("%-5s\t%-5s\t%-5s\t%-15s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%-5s\t%-5s\t%-5d\t%-15s\t%-30s\n"
		, pc->data[ret].name
		, pc->data[ret].sex
		, pc->data[ret].age
		, pc->data[ret].call
		, pc->data[ret].addr);
}

void ModfiyContact(Contact* pc)
{
	printf("请输入修改人姓名:");
	char Name[MAX_NAME] = { 0 };
	scanf("%s", Name);
	int ret = FindContact(pc, Name);
	if (ret == -1)
	{
		printf("无此联系人,请重新选择\n");
		return;
	}
	printf("请输入修改后姓名:");
	scanf("%s", pc->data[ret].name);
	printf("请输入修改后性别:");
	scanf("%s", pc->data[ret].sex);
	printf("请输入修改后年龄:");
	scanf("%d", &pc->data[ret].age);
	printf("请输入修改后电话:");
	scanf("%s", pc->data[ret].call);
	printf("请输入修改后地址:");
	scanf("%s", pc->data[ret].addr);
	printf("修改成功\n");
}

//不同排序方法所使用的不同函数,用于比较两个元素的大小
int NameSort(const void*e1, const void*e2)
{
	return strcmp(((Contact*)e1)->data->name, ((Contact*)e2)->data->name);
}

int SexSort(const void* e1, const void* e2)
{
	return strcmp(((Contact*)e1)->data->sex, ((Contact*)e2)->data->sex);
}

int AgeSort(const void* e1, const void* e2)
{
	return ((Contact*)e1)->data->age - ((Contact*)e2)->data->age;
}

int CallSort(const void* e1, const void* e2)
{
	return strcmp(((Contact*)e1)->data->call, ((Contact*)e2)->data->call);
}

int AddrSort(const void* e1, const void* e2)
{
	return strcmp(((Contact*)e1)->data->addr, ((Contact*)e2)->data->addr);
}

void SortContact(Contact* pc)
{
	printf("请选择排序方法:\n");
	printf("**  1.name    2.sex     ***\n");
	printf("**  3.age     4.call    ***\n");
	printf("**  5.addr    0.exit    ***\n");
	int n = 0;
	scanf("%d", &n);
	//使用函数指针数组,利用下标访问不同函数
	int(*cmp[6])(const void*, const void*) = { NULL,NameSort ,SexSort, AgeSort, CallSort, AddrSort };
	switch (n)
	{
	case 1:
		qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]);  //使用qsort函数进行排序
		break;
	case 2:
		qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]);
		break;
	case 3:
		qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]);
		break;
	case 4:
		qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]);
		break;
	case 5:
		qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]);
		break;
	case 0:
		return;

	default:
		printf("输入错误,请重新选择\n");
		return;
	}
		printf("排序成功\n");
}

主要逻辑部分

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"

void menu()
{
	printf("***********************************\n");
	printf("*****  1.add    2.del     *********\n");
	printf("*****  3.query  4.modify  *********\n");
	printf("*****  5.print  6.sort    *********\n");
	printf("*****      0.exit         *********\n");
	printf("***********************************\n");
}
enum en
{
	EXIT,
	ADD,
	DEL,
	QWERY,
	MODIFY,
	PRINT,
	SORT
};
//添加,删除,查找,修改,打印,排序,
int main()
{
	int input = 0;
	Contact con;
	//初始化
	initialize(&con);
	do
	{
		menu();
		printf("请输入->");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case QWERY:
			QweryContact(&con);
			break;
		case MODIFY:
			ModfiyContact(&con);
			break;
		case PRINT:
			PrintContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case EXIT:
			SaveContact(&con);
			destroycontact(&con);//销毁通讯录
			printf("退出程序");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

theonly_Love

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

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

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

打赏作者

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

抵扣说明:

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

余额充值