【C语言】实现通讯录的增删改查、动态扩容及将信息保存到文件中

目录
一、头文件部分
二、测试部分
三、通讯录实现的功能模块介绍
1.初始化通讯录
静态版本
动态版本
将通讯录信息保存到文件
加载文件信息到通讯录
2.添加联系人
静态版本
动态版本
核查通讯录容量
3.销毁通讯录
4.显示所有的联系人
5.显示单个联系人
6.删除指定的联系人
7.查找指定的联系人
8.修改指定的联系人
9.排序所有联系人
10.将通讯录信息保存到文件中
一、头文件声明

#pragma once
struct people_info//联系人结构体
{
	int age;//考虑到结构体内存对齐问题
	char name[32];
	char sex[8];
	char phone[16];
	char address[32];
};

#define CAPACITY_cur_size 3
#define MAX_PEOPLE 1000
struct address_book//通讯录结构体
{
	struct people_info *p;
	int capacity;//最大容量,默认就是MAX_PEOPLE
	int cur_size;//当前联系人数量
};

extern void book_init(struct address_book *book);//初始化通讯录
extern int book_add(struct address_book *book);//增加联系人
extern void book_print(struct address_book *book);//打印通讯录
extern int find(struct address_book *book);//查找指定联系人
extern int book_del(struct address_book *book);//删除指定联系人
extern int book_mod(struct address_book *book);//修改指定联系人
extern int book_clear(struct address_book *book);//清空通讯录
extern int book_sort(struct address_book *book);//联系人排序
extern void book_destory(struct address_book *book);//销毁通讯录
extern void book_saveaddress(struct address_book *book);//保存信息到通讯录
extern void book_Loadaddress(struct address_book *book);//加载文件中的信息到通讯录中

二、
这部分主要完成通讯录各个功能的入口,及一个菜单显示页面。具体实现程序如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include"child.h"

int main()
{
	struct address_book book;
	book_init(&book);//初始化只需要一次,所以不需放在while循环中
	while (1)
	{
		printf("**************通讯录**************\n");
		printf("*****1.添加联系人 2.查找联系人*****\n");
		printf("*****3.修改联系人 4.删除联系人*****\n");
		printf("*****5.排序联系人 6.打印通讯录*****\n");
		printf("*********** 0.退出通讯录**********\n");
		int choice = -1;
		printf("请输入操作:");
		scanf("%d", &choice);
		switch (choice)
		{
		case 1:
			book_add(&book);
			break;
		case 2:
			find(&book);
			break;
		case 3:
			book_mod(&book);
			break;
		case 4:
			book_del(&book);
			break;
		case 5:
			book_sort(&book);
			break;
		case 6:
			book_print(&book);
			break;
		case 0:
			//book_saveaddress(&book);
			book_destory(&book);
			break;
		default:
			printf("选项错误,请重新输入!");
			break;
		}
	}
	system("pause");
	return 0;
}

三、通讯录实现的功能模块介绍
1.初始化通讯录
静态版本:

void book_init(struct address_book *book)
{
	book->cur_size = 0;//默认没有信息
	//memset(book->p, 0, MAX*sizeof(struct people_info));
	//memset()函数原型是extern void *memset(void *buffer, int c, int count)       
	//buffer:为指针或是数组,c:是赋给buffer的值,count:是buffer的长度.
	memset(book->p, 0, sizeof(book->p));
}

动态版本:

void book_init(struct address_book *book)
{
	book->capacity = CAPACITY_cur_size;
	book->cur_size = 0;
	book->p= (struct people_info*)malloc(book->capacity * sizeof(struct people_info));
	if (book->p == NULL)
	{
		printf("初始化失败\n");
		exit(1);//exit(1)表示异常退出
	}
	//加载文件信息到通讯录
	book_Loadaddress(book);
	return;
}

将通讯录信息保存到文件中

void book_saveaddress(struct address_book *book)
{
	FILE* pout = fopen("address_book.dat", "wb");//打开文件,二进制写
	if (pout == NULL)
	{
		printf("打开失败\n");
		return;
	}

	for (int i = 0; i < book->cur_size; i++)
	{
		fwrite(book->p + i, sizeof(struct people_info), 1, pout);
	}
	printf("保存成功\n");
	fclose(pout);
	pout = 0;
}

加载文件信息到通讯录

void book_Loadaddress(struct address_book *book)
{
	FILE* puin = fopen("address_book.dat", "rb");
	if (puin == NULL)
	{
		printf("打开失败\n");
		return;
	}

	struct people_info tmp = { 0 };//相当于中间变量
	while (fread(&tmp, sizeof(struct people_info), 1, puin))//取出一个单位的内容到tmp的地址中
	{
		if (expansion(book) == 0)//相当于增加,所以要判断容量
		{
			printf("容量不足且扩容失败\n");
			return;
		}
		book->p[book->cur_size] = tmp;//当前位置的值
		book->cur_size++;
	}
	fclose(puin);//读完关闭文件,并将指针滞空
	puin = NULL;
}

2.添加联系人
静态版本:

int book_add(struct address_book *book)
{
	if (book->cur_size == MAX_PEOPLE)
	{
		printf("通讯录已满,无法增加新的联系人\n");
		return;
	}
	printf("请输入联系人姓名:");
	scanf("%s", book->p[book->cur_size].name);
	printf("请输入联系人性别:");
	scanf("%s", book->p[book->cur_size].sex);
	printf("请输入联系人年龄:");
	scanf("%d", &book->p[book->cur_size].age);//年龄属于数字,需用%d打印输出
	printf("请输入联系人电话:");
	scanf("%s", book->p[book->cur_size].phone);
	printf("请输入联系人地址:");
	scanf("%s", book->p[book->cur_size].address);
	book->cur_size += 1;
	return 0;
}

动态版本:

int book_add(struct address_book *book)
{
	expansion(book);
	printf("请输入联系人姓名:");
	scanf("%s", book->p[book->cur_size].name);
	printf("请输入联系人性别:");
	scanf("%s", book->p[book->cur_size].sex);
	printf("请输入联系人年龄:");
	scanf("%d", &book->p[book->cur_size].age);//年龄属于数字,需用%d打印输出
	printf("请输入联系人电话:");
	scanf("%s", book->p[book->cur_size].phone);
	printf("请输入联系人地址:");
	scanf("%s", book->p[book->cur_size].address);
	book->cur_size += 1;
	return 0;
}

此模块中涉及检查通讯录容量部分,如果容量已超过最初设置的参数,则将扩容,将这部分也写成了一个函数如下所示:
核查通讯录容量

int expansion(struct address_book *book)
{
	if (book->cur_size == book->capacity-1)
	{
		struct people_info *ptr = (struct people_info*)realloc(book->p, (book->capacity + 2) * sizeof(struct people_info));
		if (ptr != NULL)
		{
			book->p = ptr;
			book->capacity += 2;
			printf("扩容成功\n");
		}
		else
		{
			perror("通讯录增容失败");
			exit(1);
		}
	}
}

3.销毁通讯录

void book_destory(struct address_book *book)
{
	book_saveaddress(book);
	free(book->p);
	book->p = NULL;
	book->capacity = 0;
	book->cur_size = 0;
}

4.显示所有联系人

void book_print(struct address_book *book)
{
	printf("%10s\t%5s\t%5s\t%15s\t%20s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < book->cur_size; i++)
	{
		printf("%10s\t%5s\t%5d\t%15s\t%20s\n", book->p[i].name, book->p[i].sex, book->p[i].age, book->p[i].phone, book->p[i].address);
	}
	return;
}

5.显示单个联系人

void print_people(struct address_book *book, int i)//打印单个联系人
{
	printf("%10s\t%5s\t%5s\t%15s\t%20s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%10s\t%5s\t%5d\t%15s\t%20s\n", book->p[i].name, book->p[i].sex, book->p[i].age, book->p[i].phone, book->p[i].address);
}

6.删除指定联系人

int book_del(struct address_book *book)
{
	printf("请输入要删除的联系人名称:");
	int pos = book_find(book);
	if (pos == -1)
	{
		printf("要删除的联系人不存在!\n");
		return -1;
	}
	for (int i = pos; i < book->cur_size - 1; i++)//i < book->cur_size - 1,防止i+1出现越界问题
	{
		book->p[i] = book->p[i + 1];
	}
	book->cur_size--;
	printf("删除联系人完毕!\n");
	return 0;
}

7.查找指定联系人

int book_find(struct address_book *book)
{
	//printf("请输入要查找的联系人名称:");
	char name[32] = { 0 };
	scanf("%s", name);
	for (int i = 0; i < book->cur_size; i++)
	{
		if (strcmp(name, book->p[i].name) == 0)//strcmp比较两个字符串
		{
			return i;
		}
	}
	return 0;
}

int find(struct address_book *book)
{
	printf("请输入要查找的联系人名称:");
	int pos = book_find(book);
	if (pos == -1)
	{
		printf("要查找的联系人不存在!\n");
		return -1;
	}
	print_people(book, pos);
	return 0;
}

8.修改指定联系人

int book_mod(struct address_book *book)
{
	printf("请输入要修改的联系人名称:");
	int pos = book_find(book);
	if (pos == -1)
	{
		printf("要修改的联系人不存在!\n");
		return -1;
	}
	printf("********修改信息选择**********\n");
	printf("*****1.姓名        2.性别*****\n");
	printf("*****3.年龄        4.电话*****\n");
	printf("*****5.地址        0.退出*****\n");
	printf("********修改信息选择**********\n");
	int choice = -1;
	scanf("%d", &choice);
	switch (choice)
	{
	case 1:
		printf("请输入联系人姓名:");
		scanf("%s", book->p[pos].name);
		break;
	case 2:
		printf("请输入联系人性别:");
		scanf("%s", book->p[pos].sex);
		break;
	case 3:
		printf("请输入联系人年龄:");
		scanf("%d", &book->p[pos].age);
		break;
	case 4:
		printf("请输入联系人电话:");
		scanf("%s", book->p[pos].phone);
		break;
	case 5:
		printf("请输入联系人地址:");
		scanf("%s", book->p[pos].address);
		break;
	default:
		printf("退出修改!\n");
	}
	printf("修改完毕!\n");
	return 0;
}

9.将所有联系人排序

int book_sort(struct address_book *book)
{
	for (int i = 0; i < book->cur_size-1; i++)
	{
		for (int j = 0; j < book->cur_size - i - 1; j++)
		{
			if (strcmp(book->p[j].name, book->p[j + 1].name) > 0)
			{
				struct people_info tmp = book->p[j];
				book->p[j] = book->p[j + 1];
				book->p[j + 1] = tmp;
			}
		}
	}
	return 0;
}

10.将通讯录信息保存到文件中

void book_saveaddress(struct address_book *book)
{
	FILE* pout = fopen("address_book.dat", "wb");//打开文件,二进制写
	if (pout == NULL)
	{
		printf("打开失败\n");
		return;
	}

	for (int i = 0; i < book->cur_size; i++)
	{
		fwrite(book->p + i, sizeof(struct people_info), 1, pout);
	}
	printf("保存成功\n");
	fclose(pout);
	pout = 0;
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值