丐版通讯录 基础版 丐版通讯录 静态版本 动态版本

「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

丐版通讯录

什么是丐版,就是能达到基本温饱,而微星的丐版是性价比最高的丐版,当然我是高配哈哈哈,这个通讯录就是微星丐版,一些基本用户功能是有的,甚至还多了功能,排序,用户级别的控制内存,当然有些用户友好功能没写(例如输错三次强制退出啊什么的),这些得高配再写,不然就不叫丐版了,我相信大多数人用了没有说不好的,那些高配的不要来装了(文件处理的哈哈哈),高配我们家也有,不过还没到发售时间。不吹了,吃饭了

通讯录他能干什么呢

1.存放1000个好友信息

那么一个人的好友信息包含什么东西呢

包含姓名,电话,性别,住址,年龄

2.还可以增加好友信息

3.删除指定名字的好友信息

4.查找好友信息

5.修改好友信息

6.打印好友信息

7.排序好友信息

静态版本

test.c

测试通讯录各个功能

main.c

首先就是主函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
c复制代码int main()
{
int input = 0;
//int size = 0;//用来记录通讯录有多少人的信息变量
//struct PeoInfo con[MAX];//存放1000个人的信息
/*为了下面函数不重复的写con,&size,就把他们集合在 一起了struct Contact*/
struct Contact con;//con就是通讯录,里面包含1000人信息的数组,和size
InitContact(&con);//初始化通讯录

do//首先让他循环起来
{
menu();//显示菜单
printf("请选择:>");
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:
QsortContact(&con);
break;
case EXIT:
printf("退出通讯录\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}

image-20210923080715957

菜单

1
2
3
4
5
6
7
8
9
c复制代码void menu()
{
printf("*******************************\n");
printf("***** 1.add 2.del ***\n");
printf("***** 3.search 4.modify ***\n");
printf("***** 5.show 6.short ***\n");
printf("***** 0.exit ***\n");
printf("*******************************\n");
}

这里的菜单序号要想到枚举

contact.c

通讯录的实现

初始化通讯录函数InitContact

1
2
3
4
5
6
7
c复制代码//初始化通讯录
void InitContact(struct Contact* ps)
{
assert(ps);
memset(ps->data, 0, sizeof(ps->data));//把data这个空间里全部设置为零
ps->size = 0;//让我们通讯录最初只有0个元素
}

添加通讯录函数AddContact

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
c复制代码//添加通讯录
void AddContact(struct Contact* ps)
{
assert(ps);
if (ps->size == MAX)//通讯录满了就添加不了信息
{
printf("通讯录已满无法添加\n");
}
else
{
printf("请输入名字:");
scanf("%s", ps->data[ps->size].name);//ps->data找到那个数组,
//ps->size找到放在[]里面就是 找到数组里面的某一个元素了,找到后再.name放到名字里面去
printf("请输入电话:");
scanf("%s", ps->data[ps->size].tele);
printf("请输入性别:");
scanf("%s", ps->data[ps->size].sex);
printf("请输入地址:");
scanf("%s", ps->data[ps->size].addr);
printf("请输入年龄:");
scanf("%d", &(ps->data[ps->size].age));//这里和上面不一样,因为上面是字符串,名字就是首地址
//而age是int 所以得取地址
//填好之后size得加加,因为size既是通讯录数组下标,也是人数的标准,添加一人就++;
ps->size++;
printf("添加成功\n");
}
}

显示通讯录函数ShowContact

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
c复制代码//不知道自己操作成没成功就show一下
//显示通讯录
void ShowContact(const struct Contact* ps)//这里为了安全,我们只是看一下里面的内容,不会修改,所以就const
{
assert(ps);
if (!ps->size)
{
printf("通讯录里面没有人,没什么好显示的:\n");
}
else
{
int i = 0;
printf("%-10s\t%-5s\t%-5s\t%-12s\t%-20s\n","名字","年龄","性别","电话","地址");
for (i = 0; i < ps->size; i++)
{
printf("%-10s\t%-5d\t%-5s\t%-12s\t%-20s\n",//为了对齐就把上面的格式拿下来,注意年龄的格式s变成了d
ps->data[i].name,
ps->data[i].age,
ps->data[i].sex,
ps->data[i].tele,
ps->data[i].addr);
}
}
}

image-20210923080753902

找人函数FindByName

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
c复制代码//只给本文件内函数用
static int FindByName(const struct Contact* ps, char name[MAX_NAME])
{
assert(ps);
int i = 0;
for (i = 0; i < ps->size; i++)
{
if (0 == strcmp(ps->data[i].name, name))
{
//break;//找到就跳出来
return i;
}
}
return -1;
}

删除指定联系人函数DelContact

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
c复制代码//删除指定的联系人
void DelContact(struct Contact* ps)
{
assert(ps);
if (ps->size == 0)
{
printf("通讯录为空,无法删除.\n");
return 0;
}
char name[MAX_NAME] = {0};
printf("请输入要删除人的姓名:");
scanf("%s", name);
int pos = FindByName(ps,name);//找到把下标拿出来,找不到返回-1
////查找要删除的人在什么位置
////高校做法也就是打工人做法,万物皆遍历
//int i = 0;
//for (i = 0; i < ps->size; i++)
//{
// if (0 == strcmp(ps->data[i].name, name))
// {
// break;//找到就跳出来
// }
//}
//然后再删除
if (pos == -1)//说明他遍历完了也没找到那个名字,也就是说是不存在的
{
printf("要删除的人不存在:");
}
else
{
//删除数据
int j = 0;
for (int j = pos; j < ps->size; j++)
{
ps->data[j] = ps->data[j + 1];//需要删除的数据后面的来补删除数据的空间
}
ps->size--;//删除了,人就减一
printf("删除成功");
}
}

查找联系人函数SearchContact

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
c复制代码//查找联系人  我就是查找不修改,所以要const
void SearchContact(const struct Contact* ps)
{
assert(ps);
char name[MAX_NAME] = { 0 };
printf("请输入 需要查找人的名字:");
scanf("%s",name);
////查找的过程和删除的 查找过程一样 ,这时候再写一样的话就会出现代码冗余,所以我们需要写一个通用的查找功能
//int i = 0;
//for (i = 0; i < ps->size; i++)
//{
// if (0 == strcmp(ps->data[i].name, name))
// {
// break;//找到就跳出来
// }
//}
int pos = FindByName(ps, name);
if (pos == -1)//说明他遍历完了也没找到那个名字,也就是说是不存在的
{
printf("要查找的人不存在:");
}
else
{
//找到就打印
printf("%-10s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%-10s\t%-5d\t%-5s\t%-12s\t%-20s\n",//为了对齐就把上面的格式拿下来,注意年龄的格式s变成了d
ps->data[pos].name,
ps->data[pos].age,
ps->data[pos].sex,
ps->data[pos].tele,
ps->data[pos].addr);
}
}

修改指定联系人函数ModifyContact

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
c复制代码//修改指定联系人
void ModifyContact( struct Contact* ps)
{
assert(ps);
char name[MAX_NAME] = { 0 };
printf("请输入要修改人的名字:");
scanf("%s",name);
int pos = FindByName(ps,name);
if (pos == -1)
{
printf("没有修改人的名字\n");
}
else
{
printf("请输入名字:");
scanf("%s", ps->data[pos].name);//ps->data找到那个数组,
//ps->size找到放在[]里面就是 找到数组里面的某一个元素了,找到后再.name放到名字里面去
printf("请输入电话:");
scanf("%s", ps->data[pos].tele);
printf("请输入性别:");
scanf("%s", ps->data[pos].sex);
printf("请输入地址:");
scanf("%s", ps->data[pos].addr);
printf("请输入年龄:");
scanf("%d", &(ps->data[pos].age));

printf("修改完成:");
}
}

快排通讯录函数(年龄排序)QsortContact

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
c复制代码//由于中文名在内存中存储方式的问题。所以我们选择年龄排序
static int cmp_peoinfo_age(const void* e1, const void* e2)
{
return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
//快排通讯录
void QsortContact(struct Contact* ps)
{
assert(ps);
if (ps->size < 2)
{
printf("所需排序人少于2人,无需排序");
return 0;
}
qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_peoinfo_age);
}

contact.h

通讯录的声明

创建通讯录的一些宏

1
2
3
4
5
c复制代码#define MAX                1000
#define MAX_NAME 20 //为了好修改直接宏定义
#define MAX_TELE 12
#define MAX_SEX 5
#define MAX_ADDR 30

选项(方便删改)

1
2
3
4
5
6
7
8
9
10
11
c复制代码//选项,因为每次输入数字的话还要看看数字的意思,会很麻烦,所以枚举
enum Option
{
EXIT, //0退出
ADD, //1添加
DEL, //2删除
SEARCH, //3查找
MODIFY, //4修改
SHOW, //5查看
SORT //6排序
};

image-20210923080632563

用户信息结构体

1
2
3
4
5
6
7
8
9
10
c复制代码//创建用户信息类型包含姓名,电话,性别,住址,年龄
//然后通讯录就是1000个用户组成的,创建一个数组就好
struct PeoInfo
{
char name[MAX_NAME];
char tele[MAX_TELE];
char sex[MAX_SEX];
char addr[MAX_ADDR];
int age;
};

通讯录结构体

1
2
3
4
5
6
c复制代码//通讯录类型,里面是通讯录信息
struct Contact
{
struct PeoInfo data[MAX];//存放1000个信息
int size;//记录当前个数
};

声明函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
c复制代码//声明函数

//初始化通讯录
void InitContact(struct Contact* ps);
//添加通讯录
void AddContact(struct Contact* ps);
//显示通讯录
void ShowContact(const struct Contact* ps);
/*为了通过name查找人,这里用函数写是因为之后删除,查询,修改等都
需要用到find这个功能,写在函数里面的话很多都是重复的会显的很冗余
int FindByName(struct Contact* ps, char name[MAX_NAME]); 这个函数声明就不要声明了,不需要给用户,
我们给用户的功能就那菜单里的那几个,这个函数是为了服务查询名字而出现的,不是为了用户出现,所以不
需要暴露给用户,而且还要加上static,不让其他人用,只给文件 内函数用*/
//删除指定的联系人
void DelContact(struct Contact* ps);
//查找联系人
void SearchContact(const struct Contact* ps);
//修改指定联系人
void ModifyContact(struct Contact* ps);
//排序联系人
void QsortContact(struct Contact* ps);

动态版本

比其他丐版的优势

contact.h

改一:通讯录结构体

1
2
3
4
5
6
7
8
c复制代码//动态版本
//通讯录类型,里面是通讯录信息
struct Contact
{
struct PeoInfo* data;//用指针来维护用户空间
int sz; //记录通讯录当前的元素个数
int capacity ; //通讯录最大容量
};

image-20210923082936339

contact.c

改二:初始化通讯录函数InitContact

1
2
3
4
5
6
7
8
9
10
c复制代码//动态版本
//初始化通讯录
//刚开始的时候通讯录结构体就给了指针但没有指向空间,所以我们得初始化给他
//只有三个人的元素,不够再加呗
void InitContact(struct Contact* ps)
{
ps->sz = 0;//此时有效元素是0
ps->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo));//先给3个元素
ps->capacity = DEFAULT_SZ;
}

image-20210923084747640

改三:增加通讯录函数AddContact

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
c复制代码//动态版本
// 添加通讯录
void AddContact( struct Contact* ps)
{
//当有效元素个数和通讯录最大容量相等时就要扩容了
if (ps->sz == ps->capacity)
{
struct PeoInfo* ptr = (struct PeoInfo*)realloc(ps->data, (ps->capacity + 2) * sizeof(struct PeoInfo));//增加两个元素
if (ptr == NULL)
{
printf("扩容失败\n");
return 0;
}
else
{
ps->data = ptr;//ptr不为空就交给data维护
ps->capacity += 2;//这个不要忘了总容量也要加
printf("扩容成功\n");
}
}
//然后再增加新的信息
printf("请输入名字:");
scanf("%s", ps->data[ps->sz].name);//ps->data找到那个数组,
//ps->size找到放在[]里面就是 找到数组里面的某一个元素了,找到后再.name放到名字里面去
printf("请输入电话:");
scanf("%s", ps->data[ps->sz].tele);
printf("请输入性别:");
scanf("%s", ps->data[ps->sz].sex);
printf("请输入地址:");
scanf("%s", ps->data[ps->sz].addr);
printf("请输入年龄:");
scanf("%d", &(ps->data[ps->sz].age));//这里和上面不一样,因为上面是字符串,名字就是首地址
//而age是int 所以得取地址
//填好之后sz得加加,因为sz既是通讯录数组下标,也是人数的标准,添加一人就++;
(ps->sz)++;
printf("添加成功\n");
}

注意我们在扩容却没有释放,那我们什么时候释放呢,是不是只有程序结束也就是程序退出的时候释放,也就是Exit的时候

所以我们得写个销毁通讯录的函数

添加四:销毁通讯录函数DestroyContact

1
2
3
4
5
6
7
8
9
10
c复制代码//销毁通讯录
void DestroyContact(struct Contact* ps)
{
//释放人员信息空间
free(ps->data);
ps->data = NULL;
//指向的数组都没了,所以sz,capacity也没用了
ps->sz = 0;
ps->capacity = 0;
}

完整代码

test.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
c复制代码#define _CRT_SECURE_NO_WARNINGS 1

#include"contact.h"


void menu()
{
printf("*******************************\n");
printf("***** 1.add 2.del ***\n");
printf("***** 3.search 4.modify ***\n");
printf("***** 5.show 6.short ***\n");
printf("***** 0.exit ***\n");
printf("*******************************\n");
}

int main()
{
int input = 0;
//int size = 0;//用来记录通讯录有多少人的信息变量
//struct PeoInfo con[MAX];//存放1000个人的信息
/*为了下面函数不重复的写con,&size,就把他们集合在 一起了struct Contact*/
struct Contact con;//con就是通讯录,里面包含1000人信息的数组,和size
InitContact(&con);//初始化通讯录

do//首先让他循环起来
{
menu();//显示菜单
printf("请选择:>");
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:
QsortContact(&con);
break;
case EXIT:
DestroyContact(&con);
printf("退出通讯录\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}

contact.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
c复制代码#define _CRT_SECURE_NO_WARNINGS 1

#include"contact.h"


////静态版本
////初始化通讯录
//void InitContact(struct Contact* ps)
//{
// assert(ps);
// memset(ps->data, 0, sizeof(ps->data));//把data这个空间里全部设置为零
// ps->size = 0;//让我们通讯录最初只有0个元素
//}

//动态版本
//初始化通讯录
//刚开始的时候通讯录结构体就给了指针但没有指向空间,所以我们得初始化给他
//只有三个人的元素,不够再加呗
void InitContact(struct Contact* ps)
{
ps->sz = 0;//此时有效元素是0
ps->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo));//先给3个元素
ps->capacity = DEFAULT_SZ;
}

////静态版本
////添加通讯录
//void AddContact(struct Contact* ps)
//{
// assert(ps);
// if (ps->size == MAX)//通讯录满了就添加不了信息
// {
// printf("通讯录已满无法添加\n");
// }
// else
// {
// printf("请输入名字:");
// scanf("%s", ps->data[ps->size].name);//ps->data找到那个数组,
// //ps->size找到放在[]里面就是 找到数组里面的某一个元素了,找到后再.name放到名字里面去
// printf("请输入电话:");
// scanf("%s", ps->data[ps->size].tele);
// printf("请输入性别:");
// scanf("%s", ps->data[ps->size].sex);
// printf("请输入地址:");
// scanf("%s", ps->data[ps->size].addr);
// printf("请输入年龄:");
// scanf("%d", &(ps->data[ps->size].age));//这里和上面不一样,因为上面是字符串,名字就是首地址
// //而age是int 所以得取地址
// //填好之后size得加加,因为size既是通讯录数组下标,也是人数的标准,添加一人就++;
// ps->size++;
// printf("添加成功\n");
// }
//}

//动态版本
// 添加通讯录
void AddContact( struct Contact* ps)
{
//当有效元素个数和通讯录最大容量相等时就要扩容了
if (ps->sz == ps->capacity)
{
struct PeoInfo* ptr = (struct PeoInfo*)realloc(ps->data, (ps->capacity + 2) * sizeof(struct PeoInfo));//增加两个元素
if (ptr == NULL)
{
printf("扩容失败\n");
return 0;
}
else
{
ps->data = ptr;//ptr不为空就交给data维护
ps->capacity += 2;//这个不要忘了总容量也要加
printf("扩容成功\n");
}
}
//然后再增加新的信息
printf("请输入名字:");
scanf("%s", ps->data[ps->sz].name);//ps->data找到那个数组,
//ps->size找到放在[]里面就是 找到数组里面的某一个元素了,找到后再.name放到名字里面去
printf("请输入电话:");
scanf("%s", ps->data[ps->sz].tele);
printf("请输入性别:");
scanf("%s", ps->data[ps->sz].sex);
printf("请输入地址:");
scanf("%s", ps->data[ps->sz].addr);
printf("请输入年龄:");
scanf("%d", &(ps->data[ps->sz].age));//这里和上面不一样,因为上面是字符串,名字就是首地址
//而age是int 所以得取地址
//填好之后sz得加加,因为sz既是通讯录数组下标,也是人数的标准,添加一人就++;
(ps->sz)++;
printf("添加成功\n");
}

//销毁通讯录
void DestroyContact(struct Contact* ps)
{
//释放人员信息空间
free(ps->data);
ps->data = NULL;
//指向的数组都没了,所以sz,capacity也没用了
ps->sz = 0;
ps->capacity = 0;
}



//不知道自己操作成没成功就show一下
//显示通讯录
void ShowContact(const struct Contact* ps)//这里为了安全,我们只是看一下里面的内容,不会修改,所以就const
{
assert(ps);
if (!ps->sz)
{
printf("通讯录里面没有人,没什么好显示的:\n");
}
else
{
int i = 0;
printf("%-10s\t%-5s\t%-5s\t%-12s\t%-20s\n","名字","年龄","性别","电话","地址");
for (i = 0; i < ps->sz; i++)
{
printf("%-10s\t%-5d\t%-5s\t%-12s\t%-20s\n",//为了对齐就把上面的格式拿下来,注意年龄的格式s变成了d
ps->data[i].name,
ps->data[i].age,
ps->data[i].sex,
ps->data[i].tele,
ps->data[i].addr);
}
}
}
//只给本文件内函数用
static int FindByName(const struct Contact* ps, char name[MAX_NAME])
{
assert(ps);
int i = 0;
for (i = 0; i < ps->sz; i++)
{
if (0 == strcmp(ps->data[i].name, name))
{
//break;//找到就跳出来
return i;
}
}
return -1;
}

//删除指定的联系人
void DelContact(struct Contact* ps)
{
assert(ps);
if (ps->sz == 0)
{
printf("通讯录为空,无法删除.\n");
return 0;
}
char name[MAX_NAME] = {0};
printf("请输入要删除人的姓名:");
scanf("%s", name);
int pos = FindByName(ps,name);//找到把下标拿出来,找不到返回-1
////查找要删除的人在什么位置
////高校做法也就是打工人做法,万物皆遍历
//int i = 0;
//for (i = 0; i < ps->size; i++)
//{
// if (0 == strcmp(ps->data[i].name, name))
// {
// break;//找到就跳出来
// }
//}
//然后再删除
if (pos == -1)//说明他遍历完了也没找到那个名字,也就是说是不存在的
{
printf("要删除的人不存在:");
}
else
{
//删除数据
int j = 0;
for (int j = pos; j < ps->sz; j++)
{
ps->data[j] = ps->data[j + 1];//需要删除的数据后面的来补删除数据的空间
}
ps->sz--;//删除了,人就减一
printf("删除成功");
}
}
//查找联系人 我就是查找不修改,所以要const
void SearchContact(const struct Contact* ps)
{
assert(ps);
char name[MAX_NAME] = { 0 };
printf("请输入 需要查找人的名字:");
scanf("%s",name);
////查找的过程和删除的 查找过程一样 ,这时候再写一样的话就会出现代码冗余,所以我们需要写一个通用的查找功能
//int i = 0;
//for (i = 0; i < ps->size; i++)
//{
// if (0 == strcmp(ps->data[i].name, name))
// {
// break;//找到就跳出来
// }
//}
int pos = FindByName(ps, name);
if (pos == -1)//说明他遍历完了也没找到那个名字,也就是说是不存在的
{
printf("要查找的人不存在:");
}
else
{
//找到就打印
printf("%-10s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%-10s\t%-5d\t%-5s\t%-12s\t%-20s\n",//为了对齐就把上面的格式拿下来,注意年龄的格式s变成了d
ps->data[pos].name,
ps->data[pos].age,
ps->data[pos].sex,
ps->data[pos].tele,
ps->data[pos].addr);
}
}

//修改指定联系人
void ModifyContact( struct Contact* ps)
{
assert(ps);
char name[MAX_NAME] = { 0 };
printf("请输入要修改人的名字:");
scanf("%s",name);
int pos = FindByName(ps,name);
if (pos == -1)
{
printf("没有修改人的名字\n");
}
else
{
printf("请输入名字:");
scanf("%s", ps->data[pos].name);//ps->data找到那个数组,
//ps->size找到放在[]里面就是 找到数组里面的某一个元素了,找到后再.name放到名字里面去
printf("请输入电话:");
scanf("%s", ps->data[pos].tele);
printf("请输入性别:");
scanf("%s", ps->data[pos].sex);
printf("请输入地址:");
scanf("%s", ps->data[pos].addr);
printf("请输入年龄:");
scanf("%d", &(ps->data[pos].age));

printf("修改完成:");
}
}
//由于中文名在内存中存储方式的问题。所以我们选择年龄排序
static int cmp_peoinfo_age(const void* e1, const void* e2)
{
return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
//快排通讯录
void QsortContact(struct Contact* ps)
{
assert(ps);
if (ps->sz < 2)
{
printf("所需排序人少于2人,无需排序");
return 0;
}
qsort(ps->data, ps->sz, sizeof(ps->data[0]), cmp_peoinfo_age);
}

contact.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
c复制代码#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>

#define MAX 1000
#define MAX_NAME 20 //为了好修改直接宏定义
#define MAX_TELE 12
#define MAX_SEX 5
#define MAX_ADDR 30
#define DEFAULT_SZ 3

//选项,因为每次输入数字的话还要看看数字的意思,会很麻烦,所以枚举
enum Option
{
EXIT, //0退出
ADD, //1添加
DEL, //2删除
SEARCH, //3查找
MODIFY, //4修改
SHOW, //5查看
SORT //6排序
};

//创建用户信息类型包含姓名,电话,性别,住址,年龄
//然后通讯录就是1000个用户组成的,创建一个数组就好
struct PeoInfo
{
char name[MAX_NAME];
char tele[MAX_TELE];
char sex[MAX_SEX];
char addr[MAX_ADDR];
int age;
};
////静态版本
////通讯录类型,里面是通讯录信息
//struct Contact
//{
// struct PeoInfo data[MAX];//存放1000个信息
// int size;//记录当前个数
//};

//动态版本
//通讯录类型,里面是通讯录信息
struct Contact
{
struct PeoInfo* data;//用指针来维护用户空间
int sz; //记录通讯录当前的元素个数
int capacity ; //通讯录最大容量
};

//声明函数

//初始化通讯录
void InitContact(struct Contact* ps);
//添加通讯录
void AddContact(struct Contact* ps);
//显示通讯录
void ShowContact(const struct Contact* ps);
/*为了通过name查找人,这里用函数写是因为之后删除,查询,修改等都
需要用到find这个功能,写在函数里面的话很多都是重复的会显的很冗余
int FindByName(struct Contact* ps, char name[MAX_NAME]); 这个函数声明就不要声明了,不需要给用户,
我们给用户的功能就那菜单里的那几个,这个函数是为了服务查询名字而出现的,不是为了用户出现,所以不
需要暴露给用户,而且还要加上static,不让其他人用,只给文件 内函数用*/
//删除指定的联系人
void DelContact(struct Contact* ps);
//查找联系人
void SearchContact(const struct Contact* ps);
//修改指定联系人
void ModifyContact(struct Contact* ps);
//排序联系人
void QsortContact(struct Contact* ps);
//销毁通讯录函数
void DestroyContact(struct Contact* ps);

跑图

image-20210923094800813

image-20210923101309076

image-20210923101705704

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%