C语言模拟通讯录

通讯录最主要的就是需要保存联系人的姓名,电话号码.所以定义联系人信息的结构体

// 联系人信息
typedef struct ContactInfo {
	char name[1024];
	char phone_number[1024];
} ContactInfo;

联系人有多少也不一定,所以用一个动态顺序表存储所有联系人

// 通讯录
typedef struct AddressBook {
	ContactInfo *contact_info;	// 存储联系人
	int size;					// 有效联系人个数
	int cap;					// 当前存储联系人的容量
} AddressBook;

主函数

int main() {
	// 转移表
	void(*pfunc[3])() = { AddContact, SearchContact, ClearAllContact };
	Init();		// 初始化

	while (1) {
		system("cls");		
		Menu();		// 开始界面
		int chiose;
		// 联系人序号和其他操作序号
		while (scanf("%d", &chiose) == 0 || chiose < 0 ||
			   (chiose >= g_address_book.size && chiose < 10000) ||
			   chiose > 10003) {
			setbuf(stdin, NULL);	// 清空缓冲区
			printf("输入非法!请重输: ");
		}
		if (chiose == 10003) {	// 退出
			SaveContactInfo();
			free(g_address_book.contact_info);
			break;
		}
		else if ((chiose - 10000) >= 0) {	// 功能
			(*pfunc[chiose - 10000])();
		}
		else {
			DetailInfo(chiose);	// 联系人详细信息
		}
	}

	system("pause");
	return 0;
}

初始化

// 初始化
void Init() {
	// 初始化联系人上限为64人
	g_address_book.contact_info = (ContactInfo *)malloc(64 * sizeof(ContactInfo));
	g_address_book.size = 0;		// 有效联系人为空
	g_address_book.cap = 64;		// 上限为64
	loadContactInfo();	// 加载已有的联系人
}

加载已有的联系人

// 加载联系人
void loadContactInfo() {
	// 打开文件
	FILE *fp = fopen("../contactinfo.txt", "r");
	if (fp == NULL) {	// 判空
		printf("%s\n", strerror(errno));
		system("pause");
		return;
	}
	char buf[1024] = { 0 };	// 输入缓冲
	while (fgets(buf,1024,fp) != NULL) {
		if (g_address_book.size >= g_address_book.cap) {	// 内存空间满了
			// 重新申请内存空间
			g_address_book.contact_info = 
				(ContactInfo *)realloc(g_address_book.contact_info, 2 * g_address_book.size * sizeof(ContactInfo));
			// 修改容量
			g_address_book.cap = 2 * g_address_book.size;
		}
		// 读入联系人信息
		ContactInfo *info = &g_address_book.contact_info[g_address_book.size];
		// fgets函数会将换行一并读取, 所以在此将换行去掉
		// 读入姓名
		strcpy(info->name, DelWrap(buf));
		// 读入电话号码	
		if (fgets(buf, 1024, fp) != NULL) {
			strcpy(info->phone_number, DelWrap(buf));
		}
		// 有效联系人增加
		++g_address_book.size;
	}
	// 关闭文件
	fclose(fp);
}

去掉换行符

// 去掉加载联系人是读入的换行符
char * DelWrap(char *str) {
	if (str == NULL) {
		return NULL;
	}
	// 用结束符覆盖换行符
	int len = strlen(str);
	str[len - 1] = str[len];
	return str;
}

保存联系人到磁盘

// 保存联系人信息
void SaveContactInfo() {
	// 打开文件
	FILE *fp = fopen("../contactinfo.txt", "w");
	if (fp == NULL) {	// 判空
		printf("%s\n", strerror(errno));
		system("pause");
		return;
	}
	// 将数据保存到文件中
	for (int curr = 0; curr < g_address_book.size; ++curr) {
		ContactInfo *info = &g_address_book.contact_info[curr];
		// 使用格式化输出
		fprintf(fp, "%s\n", info->name);
		fprintf(fp, "%s\n", info->phone_number);
	}
	// 关闭文件
	fclose(fp);
}

初始界面

// 通讯录界面
void Menu() {
	printf("********************************\n");
	printf("*********** 通 讯 录 ***********\n");
	printf("********************************\n");
	PrintAllContact();	// 打印全部联系人
	printf("** 10000 :新建 ** 10001 :搜索 **\n");
	printf("********************************\n");
	printf("** 10002 :清空 ** 10003 :退出 **\n");
	printf("********************************\n");
	printf("请输入: ");
}

打印全部联系人

// 打印全部联系人
void PrintAllContact() {
	printf("  共 %d 个联系人\n", g_address_book.size);
	// 遍历打印联系人
	for (int curr = 0; curr < g_address_book.size; ++curr) {
		ContactInfo *info = &g_address_book.contact_info[curr];
		printf("  [%4d] %s\n", curr, info->name);
	}
	// 有联系人才输出
	if (g_address_book.size != 0) {
		printf("********************************\n");
		printf("**** 输入序号以查看详细信息 ****\n");
	}
	printf("********************************\n");
}

查看联系人详细信息

// 根据序号查看联系人详细信息
void DetailInfo(int number) {
	int(*pfunc[2])(int num) = { UpdateContactInfo, DeleteContact };
	while (1) {
		system("cls");
		printf("********************************\n");
		printf("******** 联系人详细信息 ********\n");
		printf("********************************\n");
		ContactInfo *info = &g_address_book.contact_info[number];
		printf("  姓名: %s\n", info->name);
		printf("  电话: %s\n", info->phone_number);
		printf("********************************\n");
		printf("** 10000 :修改 ** 10001 :删除 **\n");
		printf("********************************\n");
		printf("********* 10002 :退出 **********\n");
		printf("********************************\n");
		printf("请输入: ");
		int chiose;
		// 功能选项
		while (scanf("%d", &chiose) == 0 || chiose < 10000 || chiose > 10002) {
			setbuf(stdin, NULL);	// 清空缓冲区
			printf("输入非法!请重输: ");
		}
		// 返回上一级
		if (chiose == 10002) {
			break;
		}
		else if ((*pfunc[chiose - 10000])(number)) {
			break;	// 删除联系人后退出到主界面
		}
	}
}

修改联系人信息

// 修改联系人信息
int UpdateContactInfo(int number) {
	system("cls");
	printf("********************************\n");
	printf("******** 修改联系人信息 ********\n");
	printf("********************************\n");
	printf("****** 输入 '/' 跳过该项 *******\n");
	printf("********************************\n");
	ContactInfo *info = &g_address_book.contact_info[number];
	char tmp_info[1024] = { 0 };
	setbuf(stdin, NULL);	// 清空输入缓冲,以免读错
	printf("  姓名(%s): ", info->name);
	gets(tmp_info);
	if (tmp_info[0] != '/') {
		strcpy(info->name, tmp_info);
	}
	printf("  电话(%s): ", info->phone_number);
	gets(tmp_info);
	if (tmp_info[0] != '/') {
		strcpy(info->phone_number, tmp_info);
	}
	printf("********************************\n");
	printf("*********** 修改成功 ***********\n");
	printf("********************************\n");
	system("pause");
	return 0;
}

删除联系人

// 删除联系人
int DeleteContact(int number) {
	printf("********************************\n");
	printf("****** 确定要删除该联系人 ******\n");
	printf("********************************\n");
	printf("****** / Y / ****** / N / ******\n");
	printf("********************************\n");
	printf("请输入: ");
	setbuf(stdin, NULL);
	char chiose = getchar();
	setbuf(stdin, NULL);	// 怕用户乱输,清空缓冲区
	if (chiose == 'Y' || chiose == 'y') {	// 大小写均可
		// 无序
		//g_address_book.contact_info[number] = g_address_book.contact_info[g_address_book.size - 1];
		//--g_address_book.size;

		// 有序
		// 所有元素number之后的元素向前移动
		ContactInfo *info = g_address_book.contact_info;
		for (int curr = number; curr < g_address_book.size - 1; ++curr) {
			info[curr] = info[curr + 1];
		}
		--g_address_book.size;	// 有效联系人减少
		printf("********************************\n");
		printf("*********** 删除成功 ***********\n");
		printf("********************************\n");
		system("pause");
		return 1;
	}
	return 0;	// 取消删除,乱输都视为删除失败
}

新建联系人

// 新建联系人
void AddContact() {
	system("cls");
	// 联系人上限固定不能改
	//if (g_address_book.size >= 1024) {
	//	printf("********************************\n");
	//	printf("******* 新增未能成功执行 *******\n");
	//	printf("********************************\n");
	//	system("pause");
	//	return;
	//}
	
	// 动态内存
	if (g_address_book.size >= g_address_book.cap) {	// 内存空间满了
														// 重新申请内存空间
		g_address_book.contact_info =
			(ContactInfo *)realloc(g_address_book.contact_info, 2 * g_address_book.size * sizeof(ContactInfo));
		// 修改容量
		g_address_book.cap = 2 * g_address_book.size;
	}
	ContactInfo *info = &g_address_book.contact_info[g_address_book.size];
	printf("********************************\n");
	printf("********** 新建联系人 **********\n");
	printf("********************************\n");
	printf("  姓名: ");
	setbuf(stdin, NULL);
	gets(info->name);
	printf("  电话: ");
	gets(info->phone_number);
	printf("********************************\n");
	printf("*********** 新增成功 ***********\n");
	printf("********************************\n");
	++g_address_book.size;	// 有效联系人增加
	SortContact();	// 对新增的联系人进行插入排序
	system("pause");
}

对联系人排序

// 对新增联系人排序
void SortContact() {
	ContactInfo *info = g_address_book.contact_info;
	ContactInfo tmp_info = info[g_address_book.size - 1];	// 最后一个元素
	int curr = g_address_book.size - 1;		// 最后一个元素位置
	for (; curr > 0; --curr) {
		if (strcmp(info[curr - 1].name, tmp_info.name) > 0) {	// 前一个元素比待排序元素大
			info[curr] = info[curr - 1];	// 前一个元素后移
		}
		else {
			info[curr] = tmp_info;		// 否则,待排序数就在当前位置
			break;						// 只排序最新的联系人
		}
	}
	if (curr == 0) {		// 循环结束,待排序元素比所有元素都小
		info[curr] = tmp_info;
	}
}

根据姓名查找联系人信息

// 搜索联系人
void SearchContact() {
	if (g_address_book.size == 0) {
		printf("********************************\n");
		printf("********** 通讯录为空 **********\n");
		printf("********************************\n");
		system("pause");
		return;
	}
	system("cls");
	printf("********************************\n");
	printf("********** 搜索联系人 **********\n");
	printf("********************************\n");
	printf("请输入姓名: ");
	char name[1024] = { 0 };
	scanf("%s", name);
	printf("********************************\n");
	int count = 0;
	for (int curr = 0; curr < g_address_book.size; ++curr) {	// 打印所有匹配姓名的信息
		ContactInfo *info = &g_address_book.contact_info[curr];
		if (strcmp(info->name, name) == 0) {
			printf("  [%4d] %s\t%s\n", curr, info->name, info->phone_number);
			++count;
		}
	}
	printf("  共找到 %d 个联系人\n", count);
	if (count != 0) {
		printf("********************************\n");
		printf("**** 输入序号以查看详细信息 ****\n");
	}
	printf("********************************\n");
	printf("********* 10000 :退出 **********\n");
	printf("********************************\n");
	printf("请输入: ");
	int chiose;
	while (scanf("%d", &chiose) == 0 || chiose < 0 ||
		(chiose >= g_address_book.size && chiose != 10000)) {
		setbuf(stdin, NULL);	// 清空缓冲区
		printf("输入非法!请重输: ");
	}
	if (chiose != 10000) {
		DetailInfo(chiose);	// 联系人详细信息
	}
	return;
}

清空所有联系人

// 清空联系人
void ClearAllContact() {
	if (g_address_book.size == 0) {
		printf("********************************\n");
		printf("********** 通讯录为空 **********\n");
		printf("********************************\n");
		system("pause");
		return;
	}
	printf("********************************\n");
	printf("******* 确定要清空联系人 *******\n");
	printf("********************************\n");
	printf("****** / Y / ****** / N / ******\n");
	printf("********************************\n");
	printf("请输入: ");
	setbuf(stdin, NULL);	// 怕用户乱输,清空缓冲区
	char chiose = getchar();
	if (chiose == 'Y' || chiose == 'y') {	// 大小写均可
		g_address_book.size = 0;
		printf("********************************\n");
		printf("*********** 清空成功 ***********\n");
		printf("********************************\n");
		system("pause");
	}
	// 取消,乱输都视为失败
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值