C语言综合训练 —— 通讯录(使用动态内存)

1. 设计要求

我们设计的通讯录必须符合以下几点要求:

  1. 使用动态内存开辟通讯录,通讯录的初始默认大小为 3 个联系人类型。
  2. 联系人的信息包括:姓名、性别、年龄、电话、住址。
  3. 通讯录拥有添加联系人功能。
  4. 通讯录拥有删除联系人功能。
  5. 通讯录拥有按姓名查找联系人并输出此联系人所有信息的功能。
  6. 通讯录拥有修改联系人信息的功能。
  7. 通讯录拥有按年龄排序的功能。
  8. 通讯录拥有清空所有联系人信息、内存的功能。
  9. 通讯录拥有显示通讯录的功能。

2. 通讯录效果

 

 

 

 

3. 各文件代码

3.1 头文件各函数、结构体等声明

#define _CRT_SECURE_NO_WARNINGS 1

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

//枚举
enum Switch
{
	Exit,
	Add,
	Del,
	Seek,
	Modify,
	Show,
	Sort,
	Empty
};

//联系人
typedef struct People
{
	char name[20];
	char sex[10];
	int age;
	char tele[15];
	char addr[30];
}People;

//通讯录
typedef struct Contact
{
	People* data;//使用结构体指针,方便动态开辟空间
	int count;//统计联系人个数
	int capacity;//统计内存容量
}Contact;

//各函数声明
void InitContact(Contact* con);
void AddContact(Contact* con);
void ShowContact(Contact* con);
void DelContact(Contact* con);
void SeekContact(Contact* con);
void ModifyContact(Contact* con);
void SortContact(Contact* con);
void EmptyContact(Contact* con);

3.2 源文件功能实现

#define _CRT_SECURE_NO_WARNINGS 1
#include "func.h"
void InitContact(Contact* con)
{
	con->count = 0;
	con->data = (People*)calloc(3, sizeof(People));
	if (con->data == NULL)//若开辟不成功
	{
		printf("%s\n", strerror(errno));
		return;
	}
	else
		con->capacity = 3;
}

static void AddMemory(Contact* con)//使用 static 修饰,只能在本文件中使用
{
	People* tmp = (People*)realloc(con->data, (con->capacity + 2) * sizeof(People));
	if (tmp == NULL)//若开辟失败
	{
		printf("空间开辟失败!\n");
		printf("%s\n", strerror(errno));
		return;
	}
	else
	{
		con->data = tmp;
		printf("曾容成功!\n");
		con->capacity += 2;
	}
}
void AddContact(Contact* con)
{
	if (con->capacity == con->count)//如果容量与联系人数量相等
		AddMemory(con);//开辟空间

	//getchar() 是个人习惯,用来接收 scanf 不接收的 '\n'
	printf("请输入姓名:>");
	scanf("%s", con->data[con->count].name);
		getchar();
	printf("请输入性别:>");
	scanf("%s", con->data[con->count].sex);
		getchar();
	printf("请输入年龄:>");
	scanf("%d", &(con->data[con->count].age));
		getchar();
	printf("请输入电话:>");
	scanf("%s", con->data[con->count].tele);
		getchar();
	printf("请输入地址:>");
	scanf("%s", con->data[con->count].addr);
		getchar();
	printf("添加联系人成功\n");
	con->count++;
}

void ShowContact(Contact* con)
{
	if (con->count == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	printf("%-20s\t%-5s\t%-5s\t%-15s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");

	for (int i = 0; i < con->count; i++)
	{
		printf("%-20s\t%-5s\t%-5d\t%-15s\t%-30s\n", con->data[i].name,
													con->data[i].sex,
													con->data[i].age,
													con->data[i].tele,
													con->data[i].addr);
	}

}


static int FindName(Contact* con, char* tmp_name)//仅在本文件内使用,使用 static 修饰
{
	//对比姓名是否存在
	for (int i = 0; i < con->count; i++)
	{
		if (0 == strcmp(con->data[i].name, tmp_name))
			return i;//返回下标
	}
	return -1;
}
void DelContact(Contact* con)
{
	if (con->count == 0)
	{
		printf("通讯录为空!\n");
		return;
	}

	char tmp_name[20];
	printf("请输出要删除的联系人姓名:>");
	scanf("%s", tmp_name);
		getchar();

	int ret=FindName(con, tmp_name);
	if (ret == -1)
	{
		printf("此姓名不存在!\n");
		return;
	}
	else
	{
		for (int i = ret; i < con->count - 1; i++)
		{
			con->data[i] = con->data[i + 1];//覆盖
		}
		con->count--;//联系人个数 -1
		printf("删除成功!\n");
	}
}

void SeekContact(Contact* con)
{
	char seek_name[20];
	printf("请输出要查找的联系人姓名:>");
	scanf("%s", seek_name);
	getchar();

	int ret = FindName(con, seek_name);
	if (ret == -1)
	{
		printf("此姓名不存在!\n");
		return;
	}
	else
	{
		printf("%-20s\t%-5s\t%-5d\t%-15s\t%-30s\n", con->data[ret].name,
													con->data[ret].sex,
													con->data[ret].age,
													con->data[ret].tele,
													con->data[ret].addr);
	}
}

void ModifyContact(Contact* con)
{
	char modify_name[20];
	printf("请输入要修改的联系人姓名:>");
	scanf("%s", modify_name);
	getchar();

	int ret = FindName(con, modify_name);
	if (ret == -1)
	{
		printf("此姓名不存在!\n");
		return;
	}
	else
	{
		printf("请输入姓名:>");
		scanf("%s", con->data[ret].name);
		getchar();
		printf("请输入性别:>");
		scanf("%s", con->data[ret].sex);
		getchar();
		printf("请输入年龄:>");
		scanf("%d", &(con->data[ret].age));
		getchar();
		printf("请输入电话:>");
		scanf("%s", con->data[ret].tele);
		getchar();
		printf("请输入地址:>");
		scanf("%s", con->data[ret].addr);
		getchar();
		printf("修改联系人成功\n");
	}
	
}

static int cmp(const void* p1, const void* p2)//只在本文件内使用
{
	return ((People*)p1)->age - ((People*)p2)->age;
}
void SortContact(Contact* con)
{
	if (con->count == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	qsort(con->data, con->count, sizeof(People), cmp);//快速排序
	printf("排序成功!\n");
}

void EmptyContact(Contact* con)
{
	if (con->count == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	con->count = 0;
	free(con->data);//释放动态开辟的空间
	con->data = NULL;
	con->capacity = 0;
	InitContact(con);//初始化
	printf("清空成功!初始化成功!\n");
}

3.3 主函数程序入口

#define _CRT_SECURE_NO_WARNINGS 1
#include "func.h"
void menu()
{
	printf("\n");
	printf("\n");
	printf("\n");
	printf("********************************************\n");
	printf("********************************************\n");
	printf("*****1.添加联系人        2.删除联系人*******\n");
	printf("*****3.查找联系人        4.修改联系人*******\n");
	printf("*****5.显示通讯录        6.排序联系人*******\n");
	printf("*****7.清空通讯录        0.退出通讯录*******\n");
	printf("********************************************\n");
	printf("********************************************\n");
	printf("\n");
	printf("\n");
	printf("\n");
}
int main()
{
	int input = 0;
	Contact con;
	InitContact(&con);
	do
	{
		menu();//菜单
		printf("请选择:>");
		scanf("%d", &input);
		getchar();
		switch (input)
		{
		case Add://枚举变量
			AddContact(&con);
			break;
		case Del:
			DelContact(&con);
			break;
		case Seek:
			SeekContact(&con);
			break;
		case Modify:
			ModifyContact(&con);
			break;
		case Show:
			ShowContact(&con);
			break;
		case Sort:
			SortContact(&con);
			break;
		case Empty:
			EmptyContact(&con);
			break;
		case 0:
			EmptyContact(&con);
			printf("退出程序!\n");
			break;
		default:
			printf("输入错误!\n");
			break;
		}
	} while (input);
	return 0;
}

  • 29
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小龙向钱进

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

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

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

打赏作者

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

抵扣说明:

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

余额充值