结构体应用案例_静态通讯录的实现过程

静态通讯录的实现过程


前言

前面的一篇博客介绍了结构体如何使用(包括:定义、赋值、初始化等操作)、结构体在内存中所占用空间大小以及定义结构体时的小技巧、位段等内容。
本篇来练习使用结构体变量来实现静态通讯录的过程。


一、要实现的功能

编写一个通讯录程序,能够存储100个人信息(包括:名字、年龄、性别、电话、地址),并且这个通讯录能够进行增、删、查、改、显示、排序的功能。
本次练习使用的是多文件编程的方式(就是把多个头文件和源文件组合在一起使用构成一个程序),这是C语言学习过程中的重难点。
其中C语言头文件包含各个函数的声明,学会了多文件的编程方式,又在学习的道路上迈进了一步。

二、通讯录的实现过程

1.分文件的规划

  • 创建一个头文件 contact.h ,头文件中包含结构体类型的声明定义和各个功能实现函数声明;
  • 创建一个.c文件 contact.c ,其中包含各个函数的定义和实现;
  • 创建一个.c文件 main.c ,主要功能是整个程序的实现逻辑和程序对各个函数的调用;

在这里插入图片描述

2.实现过程

  1. 在 mian.c 主函数中先搭建程序框架,对程序框架进行打桩
#include "contact.h"//为确保各个函数正常使用,先包含头文件 “contact.h”
void menu()
{	//选择菜单
	printf("********************************\n");
	printf("*****1、add       2、del   *****\n");
	printf("*****3、search    4、modify*****\n");
	printf("*****5、show      6、sort  *****\n");
	printf("*****0、exit      7、save  *****\n");
	printf("********************************\n");
}

enum Option	//使用枚举类型代替数字,使得后面的switch语句可读性更高,
{  EXIT ,ADD ,DEL ,SEARCH ,MODIFY ,SHOW ,SORT ,SAVE };

int main()
{
	Contact con;
	InitContact(&con);//对通讯录进行初始化
	int input;
	do
	{
		menu();
		printf("input your choice:");
		scanf("%d",&input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelConct(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case SAVE:
			break;
		case EXIT:
			DestroyContact(&con);
			printf("退出通讯录!\n");
			break;
		default:
			printf("选择错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}
  1. contact.h 头文件中包含结构体类型的定义和各个函数的声明,在其他.c文件中只需引用该头文件即可;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 1000

//每个人的信息
typedef struct PeoIfo	//定义结构体类型struct PeoIfo,
{						//使用typedef函数将struct PeoIfo重命名为 PeoIfo,后面使用PeoIfo代表struct PeoIfo
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}PeoIfo;

typedef struct Contact		//定义通讯录结构体类型 struct Contact
{
	PeoIfo  date[100];
	int sz;//表示通讯录中当前存放的人的信息个数
}Contact;

//增加一个人的信息
void AddContact(Contact * pc);

//显示信息
void ShowContact(Contact * pc);

//删除信息
void DelConct(Contact * pc);

//查找信息
void SearchContact(const Contact * pc);

//修改信息
void ModContact(Contact * pc);

//排序信息
void SortContact(Contact *pc);
  1. main.c 中定义了一个 名为con 的变量,表示通讯录存储的信息
Contact con;
InitContact(&con);//对通讯录进行初始化

在程序开始先将con初始化,将所有数据初始化为0;

void InitContact(Contact * pc)
{
	pc->sz = 0;
	memset(pc->data,0,sizeof(pc->data));
	printf("通讯录初始化完成!\n");
}
  1. 将con初始化完成之后,在contact.c 中编写AddContact( )函数,实现通讯录人数的增加
#include "contact.h"//在文件开头先引用contact.h头文件,确保各个函数可正常使用

void AddContact(struct Contact* pc) //增加通讯录信息
{
	if (pc->sz == MAX)		//判断通讯录的存贮人数是否达到最大值
	{						//人数达到最大值时,无法添加
		printf("通讯录已满,无法添加!\n");
	}
	else
	{
		printf("请输入名字:>");
		scanf("%s", pc->data[pc->sz].name);
		printf("请输入年龄:>");
		scanf("%d", &pc->data[pc->sz].age);
		printf("请输入性别:>");
		scanf("%s", pc->data[pc->sz].sex);
		printf("请输入电话:>");
		scanf("%s", pc->data[pc->sz].tel);
		printf("请输入住址:>");
		scanf("%s", pc->data[pc->sz].addr);
		pc->sz++;
		printf("添加成功!\n");
	}
}
  1. 为了方便后面的调试,先编写 ShowContact( ),来显示通讯录存储的信息
/*************************contact.c*************************/
//显示信息
void ShowContact(Contact* pc)
{
	if (0 == pc->sz)
	{
		printf("通讯录为空!\n无法打印!\n");
		return;
	}
	printf("name  age  sex   tele   address\n");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%s      %d    %s      %s      %s\n",
				pc->date[i].name, 
				pc->date[i].age, 
				pc->date[i].sex, 
				pc->date[i].tele,
				pc->date[i].addr);
	}
	printf("show finish!\n");
}
  1. 编写 DelConct( ),来删除通讯录存储的信息
/*************************contact.c*************************/
static int FindByName(Contact* pc, char* name)
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (!strcmp(pc->date[i].name, name))
			return i;//找到时返回下标的位置
	}
	return -1;//没找到时返回-1
}

在删除通讯录时,首先要对通讯录人员的名字进行查找.
当返回值为 -1 时,则说明通讯录中查不到此人
当返回值不为 -1 时,则说明通讯录中存在此人,返回的数值是联系人在通讯录中的位置

由于在后面的查找和修改功能功能中也需要用到该函数,为了避免代码的冗余,将此函数独立出来,方便代码的使用,代码更加简洁;

/*************************contact.c*************************/
//删除信息
void DelConct(Contact* pc)
{
	if (0 == pc->sz)
	{
		printf("通讯录为空!\n无删除信息!\n");
		return;
	}
	char name[NAME_MAX];
	printf("input your delete name:");
	scanf("%s",name);
	int pos =FindByName(pc, name);
	if (-1 == pos)
	{
		printf("你要删除的人不存在!\n");
	}
	else
	{
		int i = 0;
		for (i = pos; i < pc->sz - 1; i++)
			pc->date[pos] = pc->date[pos + 1];
		pc->sz--;
		printf("delete success!\n");
	}
}
  1. 编写 SearchContact( ),查找通讯录人员信息
/*************************contact.c*************************/
//查找信息
void SearchContact(const Contact* pc)
{
	char name[NAME_MAX];
	printf("input your srarch name:");
	scanf("%s",name);
	int pos = FindByName(pc,name);
	if (-1 == pos)
	{
		printf("no person!");
		return;
	}
	else
	{
		printf("%s      %d    %s      %s      %s\n",
			pc->date[pos].name,
			pc->date[pos].age,
			pc->date[pos].sex,
			pc->date[pos].tele,
			pc->date[pos].addr);
		printf("search message finish!\n");
	}
}
  1. 编写 ModContact( ),修改通讯录人员信息
/*************************contact.c*************************/
//修改信息
void ModContact(Contact* pc)
{
	char name[NAME_MAX];
	printf("input your modify name:");
	scanf("%s",name);
	int pos = FindByName(pc,name);
	if (-1 == pos)
	{
		printf("not find!\n ");
		return;
	}
	else
	{
		printf("input name:");
		scanf("%s", pc->date[pos].name);

		printf("input age:");
		scanf("%d", &pc->date[pos].age);

		printf("input sex:");
		scanf("%s", pc->date[pos].sex);

		printf("input tele:");
		scanf("%s", pc->date[pos].tele);

		printf("input address:");
		scanf("%s", pc->date[pos].addr);

		printf("modify sucess!\n");
	}
}
  1. 编写 SortContact( ),排序通讯录人员信息
    为了方便理解,使用冒泡排序的方法对通讯录进行排序,也可使用qsort函数来排序
/*************************contact.c*************************/
//排序信息
void SortContact(Contact* pc)
{
	if (0 == pc->sz)
	{
		printf("通讯录为空!\n无法排序!\n");
		return;
	}
	else
	{
		PeoIfo tmp;
		int i = 0;
		for ( i = 0; i < pc->sz; i++)
		{
			int j = 0;
			for (j = 0; j < pc->sz-i-1; j++)
			{
				if (strcmp(pc->date[j].name, pc->date[j + 1].name) > 0)
				{
					tmp = pc->date[j];
					pc->date[j] = pc->date[j + 1];
					pc->date[j + 1] = tmp;
				}
			}
		}
		printf("end of the sort!\nsucess\n");
	}
}

运行结果如下:
在这里插入图片描述

总结

以上就是静态结构体实现通讯录增、删、查、改等功能的方法,这种方法开辟的空间大小是固定的,无法调整,人数少时,浪费空间,人数多时,又无法再次开辟空间,所以后面会有动态开辟空间的版本。如果有表述不清或错误的地方,请大家多多指教^ _ ^!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值