为数据结构与算法关于通讯录管理系统的解决方案。采用顺序表和二次散列存储的方式,使用表格的输出形式并向文件导出。

目录

设计内容和要求

代码实现

1.结构体实现

 2.增删改查操作

 添加联系人

删除联系人

修改联系人

查找联系人

3.打印输入和文件导入

打印通讯录

导入信息到文件

4.菜单函数和主函数

5.**完整代码


设计内容和要求

设计内容:

    设计散列表实现通讯录查找系统。

(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;
}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐