目录
前言
学完了C语言的基础语法、数组、函数、指针、自定义类型、动态内存分配、文件操作等知识后算是掌握了一些C基础,这时候写写小项目倒是一个不错的巩固方法,本文就来分享一波用C语言简单实现三个版本的通讯录小程序(源码放在文末了)。
如果有尚未掌握的知识点最好先去学习了再来阅读本文,欢迎读者来我的C语言专栏参考参考。
由于笔者水平有限,难免存在纰漏,读者各取所需即可。
🧩1.静态版本
🧩需求
1.通讯录中能存放1000个人的信息
2.每个人的信息包括:姓名+年龄+性别+电话+地址
3.增删查改指定人的信息
4.能对通讯录信息排序
5.可以打印出所需信息
6.随时退出
🧩基本构架
用三个文件实现,一个是运行主函数的文件test.c,一个是存放通讯录具体功能实现函数的文件contact.c,另一个就是对应头文件contact.h。
因为每次操作完都需要不断刷新状态,所以用do while循环。
初始化一下菜单,定义menu函数,1-6分别对应增删查改和排序、打印,0则为退出。
void menu()
{
printf("************************************************\n");
printf("************* 1.add 2.del ***********\n");
printf("************* 3.search 4.modify ***********\n");
printf("************* 5.sort 6.print ***********\n");
printf("************* 0.exit ***********\n");
printf("************************************************\n");
printf("************************************************\n");
}
需要根据用户输入决定下一步操作,用input接收输入值,switch()对应7种情况。
定义了一个枚举,如果单单用case 1:之类的语句不清楚到底对应哪一个操作,而使用枚举常量就可以很清楚input的值到底对应哪一个操作了。
//防止忘记选项对应操作
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
PRINT
};
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf_s("%d",&input);
switch (input)
{
case EXIT:
break;
case ADD:
break;
case DEL:
break;
case SEARCH:
break;
case MODIFY:
break;
case PRINT:
break;
case SORT:
break;
default:
break;
}
} while (input);
system("pause");
}
要存放多个人的信息,并且每个人的信息都具有这五个属性,只是对应值各不相同,所以用结构体来封装变量,多人就用结构体数组。
用宏定义常量,方便修改。
为什么又用了一层结构体封装呢?为的是加上一个记录通讯录已存储联系人个数的变量,类似于索引。
对于结构类型定义,因为两个c文件都要使用对应结构,所以把它放在头文件contact.h中。
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
#define MAX 1000
//结构类型定义--个人信息
struct PeoInfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_TELE];
char addr[MAX_ADDR];
};
//通讯录结构
typedef struct Contact
{
struct PeoInfo data[MAX];//存放信息
int size;//记录当前通讯录中有效信息个数
}Contact;
然后根据功能需求设计函数,传结构体地址给每个功能函数(更高效)。
每个函数定义放在contact.c,声明放在contact.h。
🧩初始化函数
使用memset函数把整个结构初始化为0。
//初始化通讯录
void InitContact(Contact*pc)
{
//全部置零
memset(pc, 0, sizeof(pc));
}
🧩增加联系人函数
利用size作为索引,size就是目前已存入联系人个数和下一个要存储的联系人次序,比如size == 5代表现在将要录入的是第五个人的信息。结构数组data以size为下标,每增加一个人的信息后size++。
//增加联系人
void AddContact(Contact* pc)
{
//首先判断通讯录是否已满
if (pc->size == MAX)
{
printf("通讯录已满,无法再添加联系人!\n");
return;//无返回值但是可以用来结束函数
}
//增加一个人的信息
printf("请输入姓名:>");
scanf("%s",pc->data[pc->size].name);
getchar();
printf("请输入年龄:>");
scanf("%d",&(pc->data[pc->size].age));
printf("请输入性别:>");
scanf("%s", pc->data[pc->size].sex);
getchar();
printf("请输入电话:>");
scanf("%s", pc->data[pc->size].tele);
getchar();
printf("请输入地址:>");
scanf("%s", pc->data[pc->size].addr);
getchar();
pc->size++;//索引+1
printf("增加成功!\n");
}
🧩打印函数
为了先看看上一个函数录入信息效果如何,我们先写一下打印函数。
//打印联系人信息
void PrintContact(const Contact* pc)//常量指针防修改,只是打印操作并不需要改变原结构体
{
int i;
printf("%-15s\t%-5s\t%-5s\t%-12s\t%-20s\n","姓名","年龄","性别","电话","地址");
//打印所有联系人信息
for (i = 0; i < pc->size; i++)
{
printf("%-15s\t%-5