目录
注
要求
思路
前期的准备
1.设置类型存储通讯录内的数据
2.规划流程
实现
创建通讯录
初始化通讯录部分
用户选择部分
ADDContact函数部分(增加联系人)
PRINTContact函数部分(打印联系人信息)
FindByName函数部分(通过名字查找对象)
DELContact函数部分(删除联系人的信息)
SEARCHContact函数部分(查找指定联系人)
MODIFYContact函数部分(修改指定联系人)
SORTContact函数部分(排序联系人信息)
优化
1.如果出现重名的联系人该怎么办?
2.把数据移动到堆上
3.保存数据
源代码
test.c
contact.h
contact.c
本笔记参考B站up鹏哥C语言
1. 通讯录能够存放1000个人的信息
每个人的信息:
名字+年龄+性别+电话+地址
2. 增加人的信息
3. 删除指定人的信息
4. 修改指定人的信息
5. 查找指定人的信息
6. 排序通讯录的信息
在 contact.h 内部(此处代码仅供参考)
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
//类型的定义
typedef struct PeoInfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
通过定义常量的方式方便后期的调试。
typedef 定义函数,方便之后使用。
需要:
PeoInfo data[MAX];
int sz = 0;
但是在封装函数时会发现,如果使用sz计数,在传参时每次都要传入两个参数。这时候就会思考是否可以合并 PeoInfo 和 sz 这两个部分?
所以再封装一个结构体(MAX已提前定义):
//通讯录
typedef struct Contact
{
PeoInfo data[MAX];//存储添加进来的人的信息
int sz;//记录当前通讯录中有效信息的个数
}Contact;
此时也改变 test.c 内的结构体
Contact内部
认为,刚刚创建好的通讯录内部应该没有数据,所以通讯录内部的 结构体PeoInfo 和 整型sz 应该被初始化。
首先在 test.c 内部写入函数 InitContact
InitContact(&con);
//选择传入 con 的地址,可以改动 con 内部的内容
再在 contact.h 内部声明函数
void InitContact(Contact* pc);
最后在 contact.c 内部首先该函数(需要包含头文件 contact.h )
memset() - 内存设置函数,可以设置一块连续的内存。把指定空间的每个字节的内容初始化成指定的值(以字节为单位)。
void InitContact(Contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
//这种写法适用于较为复杂的初始化。
为什么可以直接使用 sizeof 计算字节个数?
分析:指针 pc->data 找到的是 data 这个数组的数组名,相当于将数组名单独放入 sizeof 内部,此时计算的是data这个数组的总大小。
通过枚举类型的使用方便分支语句的选择,逻辑清晰
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
PRI
};
可对应switch语句(用户选择)
switch (input)
{
case ADD://增加信息
break;
case DEL://删除信息
break;
case SEARCH://查找信息
break;
case MODIFY://修改信息
break;
case SORT://排序
break;
case PRINT://打印信息
break;
case EXIT://退出
break;
default:
break;
}
写入函数(test.c)→ 声明函数(contact.h) → 实现函数(contact.c)
分析:
由此可以发现新增加的联系人的信息应该被放入 data[sz] 的内部(放入后 sz++)。
另一方面,当通讯录满了之后就不可以放入数据了。
void ADDContact(Contact* pc)
{
//处理通讯录满了的情况
if (pc->sz == MAX)
{
printf("通讯录已满,无法添加\n");
return;
}
//增加一个人的信息
printf("请输入名字:");
scanf("%s", pc->data[pc->sz].name);//name是一个数组,故不用取地址
printf("请输入年龄:");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
首先在 test.c 内部写入函数 PRINTCotact
PRINTContact(&con);//传入地址
这里选择传入地址,不是为了更改 con 内部的内容,而是因为结构体传地址效率会更高。
声明函数(contact.h)
void PRINTContact(const Contact* pc);
因为并改变 con 内容,所以使用 const 修饰变量。
实现函数(contact.c)
要求
- 先打印标题
//先设计好要打印的标题格式(左对齐,长度不够的部分会用空格替代) printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
- 再打印数据
void PRINTContact(const Contact* pc)
{
int i = 0;
//打印标题
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
for ( i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
DELContact函数、SEARCHContact函数 和 MODIFYContact函数 都需要查找对象,所以统一使用函数FindByName进行查找。
需要:
该函数在 contact.c 内部被使用
int pos = FindByName(pc, name);//传入通讯录和要查找的对象的名字
所以也在 contact.c 内部创建:
static int FindByName(Contact* pc, char name[])//此处name是字符串
{
int i = 0;
for ( i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)//找到了
return i;
}
return -1;//找不到
}
依旧是遍历通过通讯录的方式找到目标。同时,因为其他源文件内不需要使用该函数,所以加上 static 保护函数。
写入函数(test.c)→ 声明函数(contact.h) → 实现函数(contact.c)
分析:
如果对象不存在,不用删除;
如果对象存在,执行删除操作。
要删除对象,只需要把要删除的对象后面的所有对象往前移动一个元素就可以了。如:
void DELContact(Contact* pc)
{
char name[MAX_NAME];
//检测通讯录是否为空
if (pc->sz == 0)
{
printf("通讯录为空,无需删除\n");
return;
}
printf("请输入要删除联系人的名字:");
scanf("%s", name);
//1.查找删除的对象
//判断:对象是否存在
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要删除的联系人不存在\n");
return;
}
//2.对象存在,执行删除操作
int i = 0;
for (i = pos; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
为什么此处的 for (i = pos; i < pc->sz - 1; i++) 内部是 sz - 1 呢?
但是当 i + 1 取到5时,访问的是这个数组的第6个元素,删除对象后元素都往前移动一个元素,本就无法访问下标为 i + 1 的那个元素。
写入函数(test.c)→ 声明函数(contact.h) → 实现函数(contact.c)
大部分代码和前面有重复,这里直接上代码
void SEARCHContact(Contact* pc)
{
char name[MAX_NAME] = { 0 };
printf("请输入要查找的联系人的名字:");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
else
{
printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",
pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
//打印部分和之前实现的PRINTContact相类似,但是没有循环
}
}
修改信息需要传输地址,在 test.c 中
MODIFYContact(&con);//传入地址
声明函数 contact.h
void MODIFYContact(Contact* pc);//与之前的函数类似
实现函数 contact.c
void MODIFYContact(Contact* pc)
{
char name[MAX_NAME] = { 0 };
printf("请输入要修改的联系人的名字:");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
else
{
printf("请输入名字:");
scanf("%s", pc->data[pos].name);//name是一个数组,故不用取地址
printf("请输入年龄:");
scanf("%d", &(pc->data[pos].age));
printf("请输入性别:");
scanf("%s", pc->data[pos].sex);
printf("请输入电话:");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
}
可以看出,这一部分代码和之前的代码有很多重复的部分。
写入函数(test.c)→ 声明函数(contact.h) → 实现函数(contact.c)
复习 strcmp函数 的返回值
int strcmp ( const char * str1, const char * str2 );
首先是检测通讯录是否为空。
其次,通过冒泡排序把姓名下ASCII值较小的联系人排到前面。
void SORTContact(Contact* pc)
{
if (pc->data[0].name == 0)
{
printf("通讯录为空,无法排序\n");
return;
}
int i = 0;
int j = 0;
for (i = 0; i < pc->sz; i++)
{
for (j = 0; j < pc->sz - 1; j++)
{
PeoInfo tmp[] = { 0 };
if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
{
tmp[0] = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = tmp[0];
}
}
}
printf("排序成功\n");
}
一种解决方法:
多列出一列行号,通过行号来区分不同的联系人。会需要处理重名的联系人的函数只有DELContact函数和MODIFYContact函数,这里只举例DELContact函数。
这就是第一个问题,如何改变变量pos?
pos = FindByName(pc, name, pos);
//……
pos++;
这里从函数FindByName入手,因为这样可以筛出每一个同名的联系人。
FindByName函数只改变了循环条件
for (; i < pc->sz; i++)
接下来要在SEARCHContact函数内部增加一行打印行号,同时改变循环结束的条件。
void SEARCHContact(Contact* pc, char name[])
{
int pos = 0;
pos = FindByName(pc, name, pos);
if (pos == -1)
{
//打印内容
return;
}
else
{
//打印内容
while (1)
{
//打印内容
pos++;
}
else
return;
}
}
}
改为else语句退出。
这里还有一个问题:如果用户只要求删除一个联系人,这种情况要怎么办?
上代码:
do { //…… pos = FindByName(pc, name, 0); if (pos == -1)//检测是否还有要求的联系人信息存在 { printf("修改完毕\n"); return; } printf("是否继续修改(Y/N):"); scanf("%c", &ch); getchar(); printf("退出成功\n"); } while (ch != 'N');
代码分为两部分:
1.检测联系人信息是否依然存在;
2.询问客户是否依旧修改。
为什么要把数据移动到堆上呢?
这就需要动态内存开辟:当需要的时候再增加空间,使得使用更加高效。
设定:
写成代码:
//通讯录 - 动态版本
typedef struct Contact
{
PeoInfo* data;//指向动态申请的空间,用来存放联系人信息
int sz;//记录当前通讯录中有效信息的个数
int capacity;//记录当前通讯录的最大容量
}Contact;
此时的 InitContact(&con); 只是创建了一个变量而已,其中的动态空间还没有开辟,其他参数也还没有。现在我们需:
为了方便,多定义两个常量:
#define DEFAULY_SZ 3 - 默认存储信息数量
#define INC_SZ 2 - 默认每次增加存储空间大小
初始化函数的修改:
void InitContact(Contact* pc)
{
pc->data = (PeoInfo*)malloc(DEFAULY_SZ*sizeof(PeoInfo));
if (pc->data == NULL)//如果空间开辟失败
{
perror("InitContact");
return;
}
pc->sz = 0;//初始化后默认为0
pc->capacity = DEFAULY_SZ;
}
初始化后,得到:
现在思考那些函数会涉及通讯录满的情况?
ADDContact函数
if (pc->sz == MAX)
{
printf("通讯录已满,无法添加\n");
return;
}
现在不是通讯录已满,而是到达最大存储容量时需要增加容量:
//考虑增容
if (pc->sz == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
if (ptr != NULL)
{
pc->data = ptr;
pc->capacity += INC_SZ;
}
else
{
perror("ADDContact");
printf("增加联系人失败\n");
return;
}
}
退出部分 - 增加:销毁通讯录(DESTORYConstact函数)
还是 写入函数(test.c)→ 声明函数(contact.h) → 实现函数(contact.c)三部分
contact.c 内部实现函数:
//销毁通讯录
void DESTORYConstact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
ps:就算没有销毁通讯录,在程序结束时,也会把空间还给操作系统。
首先,在退出时需要保存通讯录,于是在 test.c 中,用户选择退出时增加一个 SaveContact函数
case EXIT://退出
//保存信息到文件
SaveContact(&con);
//销毁通讯录
DESTORYConstact(&con);
printf("退出通讯录\n");
break;
在 contact.h 中声明:
void SaveContact(Contact* pc);
在 contact.c 中实现
在存储数据方面,一行一行把数据放入 test.dat 中。
值得注意的是这里使用的是 fwrite函数 - 按照二进制的方式写入数据。
void SaveContact(Contact* pc)
{
//以“写入”的方式代开文件
FILE* pf = fopen("contact.dat", "w");
if (pf == NULL)
{
perror("SaveContact");
return;
}
//写文件
int i = 0;
for (i = 0; i < pc->sz; i++)
{
fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
随便写点数据,看看结果:
因为是以二进制的方式写入,所以会存在看不懂的数据。
注意
现在还没有读取文件内部的信息,如果此时再次运行程序,会发现通讯录内部依旧是空的。所以增加写入数据的步骤(在初始化中)。
现在要求初始化 - InitContact函数 不只是创建通讯录,还应该可以加载文件(封装新的函数 - LoadContact)。
LoadContact函数可声明,也可以不声明,因为只在 contact.c 中使用。但为了后期调试方便,笔者还是进行了声明。
注意1 - fread函数的使用方式
在 fread函数 返回值的描述中,存在着这样一句话:返回成功读取的元素的总个数。
- 如果放入8个元素,而每次读取5个元素,则 fread函数 第一次会返回 5,第二次却会返回 3。
通过返回值,我们可以确定 fread函数 是否读完了所指向的文件。
注意2 - 如果通过读取数据在放入通讯录的方式,通讯录可能会出现溢出的现象。
所以要检测容量。发现增加容量被多次使用,考虑使用函数实现 - CheckContact。
void CheckContact(Contact* pc)
{
if (pc->sz == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
if (ptr != NULL)
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("增容成功\n");
}
else
{
perror("ADDContact");
printf("增加联系人失败\n");
return;
}
}
}
LoadContact函数
void LoadContact(Contact* pc)
{
//以“读”的方式打开文件
FILE* pf = fopen("contact.dat", "r");
if (pf == NULL)
{
perror("LoadContact");
return;
}
//读文件
PeoInfo tmp = { 0 };
while (fread(&tmp, sizeof(PeoInfo), 1, pf))
{
//增加容量
CheckContact(pc);
//放入
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
//1. 通讯录能够存放1000个人的信息
// 每个人的信息:
// 名字 + 年龄 + 性别 + 电话 + 地址
//2. 增加人的信息
//3. 删除指定人的信息
//4. 修改指定人的信息
//5. 查找指定人的信息
//6. 排序通讯录的信息
#include
#include"contact.h"
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");
}
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
PRINT
};
int main()
{
int input = 0;
char name[MAX_NAME] = { 0 };
//创建通讯录
Contact con;
//初始化通讯录的函数 - 静态版本
//InitContact(&con);//传入 con 的地址
//初始化通讯录 - 动态版本
InitContact(&con);
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case ADD://增加信息
ADDContact(&con);//传入地址
break;
case DEL://删除信息
DELContact(&con);
break;
case SEARCH://查找信息
printf("请输入要查找的联系人的名字:");
scanf("%s", name);
SEARCHContact(&con, name);
break;
case MODIFY://修改信息
printf("请输入要修改的联系人的名字:");
scanf("%s", name);
MODIFYContact(&con, name);
break;
case SORT://排序
SORTContact(&con);
break;
case PRINT://打印信息
PRINTContact(&con);
break;
case EXIT://退出
//保存信息到文件
SaveContact(&con);
//销毁通讯录
DESTORYConstact(&con);
printf("退出通讯录\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
#include
#include
#include
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
#define MAX 1000
#define DEFAULY_SZ 3
#define INC_SZ 2
//类型的定义
typedef struct PeoInfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
通讯录 - 静态版本
//typedef struct Contact
//{
// PeoInfo data[MAX];//存储添加进来的人的信息
// int sz;//记录当前通讯录中有效信息的个数
//}Contact;
//通讯录 - 动态版本
typedef struct Contact
{
PeoInfo* data;//指向动态申请的空间,用来存放联系人信息
int sz;//记录当前通讯录中有效信息的个数
int capacity;//记录当前通讯录的最大容量
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void ADDContact(Contact* pc);
//打印联系人信息
void PRINTContact(const Contact* pc);
//删除联系人的信息
void DELContact(Contact* pc);
//查找指定联系人
void SEARCHContact(Contact* pc, char name[]);
//修改指定联系人信息
void MODIFYContact(Contact* pc, char name[]);
//排序联系人信息
void SORTContact(Contact* pc);
//销毁通讯录
void DESTORYConstact(Contact* pc);
//保存通讯录信息到文件
void SaveContact(Contact* pc);
//加载文件内容到通讯录中
void LoadContact(Contact* pc);
//增加容量
void CheckContact(Contact* pc);
#define _CRT_SECURE_NO_WARNINGS
#include"contact.h"
初始化 - 静态版本
//void InitContact(Contact* pc)
//{
// pc->sz = 0;
//
// //memset() - 内存设置函数,可以设置一块连续的内存
// memset(pc->data, 0, sizeof(pc->data));
//}
//销毁通讯录
void DESTORYConstact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
//保存数据
void SaveContact(Contact* pc)
{
FILE* pf = fopen("contact.dat", "w");
if (pf == NULL)
{
perror("SaveContact");
return;
}
//写文件
int i = 0;
for (i = 0; i < pc->sz; i++)
{
fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
//加载数据
void LoadContact(Contact* pc)
{
//以“读”的方式打开文件
FILE* pf = fopen("contact.dat", "r");
if (pf == NULL)
{
perror("LoadContact");
return;
}
//读文件
PeoInfo tmp = { 0 };
while (fread(&tmp, sizeof(PeoInfo), 1, pf))
{
//增加容量
CheckContact(pc);
//放入
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
//初始化 - 动态版本
void InitContact(Contact* pc)
{
pc->data = (PeoInfo*)malloc(DEFAULY_SZ * sizeof(PeoInfo));
if (pc->data == NULL)//如果空间开辟失败
{
perror("InitContact");
return;
}
pc->sz = 0;//初始化后默认为0
pc->capacity = DEFAULY_SZ;
//加载文件
LoadContact(pc);
}
void CheckContact(Contact* pc)
{
if (pc->sz == pc->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
if (ptr != NULL)
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("增容成功\n");
}
else
{
perror("ADDContact");
printf("增加联系人失败\n");
return;
}
}
}
增加信息 - 静态版本
//void ADDContact(Contact* pc)
//{
// //处理通讯录满了的情况
// if (pc->sz == MAX)
// {
// printf("通讯录已满,无法添加\n");
// return;
// }
//
// //增加一个人的信息
// printf("请输入名字:");
// scanf("%s", pc->data[pc->sz].name);//name是一个数组,故不用取地址
// printf("请输入年龄:");
// scanf("%d", &(pc->data[pc->sz].age));
// printf("请输入性别:");
// scanf("%s", pc->data[pc->sz].sex);
// printf("请输入电话:");
// scanf("%s", pc->data[pc->sz].tele);
// printf("请输入地址:");
// scanf("%s", pc->data[pc->sz].addr);
//
// pc->sz++;
// printf("增加成功\n");
//}
//增加信息 - 动态版本
void ADDContact(Contact* pc)
{
//考虑增容
CheckContact(pc);
//增加一个人的信息
printf("请输入名字:");
scanf("%s", pc->data[pc->sz].name);//name是一个数组,故不用取地址
printf("请输入年龄:");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话:");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
//打印信息
void PRINTContact(const Contact* pc)
{
int i = 0;
//打印标题
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
for (i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
//寻找特定联系人
static int FindByName(Contact* pc, char name[], int i)
{
for (; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)//找到了
return i;
}
return -1;//找不到
}
//删除信息
void DELContact(Contact* pc)
{
char name[MAX_NAME];
int pos = 0;
char ch = 0;
//检测通讯录是否为空
if (pc->sz == 0)
{
printf("通讯录为空,无需删除\n");
return;
}
printf("请输入要删除联系人的名字:");
scanf("%s", name);
getchar();
//1.查找删除的对象
//判断:对象是否存在
pos = FindByName(pc, name, pos);
if (pos == -1)
{
printf("要删除的联系人不存在\n");
return;
}
//2.对象存在,执行删除操作
do
{
SEARCHContact(pc, name);
printf("请输入需要删除的联系人所在的行号:");
scanf("%d", &pos);
getchar();
int i = 0;
for (i = pos; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
pos = FindByName(pc, name, 0);
if (pos == -1)
{
printf("删除完毕\n");
return;
}
printf("是否继续删除(Y/N):");
scanf("%c", &ch);
getchar();
} while (ch != 'N');
if (pc->capacity > DEFAULY_SZ && pc->sz == pc->capacity - INC_SZ)
{
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity - INC_SZ) * sizeof(PeoInfo));
if (ptr != NULL)
{
pc->data = ptr;
pc->capacity -= INC_SZ;
printf("减容成功\n");
}
else
{
perror("DELCContact");
printf("删除联系人失败\n");
return;
}
}
printf("退出成功\n");
}
//查找指定联系人
void SEARCHContact(Contact* pc, char name[])
{
int pos = 0;
pos = FindByName(pc, name, pos);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
else
{
printf("%s\t%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "行号", "名字", "年龄", "性别", "电话", "地址");
while (1)
{
pos = FindByName(pc, name, pos);
if (pos != -1)
{
printf("%d\t%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",
pos,
pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
pos++;
}
else
return;
}
}
}
//修改指定联系人
void MODIFYContact(Contact* pc, char name[])
{
int pos = 0;
char ch = 0;
pos = FindByName(pc, name, pos);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
do
{
SEARCHContact(pc, name);
printf("请输入需要修改的联系人所在的行号:");
scanf("%d", &pos);
getchar();
printf("请输入名字:");
scanf("%s", pc->data[pos].name);//name是一个数组,故不用取地址
printf("请输入年龄:");
scanf("%d", &(pc->data[pos].age));
printf("请输入性别:");
scanf("%s", pc->data[pos].sex);
printf("请输入电话:");
scanf("%s", pc->data[pos].tele);
printf("请输入地址:");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
pos = FindByName(pc, name, 0);
if (pos == -1)
{
printf("修改完毕\n");
return;
}
getchar();
printf("是否继续修改(Y/N):");
scanf("%c", &ch);
getchar();
} while (ch != 'N');
printf("退出成功\n");
}
//排序信息
void SORTContact(Contact* pc)
{
if (pc->data[0].name == 0)
{
printf("通讯录为空,无法排序\n");
return;
}
int i = 0;
int j = 0;
for (i = 0; i < pc->sz; i++)
{
for (j = 0; j < pc->sz - 1; j++)
{
PeoInfo tmp[] = { 0 };
if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
{
tmp[0] = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = tmp[0];
}
}
}
printf("排序成功\n");
}