Fork me on GitHub

【C语言】动态顺序表 + 文件存储 = 通讯录


前言

在前面曾用静态、动态顺序表两种方式实现通讯录,但每次运行程序我们都得重新输入,之前输入的成员信息并不会保存,而现实中,通讯录里的信息创建后是永久保存的,除非你删除它,今天我们就来模拟一下如何将数据存储在文件中,当下一次运行时加载一下即可,这种做法更贴合实际。

程序中会用到与文件操作相关的函数,提前介绍一下:

  • fopen 它的函数原型为:FILEfopen(const char filename,const char *mode) ,filename:创建文件的名字;mode:允许进入文件的类型;简单来说这个文件的作用就是打开一个文件流;与fclose:关闭文件流配套使用.
  • perror: 它的函数原型为:void perror(const char * string) ,这是一种报告文件错误的函数;后面包括一个分号和一个空格,然后打印出一条用于解释errno当前错误代码的信息;
  • fwrite: 它的函数原型为:size_t fwrite(const void buffer,size_t size,size_t count,FILEstream) ,buffer:数据写入的体格缓冲区;

通讯录简要功能:

  • 初始化通讯录
  • 添加联系人
  • 查找联系人
  • 删除联系人
  • 修改联系人
  • 按姓名排序
  • 清空联系人
  • 联系人列表
  • 检查容量
  • 加载文件
  • 保存文件
  • 销毁通讯录
  • 退出

参考代码:

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
76
77
78
79
/***********************************************************
* 程序名称:通讯录(静态顺序表) *
* 编译环境:VS2013 *
* 编制日期:2018.5.29 *
* -----by Hunter *
***********************************************************/


#ifndef __CONTACT_H__
#define __CONTACT_H__

#include <stdio.h>
#include <Windows.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

enum OPPTION
{
EXIT,
ADD,
SEARCH,
DEIETE,
MODIFY,
SORT,
SHOW,
EMPTY
};

typedef char datatype;

#define MAX_NAME 10
#define MAX_SEX 5
#define MAX_TEL 11
#define MAX_ADDR 30
#define MAX_SIZE 1000

#define FILE_NAME "contact.dat"

typedef struct PeoInfo
{
datatype Name[MAX_NAME];
datatype Sex[MAX_SEX];
int age;
datatype Tel[MAX_TEL];
datatype Addr[MAX_ADDR];
}PeoInfo, *pPeoInfo;

typedef struct Contact
{
pPeoInfo data;
int size;
int capacity;
}Contact, *pContact;

//初始化通讯录
void InitContact(pContact pc);
//添加联系人
void AddContact(pContact pc);
//删除联系人
void DeleteContact(pContact pc);
//查找联系人
int SearchContact(pContact pc);
//修改联系人
void ModifyContact(pContact pc);
//按姓排序
void SortContact(pContact pc);
//列表联系人
void ShowContact(pContact pc);
//清空联系人
void EmptyContact(pContact pc);
//销毁
void DestoryContact(pContact pc);
//加载
void LoadContact(pContact pc);
//保存
void SaveContact(pContact pc);

#endif //__CONTACT_H__

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
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"


//检查扩容
void CheckCapacity(pContact pc)
{
assert(pc);
pPeoInfo *p = NULL;
if (pc->size == pc->capacity)
{
p = (pPeoInfo)realloc(pc->data, (pc->capacity + 2)*sizeof(PeoInfo));
if (p != NULL)
{
pc->data = p;

}
else
{
printf("\t\t\t增容失败");
exit(EXIT_FAILURE);
}

pc->capacity += 2;
printf("\t\t\t增容成功\n");
}
}
//加载
void LoadContact(pContact pc)
{
int i = 0;
FILE* pfRead = fopen("contact.dat", "r");
PeoInfo tmp = { 0 }; //创建临时变量保存每次读取的信息
assert(pc);
if (pfRead == NULL)
{
perror("the file to read");
exit(EXIT_FAILURE);
}

while (fread(&tmp, sizeof(PeoInfo), 1, pfRead))
{
CheckCapacity(pc);
pc->data[i] = tmp;
i++;
pc->size++;
}

fclose(pfRead);
pfRead = NULL;

}
//保存
void SaveContact(pContact pc)
{
assert(pc);
FILE *pfwrite = fopen("contact.dat", "w");
int i = 0;
if (pfwrite == NULL)
{
perror("the file to write");
exit(EXIT_FAILURE);
}
for (i = 0; i<pc->size; i++)
{
fwrite(pc->data+ i, sizeof(PeoInfo), 1, pfwrite);
}
fclose(pfwrite);
pfwrite = NULL;

}

//初始化通讯录
void InitContact(pContact pc)
{
assert(pc);
pc->size = 0;
pc->capacity = 3;
pc->data = (pPeoInfo)malloc((pc->capacity)*sizeof(PeoInfo));
if (pc->data == NULL)
{
printf("\t\t\t内存分配失败");
exit(EXIT_FAILURE);
}
memset(pc->data, 0, sizeof(pc->data));
LoadContact(pc);
}

//添加联系人
void AddContact(pContact pc)
{
assert(pc);
if (pc->size == MAX_SIZE)
{
printf("\t\t\t空间不足");
return;
}
CheckCapacity(pc);
printf("\t\t\t请输入姓名:>");
scanf("%s", pc->data[pc->size].Name);
printf("\t\t\t请输入性别:>");
scanf("%s", pc->data[pc->size].Sex);
printf("\t\t\t请输入年龄:>");
scanf("%d", &pc->data[pc->size].age);
printf("\t\t\t请输入电话号:>");
scanf("%s", pc->data[pc->size].Tel);
printf("\t\t\t请输入地址:>");
scanf("%s", pc->data[pc->size].Addr);
pc->size++;
printf("\t\t\t添加成功\n");
}
//查找联系人
int SearchContact(pContact pc)
{
char name[MAX_NAME];
int i = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无此联系人\n");
return -1;
}
printf("\t\t\t");
scanf("%s", name);
printf("\t\t\tName\tSex\tAge\tTel\t\tAddr\n");
for (i = 0; i < pc->size; i++)
{
if (0 == strcmp(pc->data[i].Name, name))
{

printf("\t\t\t%-5s\t%-5s\t%-5d\t%-12s\t%-15s\n",
pc->data[i].Name,
pc->data[i].Sex,
pc->data[i].age,
pc->data[i].Tel,
pc->data[i].Addr);
return i;
}
}
printf("\t\t\t无此联系人\n");
return -1;

}
//删除联系人
void DeleteContact(pContact pc)
{
int i = 0;
int num = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无联系人\n");
return;
}
num = SearchContact(pc);
if (num != -1)
{
int n = 0;
printf("\t\t\t确定删除? 1.yes, 2.no:>");
printf("\t\t\t");
scanf("%d", &n);
if (1 == n)
{
for (i = num; i < (pc->size) - 1; i++)
{
pc->data[i] = pc->data[i + 1];

}
pc->size--;
printf("\t\t\t删除成功\n");
}
else
{
return;
}
}

}

//交换
void Swap(pPeoInfo *a, pPeoInfo *b)
{
pPeoInfo *Tmp;
Tmp = *a;
*a = *b;
*b = Tmp;

}


//修改联系人
void ModifyContact(pContact pc)
{
int modify = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无联系人\n");
return;
}
modify = SearchContact(pc);
if (modify != -1)
{
int n = 0;
printf("\t\t\t确认修改?1.yes 2.no:>");
printf("\t\t\t");
scanf("%d", &n);
if (1 == n)
{
printf("\t\t\t请输入姓名:>");
scanf("%s", pc->data[modify].Name);
printf("\t\t\t请输入性别:>");
scanf("%s", pc->data[modify].Sex);
printf("\t\t\t请输入年龄:>");
scanf("%d", &pc->data[modify].age);
printf("\t\t\t请输入电话号:>");
scanf("%s", pc->data[modify].Tel);
printf("\t\t\t请输入地址:>");
scanf("%s", pc->data[modify].Addr);
printf("\t\t\t修改成功\n");


}
else
{
return;
}
}


}
//按姓排序
void SortContact(pContact pc)
{
int i = 0;
int j = 0;
int flag = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无联系人\n");
return;
}
// 冒泡次数
for (i = 0; i < pc->size - 1; i++)
{
//冒泡排序
for (j = 0; j < pc->size - i - 1; j++)
{
if (strcmp(pc->data[j].Name, pc->data[j + 1].Name)>0)
{
Swap(&pc->data[j], &pc->data[j + 1]);
flag = 1;
}
}
if (0 == flag)
{
break;
}
}
printf("排序成功\n");
}
//列表联系人
void ShowContact(pContact pc)
{
int i = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无联系人\n");
return;
}
printf("\t\t\tName\tSex\tAge\tTel\t\tAddr\n");
for (i = 0; i < pc->size; i++)
{
printf("\t\t\t%-5s\t%-5s\t%-5d\t%-12s\t%-15s\n",
pc->data[i].Name,
pc->data[i].Sex,
pc->data[i].age,
pc->data[i].Tel,
pc->data[i].Addr);

}

}
//清空联系人
void EmptyContact(pContact pc)
{
assert(pc);
pc->size = 0;
printf("\t\t\t清空成功");
}
//销毁通讯录
void DestoryContact(pContact pc)
{
assert(pc);
SaveContact(pc);
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->size = 0;
printf("\t\t\t销毁成功");
}

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
61
62
63
64
65
66
67
68
69

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"
void meau()
{
printf("\t\t\t****** 《通讯录》 ********\n");
printf("\t\t\t****************************************\n");
printf("\t\t\t****** 1.添加信息 2.查找信息******\n");
printf("\t\t\t****** 3.删除信息 4.修改信息******\n");
printf("\t\t\t****** 5.按姓排序 6.信息列表******\n");
printf("\t\t\t****** 7.清空信息 0.退出 ******\n");
printf("\t\t\t****************************************\n");
}

void test()
{
int input = 0;
Contact pc;
InitContact(&pc);
do
{
meau();
printf("\t\t\t请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&pc);
break;
case SEARCH:
SearchContact(&pc);
break;
case DEIETE:
DeleteContact(&pc);
break;
case MODIFY:
ModifyContact(&pc);
break;
case SORT:
SortContact(&pc);
break;
case SHOW:
ShowContact(&pc);
break;
case EMPTY:
EmptyContact(&pc);
break;
case EXIT:
break;
default:
printf("\t\t\t输入有误,请重新输入:>");
break;
}

} while (input);

}

int main()
{
Contact pc;
test();

//销毁通讯录
DestoryContact(&pc);
system("pause");
return 0;
}

结语:

最初的自己是个编程菜鸟,然而通过努力的学习,现在也能逐渐的自己写小程序了,相信这就是一种进步,暂不希望自己能有多强大。只要每一步走的充实,我相信一定会有好的回报,且行且努力!

-------------本文结束感谢您的阅读-------------