通讯录是一个可以很好锻炼我们对结构体的使用,加深对结构体的理解,在为以后学习数据结构打下结实的基础
这里我们想设计一个有添加联系人,删除联系人,查找联系人,修改联系人,展示联系人,排序
这几种功能的通讯录
目录
- 整体框架:
- 菜单:
- 创建通讯录:
- 初始化:
- 实现功能:
- 添加联系人:
- 删除联系人:
- find()的定义:
- 查找联系人:
- 修改联系人:
- 展示联系人:
- 排序:
- free空间:
- 源代码:
注意:我们按照三个区域划分
上图所示进行区域划分
- con.c用来放实现功能的函数
- con.h用来放头文件的声明
- test.c用来放整体框架
整体框架:
使用do...while
循环创建整体框架
整体框架在
test.c
中,这部分我们用来测试代码
int main()
{
int input = 0;
InitContact(&Con);
do
{
menu();
printf("请输入你的选项\n");
scanf("%d", &input);
switch (input)
{
case Add:
break;
case Del:
break;
case Search:
break;
case Modify:
break;
case Show:
break;
case Sort:
break;
case Exit:
printf("你已成功退出\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
-
注意:
-
我在使用case语句时没有用数字1,2,3…
而是使用了枚举常量,因为枚举常量会更方便程序员查看与操作要与菜单的数字相匹配,不然就会弄巧成拙
enum option
{
Exit,
Add,
Del,
Search,
Modify,
Show,
Sort,
};
菜单:
菜单的设计随心所欲,但要与枚举相匹配!
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 **\n");
printf("**************************\n");
printf("**************************\n");
}
创建通讯录:
此部分我们在
Contact.h
中创建,在另外两个里include
就可以
创建通讯录之前要先创建一个联系人的结构体:
假设我们的结构体包含了一个人的姓名,年龄,性别,电话,住址
那么久可以很好的进行创建:
typedef struct PeoInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
其中的常量用define
按需求进行定义,避免牵一发而动全身的情况
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
因为要动态通讯录
故设计通讯录时不能使用PeoInfo
创建数组的方式进行
可以创建结构体指针,指向动态内存分配的空间
typedef struct Contact
{
PeoInfo* Data;
int sz;
int capacity;
}Contact;
最后在test.c
文件中创建通讯录 Contact Con;
初始化:
在
con.c
中进行设计,不要忘记在test.c
中调用,在con.h
中声明
实现功能皆是如此设计,将不在赘述
void InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = START;
PeoInfo* p = (PeoInfo*)malloc(sizeof(PeoInfo) * START);
//start为初始化大小,define定义为3
if (p != NULL)
{
pc->Data = p;
}
else
{
perror("InitContact->malloc");
}
}
实现功能:
添加联系人:
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == pc->capacity)
{
PeoInfo* str = (PeoInfo*)realloc
(pc->Data, sizeof(PeoInfo) *
(pc->capacity + START_ADD));
//START_ADD为define定义,为一次扩容数量
if (str != NULL)
{
pc->Data = str;
pc->capacity = pc->capacity + START_ADD;
printf("增容成功\n");
}
else
{
perror("AddContact->realloc");
return;
}
}
printf("输入名字\n");
scanf("%s", pc->Data[pc->sz].name);
printf("输入年龄\n");
scanf("%d", &pc->Data[pc->sz].age);
printf("输入性别\n");
scanf("%s", &pc->Data[pc->sz].sex);
printf("输入电话\n");
scanf("%s", &pc->Data[pc->sz].tele);
printf("输入住址\n");
scanf("%s", &pc->Data[pc->sz].addr);
printf("输入成功\n");
pc->sz++;
}
删除联系人:
void DelContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无需删除\n");
return;
}
char name[NAME_MAX];
printf("输入你要删除人的姓名\n");
scanf("%s", name);
int ret = find(pc, name);
//我们这里使用了find函数
if (ret == -1)
{
printf("查无此人\n");
return;
}
for (int i = ret; i < pc->sz-1; i++)
{
pc->Data[i] = pc->Data[i + 1];
}
pc->sz--;
}
我们在输入查找姓名后要进行查找,因此我们设计了一个find
函数,方便别的函数的使用
find()的定义:
int find(Contact* pc, char name[])
{
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(name, pc->Data[i].name) == 0)
{
return i;
}
}
return -1;
}
查找联系人:
void SearchContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
char name[NAME_MAX];
printf("输入你要查找人的姓名\n");
scanf("%s", name);
int ret = find(pc, name);
if (ret == -1)
{
printf("查无此人\n");
return;
}
printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");
printf(" % -20s % -5d % -5s % -20s % -20s\n",
pc->Data[ret].name, pc->Data[ret].age, pc->Data[ret].sex, pc->Data[ret].tele, pc->Data[ret].addr);
}
修改联系人:
void ModifyContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
char name[NAME_MAX];
printf("输入你要修改人的姓名\n");
scanf("%s", name);
int ret = find(pc, name);
if (ret == -1)
{
printf("查无此人\n");
return;
}
printf("输入名字\n");
scanf("%s", pc->Data[ret].name);
printf("输入年龄\n");
scanf("%d", &pc->Data[ret].age);
printf("输入性别\n");
scanf("%s", &pc->Data[ret].sex);
printf("输入电话\n");
scanf("%s", &pc->Data[ret].tele);
printf("输入住址\n");
scanf("%s", &pc->Data[ret].addr);
printf("输入成功\n");
}
展示联系人:
void ShowContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无需打印\n");
return;
}
printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");
for (int i = 0; i < pc->sz; i++)
{
printf(" % -20s % -5d % -5s % -20s % -20s\n",
pc->Data[i].name, pc->Data[i].age, pc->Data[i].sex, pc->Data[i].tele, pc->Data[i].addr);
}
}
排序:
排序可以按照名字排,或是年龄,亦或是性别等等
这里我们只进行名字的排序,使用方法大同小异(快排)
int cmp_name(void* e1,void* e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
qsort(pc->Data, pc->sz, sizeof(PeoInfo), cmp_name);
}
free空间:
最后一步就是释放空间有始有终
void DestoryContact(Contact* pc)
{
free(pc);
}
源代码:
con.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
int find(Contact* pc, char name[])
{
for (int i = 0; i < pc->sz; i++)
{
if (strcmp(name, pc->Data[i].name) == 0)
{
return i;
}
}
return -1;
}
//void InitContact(Contact* pc)
//{
// assert(pc);
// pc->sz = 0;
// memset(pc->Data, 0, sizeof(pc->Data));
//}
void InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = START;
PeoInfo* p = (PeoInfo*)malloc(sizeof(PeoInfo) * START);
if (p != NULL)
{
pc->Data = p;
}
else
{
perror("InitContact->malloc");
}
}
void DestoryContact(Contact* pc)
{
free(pc);
}
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == pc->capacity)
{
PeoInfo* str = (PeoInfo*)realloc(pc->Data, sizeof(PeoInfo) * (pc->capacity + START_ADD));
if (str != NULL)
{
pc->Data = str;
pc->capacity = pc->capacity + 2;
printf("增容成功\n");
}
else
{
perror("AddContact->realloc");
return;
}
}
printf("输入名字\n");
scanf("%s", pc->Data[pc->sz].name);
printf("输入年龄\n");
scanf("%d", &pc->Data[pc->sz].age);
printf("输入性别\n");
scanf("%s", &pc->Data[pc->sz].sex);
printf("输入电话\n");
scanf("%s", &pc->Data[pc->sz].tele);
printf("输入住址\n");
scanf("%s", &pc->Data[pc->sz].addr);
printf("输入成功\n");
pc->sz++;
}
void ShowContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无需打印\n");
return;
}
printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");
for (int i = 0; i < pc->sz; i++)
{
printf(" % -20s % -5d % -5s % -20s % -20s\n",
pc->Data[i].name, pc->Data[i].age, pc->Data[i].sex, pc->Data[i].tele, pc->Data[i].addr);
}
}
void DelContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无需删除\n");
return;
}
char name[NAME_MAX];
printf("输入你要删除人的姓名\n");
scanf("%s", name);
int ret = find(pc, name);
if (ret == -1)
{
printf("查无此人\n");
return;
}
for (int i = ret; i < pc->sz-1; i++)
{
pc->Data[i] = pc->Data[i + 1];
}
pc->sz--;
}
void SearchContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
char name[NAME_MAX];
printf("输入你要查找人的姓名\n");
scanf("%s", name);
int ret = find(pc, name);
if (ret == -1)
{
printf("查无此人\n");
return;
}
printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");
printf(" % -20s % -5d % -5s % -20s % -20s\n",
pc->Data[ret].name, pc->Data[ret].age, pc->Data[ret].sex, pc->Data[ret].tele, pc->Data[ret].addr);
}
void ModifyContact(Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
char name[NAME_MAX];
printf("输入你要修改人的姓名\n");
scanf("%s", name);
int ret = find(pc, name);
if (ret == -1)
{
printf("查无此人\n");
return;
}
printf("输入名字\n");
scanf("%s", pc->Data[ret].name);
printf("输入年龄\n");
scanf("%d", &pc->Data[ret].age);
printf("输入性别\n");
scanf("%s", &pc->Data[ret].sex);
printf("输入电话\n");
scanf("%s", &pc->Data[ret].tele);
printf("输入住址\n");
scanf("%s", &pc->Data[ret].addr);
printf("输入成功\n");
}
int cmp_name(void* e1,void* e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
qsort(pc->Data, pc->sz, sizeof(PeoInfo), cmp_name);
}
con.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define START 3
#define START_ADD 2
typedef struct PeoInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
typedef struct Contact
{
PeoInfo* Data;
int sz;
int capacity;
}Contact;
//init
void InitContact(Contact* pc);
//add
void AddContact(Contact* pc);
//show
void ShowContact(Contact* pc);
//del
void DelContact(Contact* pc);
//search
void SearchContact(Contact* pc);
//modify
void ModifyContact(Contact* pc);
//sort
void SortContact(Contact* pc);
//destory
void DestoryContact(Contact* pc);
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
enum option
{
Exit,
Add,
Del,
Search,
Modify,
Show,
Sort,
};
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 **\n");
printf("**************************\n");
printf("**************************\n");
}
int main()
{
int input = 0;
Contact Con;
InitContact(&Con);
do
{
menu();
printf("请输入你的选项\n");
scanf("%d", &input);
switch (input)
{
case Add:
AddContact(&Con);
break;
case Del:
DelContact(&Con);
break;
case Search:
SearchContact(&Con);
break;
case Modify:
ModifyContact(&Con);
break;
case Show:
ShowContact(&Con);
break;
case Sort:
SortContact(&Con);
break;
case Exit:
DestoryContact(&Con);
printf("你已成功退出\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
欢迎纠错与讨论