通讯录管理系统 (数据结构与算法课设)(哈希表存储)
为数据结构与算法关于通讯录管理系统的解决方案。采用顺序表和二次散列存储的方式,使用表格的输出形式并向文件导出。
为数据结构与算法关于通讯录管理系统的解决方案。采用顺序表和二次散列存储的方式,使用表格的输出形式并向文件导出。
目录
设计内容和要求
|
设计内容: 设计散列表实现通讯录查找系统。 (1) 每个记录包括数据项:电话号码、用户名、地址; (2) 从键盘输入记录,分别以电话号码为关键字建立散列表; (3)查找并显示给定号码的记录; (4) 通讯录信息文件保存。 设计要求: (1) 符合课题要求,实现相应功能; (2) 要求界面友好美观,操作方便易行; (3) 注意程序的实用性、安全性。 |
|
3.设计工作任务及工作量的要求 (1) 选择合适的数据结构,并定义数据结构的结构体; (2) 根据程序所要完成的基本要求和程序实现提示,设计出完整的算法; |
代码实现
完整代码在最后,时间有限,只完整了基本函数,还存在不足和有待优化改正的地方,欢迎评论讨论和分享。
1.结构体实现
struct list {
elemtype a[Length_1];
elemtype NaMe[Length_2];
elemtype address[Length_3];
int f;
};
struct sqstack {
struct list* base;
int i;
};
struct sqstack T;
代码中使用了两个全局变量,一个是散列表,另一个NUM_T用来记录表中联系人个人数
2.增删改查操作
添加联系人
void store(elemtype* a, elemtype* NaMe, elemtype* address) {
int d[50];
int mainnumber;
mainnumber = (int)(a[0]) + (int)(a[3]) + (int)(a[7]); /*此处构造哈希函数,用关键字 037 位*/
T.i = mainnumber % MAX_size;
int j = 1;
(T.base + T.i)->f = 0;
while (1) {
if ((T.base + T.i)->f == 0) {
strcpy((T.base + T.i)->a, a);
strcpy((T.base + T.i)->NaMe, NaMe);
strcpy((T.base + T.i)->address, address);
(T.base + T.i)->f = 1;
break;
}
T.i = (mainnumber % 20 + d[j]) % 20;
j++;
}
}
void addContact() {
void menu();
printf("请输入信息:\n\n(输入后自动保存一次)\n\n");
elemtype a[12];
elemtype NaMe[15];
elemtype address[15];
int put;
while (1) {
printf("请输入联系人的联系方式\n");
scanf("%s", a);
printf("请输入联系人姓名\n");
scanf("%s", NaMe);
printf("请输入联系人地址\n");
scanf("%s", address);
store(a, NaMe, address);
printf("输入的数据已经保存,请输入1继续输入或者输入0结束\n******************************\n");
scanf("%d",&put);
if (put == 0) { break; }
else if (put == 1) { continue;}
}
NUM_T++;
menu();
}
这里添加联系人信息后,使用store函数保存到散列表中,新增函数中实际还存在三个可以改动优化的地方。一是判断重复联系人输入,而是对于电话号码输入是否正确的判断,三是对于终止输入只使用1和0判断并不安全。
对于改动的一些思路:一,由于是采用散列表存储,可以在输入电话号后先判断散列表对应位置是否已经存在元素。没有就说明是新添加的联系人,如果有,可以让用户选择调用修改。二,电话号码是11位(一般而言)所以判断可以通过去计算数组长度或者使用strlen去计算后于“11111111111”比较。三,目前没有更好的方法去改正,如果有好想法,欢迎评论指教。
删除联系人
void deleteContact() {
void menu();
int i;
int ff = 0;
int b;
elemtype a[15];
printf("输入 1 按姓名删除,输入 2 按电话删除,输入 3 按地址删除\n");
scanf("%d", &b);
switch (b) {
case 1:
printf("请输入姓名\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->NaMe) == 0) {
(T.base + i)->f = 0;
printf("已删除: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到\n");
break;
case 2:
printf("请输入电话号码\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->a) == 0) {
(T.base + i)->f = 0;
printf("已删除: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到\n");
break;
case 3:
printf("请输入你要搜索的地址\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->address) == 0) {
(T.base + i)->f = 0;
printf("已删除: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到该用户\n");
break;
}
menu();
}
修改联系人
void modifyContact() {
void menu();
int i;
int ff = 0;
int b;
elemtype a[15];
printf("请输入姓名\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->NaMe) == 0) {
printf("您要修改的信息是: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
printf("请输入新信息\n");
scanf("%s", (T.base + i)->a);
scanf("%s", (T.base + i)->NaMe);
scanf("%s", (T.base + i)->address);
printf("您的内容已修改成: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到该用户\n");
menu();
}
void save() {
void menu();
int i = 0;
char filename[50] = { 0 };
printf("请输入导出文件的名称(不含扩展名): ");
scanf("%s", filename);
strcat(filename, ".txt"); // 自动添加扩展名
FILE* fp = fopen(filename, "w");
if (fp == NULL) {
printf("无法打开文件 %s !\a\n", filename);
return;
}
for (i = 0; i <= MAX_size; i++) {
int ch = 32;
if ((T.base + i)->f == 1) {
fprintf(fp, "%s", (T.base + i)->NaMe);
fputc(ch, fp);
fprintf(fp, "%s", (T.base + i)->a);
fputc(ch, fp);
ch = 10;
fprintf(fp, "%s", (T.base + i)->address);
fputc(ch, fp);
}
}
fclose(fp);
printf("您输入的已保存\n");
menu();
}
查找联系人
void searchContact() {
void menu();
int i;
int ff = 0;
int b;
elemtype a[15];
printf("输入 1 按姓名查找,输入 2 按电话查找,输入 3 按地址查找\n");
scanf("%d", &b);
switch (b) {
case 1:
printf("请输入姓名\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->NaMe) == 0) {
printf("%s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base + i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到该用户\n");
break;
case 2:
printf("请输入电话号码\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->a) == 0) {
printf("%s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base + i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到该用户\n");
break;
case 3:
printf("请输入地址\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->address) == 0) {
printf("%s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base + i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到\n");
break;
}
menu();
}
3.打印输入和文件导入
打印通讯录
void displayContacts() {
void menu();
printf("┌───────────┬───────────────────────┬─────────────────────┐\n");
printf("│ 姓名 │ 电话号码 │ 地址 │\n");
printf("├───────────┼───────────────────────┼─────────────────────┤\n");
int j;
for (int i = 0; i < MAX_size; i++) {
if ((T.base + i)->f == 1) {
int padding;
printf("│");
padding = (Length_1 - strlen((T.base + i)->NaMe)) / 2;
for (j = 0; j < padding; j++) printf(" ");
printf("%s",(T.base + i)->NaMe);
for (j = 0; j < Length_1 - (strlen((T.base + i)->NaMe))-padding; j++) {printf(" "); }
printf("│");
padding = (Length_2 - strlen((T.base + i)->a)) / 2;
for (j = 0; j < padding; j++) printf(" ");
printf("%s",(T.base + i)->a);
for (j = 0; j < Length_2 - strlen((T.base + i)->a) - padding; j++) { printf(" "); }
printf("│");
padding = (Length_3 - strlen((T.base + i)->address)) / 2;
for (j = 0; j < padding; j++) printf(" ");
printf("%s",(T.base + i)->address);
for (j = 0; j < Length_3 - strlen((T.base + i)->address) - padding; j++) { printf(" "); }
printf("│\n");
}
}
int n = NUM_T;
if (n - 1 == 0) { printf("└───────────┴───────────────────────┴─────────────────────┘\n"); }
else { printf("├───────────┼───────────────────────┼─────────────────────┤"); n--; }
menu();
}
对于最后存储好的通讯录的输出,还是沿用表格的形式,这种方法在上篇文章有过介绍,(比较繁琐的地方是计算表头的符号数量和数据前后空格的数量,这里还没有优化到一个函数,其实可以写一个函数来使得我们的数据能够在表格中居中打印)。这次向文件中导入并没有添加表格可以自行添加。
导入信息到文件
void save() {
void menu();
int i = 0;
char filename[50] = { 0 };
printf("请输入导出文件的名称(不含扩展名): ");
scanf("%s", filename);
strcat(filename, ".txt"); // 自动添加扩展名
FILE* fp = fopen(filename, "w");
if (fp == NULL) {
printf("无法打开文件 %s !\a\n", filename);
return;
}
for (i = 0; i <= MAX_size; i++) {
int ch = 32;
if ((T.base + i)->f == 1) {
fprintf(fp, "%s", (T.base + i)->NaMe);
fputc(ch, fp);
fprintf(fp, "%s", (T.base + i)->a);
fputc(ch, fp);
ch = 10;
fprintf(fp, "%s", (T.base + i)->address);
fputc(ch, fp);
}
}
fclose(fp);
printf("您输入的已保存\n");
menu();
}
4.菜单函数和主函数
void menu() {
int i;
printf("********* 欢迎使用通讯录查询系统* ************ \n\n");
printf("*******************************************\n");
printf("* *\n");
printf("* 请输入您要实现的操作 *\n");
printf("* 1: 输入通讯录 *\n");
printf("* 2:显示通讯录 *\n");
printf("* 3:查找联系人 *\n");
printf("* 4:删除联系人 *\n");
printf("* 5:修改联系人信息 *\n");
printf("* 6:保存到文件 *\n");
printf("* 0:结束程序 *\n");
printf("* *\n");
printf("*******************************************\n");
scanf("%d", &i);
switch (i) {
case 0:
return;
break;
case 1:
addContact();
break;
case 2:
displayContacts();
break;
case 3:
searchContact();
break;
case 4:
deleteContact();
break;
case 5:
modifyContact();
break;
case 6:
save();
break;
};
}
int main() {
T.base = (struct list*)malloc(MAX_size * sizeof(struct list));
int d[50];/*再散列*/
int i;
for (i = 1; i < 25; i++)
d[2 * i] = -1 * i * i;
for (i = 1; i < 25; i++) /*构造二次再散列*/
d[i + i - 1] = i * i;
menu();
return 0;
}
对于菜单函数,有一个地方可以优化,选择执行功能后,可以先清屏再就进行执行,可以让页面看起来简洁一些。
5.**完整代码
#define _CRT_SECURE_NO_WARNINGS 25
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_size 20
#define Length_1 11
#define Length_2 23
#define Length_3 21
typedef char elemtype;
struct list {
elemtype a[Length_1];
elemtype NaMe[Length_2];
elemtype address[Length_3];
int f;
};
struct sqstack {
struct list* base;
int i;
};
struct sqstack T;
int NUM_T = 0;
void store(elemtype* a, elemtype* NaMe, elemtype* address) {
int d[50];
int mainnumber;
mainnumber = (int)(a[0]) + (int)(a[3]) + (int)(a[7]); /*此处构造哈希函数,用关键字 037 位*/
T.i = mainnumber % MAX_size;
int j = 1;
(T.base + T.i)->f = 0;
while (1) {
if ((T.base + T.i)->f == 0) {
strcpy((T.base + T.i)->a, a);
strcpy((T.base + T.i)->NaMe, NaMe);
strcpy((T.base + T.i)->address, address);
(T.base + T.i)->f = 1;
break;
}
T.i = (mainnumber % 20 + d[j]) % 20;
j++;
}
}
void addContact() {
void menu();
printf("请输入信息:\n\n(输入后自动保存一次)\n\n");
elemtype a[12];
elemtype NaMe[15];
elemtype address[15];
int put;
while (1) {
printf("请输入联系人的联系方式\n");
scanf("%s", a);
printf("请输入联系人姓名\n");
scanf("%s", NaMe);
printf("请输入联系人地址\n");
scanf("%s", address);
store(a, NaMe, address);
printf("输入的数据已经保存,请输入1继续输入或者输入0结束\n******************************\n");
scanf("%d",&put);
if (put == 0) { break; }
else if (put == 1) { continue;}
}
NUM_T++;
menu();
}
void displayContacts() {
void menu();
printf("┌───────────┬───────────────────────┬─────────────────────┐\n");
printf("│ 姓名 │ 电话号码 │ 地址 │\n");
printf("├───────────┼───────────────────────┼─────────────────────┤\n");
int j;
for (int i = 0; i < MAX_size; i++) {
if ((T.base + i)->f == 1) {
int padding;
printf("│");
padding = (Length_1 - strlen((T.base + i)->NaMe)) / 2;
for (j = 0; j < padding; j++) printf(" ");
printf("%s",(T.base + i)->NaMe);
for (j = 0; j < Length_1 - (strlen((T.base + i)->NaMe))-padding; j++) {printf(" "); }
printf("│");
padding = (Length_2 - strlen((T.base + i)->a)) / 2;
for (j = 0; j < padding; j++) printf(" ");
printf("%s",(T.base + i)->a);
for (j = 0; j < Length_2 - strlen((T.base + i)->a) - padding; j++) { printf(" "); }
printf("│");
padding = (Length_3 - strlen((T.base + i)->address)) / 2;
for (j = 0; j < padding; j++) printf(" ");
printf("%s",(T.base + i)->address);
for (j = 0; j < Length_3 - strlen((T.base + i)->address) - padding; j++) { printf(" "); }
printf("│\n");
}
}
int n = NUM_T;
if (n - 1 == 0) { printf("└───────────┴───────────────────────┴─────────────────────┘\n"); }
else { printf("├───────────┼───────────────────────┼─────────────────────┤"); n--; }
menu();
}
void searchContact() {
void menu();
int i;
int ff = 0;
int b;
elemtype a[15];
printf("输入 1 按姓名查找,输入 2 按电话查找,输入 3 按地址查找\n");
scanf("%d", &b);
switch (b) {
case 1:
printf("请输入姓名\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->NaMe) == 0) {
printf("%s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base + i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到该用户\n");
break;
case 2:
printf("请输入电话号码\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->a) == 0) {
printf("%s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base + i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到该用户\n");
break;
case 3:
printf("请输入地址\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->address) == 0) {
printf("%s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base + i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到\n");
break;
}
menu();
}
void deleteContact() {
void menu();
int i;
int ff = 0;
int b;
elemtype a[15];
printf("输入 1 按姓名删除,输入 2 按电话删除,输入 3 按地址删除\n");
scanf("%d", &b);
switch (b) {
case 1:
printf("请输入姓名\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->NaMe) == 0) {
(T.base + i)->f = 0;
printf("已删除: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到\n");
break;
case 2:
printf("请输入电话号码\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->a) == 0) {
(T.base + i)->f = 0;
printf("已删除: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到\n");
break;
case 3:
printf("请输入你要搜索的地址\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->address) == 0) {
(T.base + i)->f = 0;
printf("已删除: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到该用户\n");
break;
}
menu();
}
void modifyContact() {
void menu();
int i;
int ff = 0;
int b;
elemtype a[15];
printf("请输入姓名\n");
scanf("%s", a);
for (i = 0; i < 20; i++)
if (strcmp(a, (T.base + i)->NaMe) == 0) {
printf("您要修改的信息是: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
printf("请输入新信息\n");
scanf("%s", (T.base + i)->a);
scanf("%s", (T.base + i)->NaMe);
scanf("%s", (T.base + i)->address);
printf("您的内容已修改成: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
i)->address);
ff = 1;
}
if (ff == 0)
printf("找不到该用户\n");
menu();
}
void save() {
void menu();
int i = 0;
char filename[50] = { 0 };
printf("请输入导出文件的名称(不含扩展名): ");
scanf("%s", filename);
strcat(filename, ".txt"); // 自动添加扩展名
FILE* fp = fopen(filename, "w");
if (fp == NULL) {
printf("无法打开文件 %s !\a\n", filename);
return;
}
for (i = 0; i <= MAX_size; i++) {
int ch = 32;
if ((T.base + i)->f == 1) {
fprintf(fp, "%s", (T.base + i)->NaMe);
fputc(ch, fp);
fprintf(fp, "%s", (T.base + i)->a);
fputc(ch, fp);
ch = 10;
fprintf(fp, "%s", (T.base + i)->address);
fputc(ch, fp);
}
}
fclose(fp);
printf("您输入的已保存\n");
menu();
}
void menu() {
int i;
printf("********* 欢迎使用通讯录查询系统* ************ \n\n");
printf("*******************************************\n");
printf("* *\n");
printf("* 请输入您要实现的操作 *\n");
printf("* 1: 输入通讯录 *\n");
printf("* 2:显示通讯录 *\n");
printf("* 3:查找联系人 *\n");
printf("* 4:删除联系人 *\n");
printf("* 5:修改联系人信息 *\n");
printf("* 6:保存到文件 *\n");
printf("* 0:结束程序 *\n");
printf("* *\n");
printf("*******************************************\n");
scanf("%d", &i);
switch (i) {
case 0:
return;
break;
case 1:
addContact();
break;
case 2:
displayContacts();
break;
case 3:
searchContact();
break;
case 4:
deleteContact();
break;
case 5:
modifyContact();
break;
case 6:
save();
break;
};
}
int main() {
T.base = (struct list*)malloc(MAX_size * sizeof(struct list));
int d[50];/*再散列*/
int i;
for (i = 1; i < 25; i++)
d[2 * i] = -1 * i * i;
for (i = 1; i < 25; i++) /*构造二次再散列*/
d[i + i - 1] = i * i;
menu();
return 0;
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)