C语言通讯录的实现(动态链表)

C语言通讯录的实现(动态链表)

编译器VS2017


AddressList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct AddressList {
	char sex;
	int age;
	char Tel[20];
	char name[50];
	char Add[100];
	struct AddressList* next;
}AL;
enum {
	退出,
	添加,
	删除,
	修改,
	查找,
	显示,
	清空,
	排序,
	保存,
	读取,
};
int Menu();//菜单
void AddressList();
void input(AL*);//输入
AL* add(AL*);//增
void del(AL*);//删
void alter(AL*); //改
AL** allfind(AL*);//查
AL* find_1(AL*, const char*);//按姓名找
AL* find_2(AL*, const char*);//按年龄找
AL* find_3(AL*, const char*);//按电话号码找
AL* find_4(AL*, const char*);//按地址找
void print(AL*);//输出
void allprint(AL*); //全部输出
int empty(AL*);//清空
void swap(AL*, AL*);//交换
int sort(AL*);//排序
int save(AL*);//保存
void finput(AL*, FILE*);//
AL* read(AL*);//读取

 func.h 

#pragma once
#include"AddressList.h"
int Menu() {//菜单
	int choic;
	int n = 0;
	printf("1.添加联系人         2.删除联系人\n"
		"3.修改联系人信息     4.查找联系人\n"
		"5.显示所有联系人     6.清空所有联系人\n"
		"7.按名称排序         8.保存到文件\n"
		"9.从文件中读取联系人 0.退出\n"
		"请输入您的选项!\n");
	n = scanf("%d", &choic);
	while (n != 1 || choic < 0 || choic > 9) {
		printf("您的输入有误,请重新输入\n");
		while (getchar() != '\n');
		n = scanf("%d", &choic);
	}
	return choic;
}
void input(AL* p) {
	int n = 0;
	printf("请输入姓名\n");
	scanf("%s", p->name);
	getchar();
	printf("请输入性别,男m,女f\n");
	n = scanf("%c", &p->sex);
	while (n != 1 || p->sex != 'm' && p->sex != 'f') {
		printf("您的输入有误,请重新输入\n");
		while (getchar() != '\n');
		n = scanf("%c", &p->sex);
	}
	printf("请输入年龄\n");
	n = scanf("%d", &p->age);
	while (n != 1 || p->age <= 0 || p->age > 130) {
		printf("您的输入有误,请重新输入\n");
		while (getchar() != '\n');
		n = scanf("%d", &p->age);
	}
	printf("请输入地址\n");
	scanf("%s", p->Add);
	printf("请输入电话号码\n");
	scanf("%s", p->Tel);
}
AL* add(AL* temphead) {//增
	int n = 0;
	AL* p = temphead;
	AL* s = NULL;
	char choic;
	do {
		s = (AL*)malloc(sizeof(AL));
		if (s == NULL) {
			exit(EXIT_FAILURE);
		}
		input(s);
		s->next = p->next;
		p->next = s;
		p = p->next;
		p->next = NULL;
		printf("继续输入请输入'y'\n");
		getchar();
		n = scanf("%c", &choic);
		while (n != 1) {
			printf("您的输入有误,请重新输入\n");
			while (getchar() != '\n');
			n = scanf("%c", &choic);
		}
	} while (choic == 'y');
	system("cls");
	return p;
}
void del(AL* p) {//删
	AL* temp;
	temp = p->next;
	p->next = temp->next;
	free(temp);
}
void alter(AL* p) {//改
	input(p->next);
}
AL* find_1(AL* p, const char* str) {//按姓名找
	if (strstr(p->next->name, str)) {
		return p;
	}
	return NULL;
}
AL* find_2(AL* p, const char* str) {//按年龄找
	char temp[5];
	sprintf(temp, "%d", p->next->age);
	if (strstr(temp, str)) {
		return p;
	}
	return NULL;
}
AL* find_3(AL* p, const char* str) {//按电话号码找
	if (strstr(p->next->Tel, str)) {
		return p;
	}
	return NULL;
}
AL* find_4(AL* p, const char* str) {//按地址找
	if (strstr(p->next->Add, str)) {
		return p;
	}
	return NULL;
}
AL** allfind(AL* head) {//查
	if (head->next == NULL) {
		printf("还未添加联系人\n");
		return NULL;
	}
	char str[100] = { 0 };
	AL* find = NULL;
	AL** ptr = NULL;
	ptr = (AL**)calloc(4, sizeof(AL*));
	if (ptr == NULL) {
		exit(EXIT_FAILURE);
	}
	printf("请输入需要查找的信息\n");
	scanf("%s", str);
	static int count;
	count = 1;
	int m = 4;
	for (AL* p = head; p->next != NULL; p = p->next) {
		if (count >= m) {
			m += 4;
			AL** pt = (AL**)realloc(ptr, m * sizeof(AL*));
			if (pt == NULL) {
				exit(EXIT_FAILURE);
			}
			ptr = pt;
		}
		if (find = find_1(p, str)) {
			ptr[count++] = find;
			continue;
		}
		if (find = find_2(p, str)) {
			ptr[count++] = find;
			continue;
		}
		if (find = find_3(p, str)) {
			ptr[count++] = find;
			continue;
		}
		if (find = find_4(p, str)) {
			ptr[count++] = find;
			continue;
		}
	}
	if (count != 0) {
		printf("序号\t姓名\t性别\t年龄\t地址\t\t电话\t\t\n");
		for (int i = 1; i < count; ++i) {
			printf("%d\t", i);
			print(ptr[i]->next);
		}
		ptr[0] = (AL*)&count;
		return ptr;
	}
	return NULL;
}
void print(AL* p) {//输出
	printf("%s\t%c\t%d\t%s\t\t%s\t\t\n", p->name, p->sex, p->age, p->Add, p->Tel);
}
void allprint(AL* head) {//全部输出
	if (head->next == NULL) {
		printf("没有联系人\n");
		return;
	}
	printf("序号\t姓名\t性别\t年龄\t地址\t\t电话\t\t\n");
	int i = 1;
	for (AL* p = head->next; p != NULL; p = p->next, ++i) {
		printf("%d\t", i);
		print(p);
	}
}
int empty(AL* head) {//清空
	if (head->next == NULL) {
		return 0;
	}
	for (AL* p = head; p->next != NULL;) {
		del(p);
	}
	return 1;
}
void swap(AL* p, AL* q) {
	AL temp;
	AL* t;
	temp = *p;
	*p = *q;
	*q = temp;
	t = p->next;
	p->next = q->next;
	q->next = t;
}
int sort(AL* head) {
	if (head->next == NULL) {
		return 0;
	}
	for (AL* p = head->next; p != NULL; p = p->next) {
		for (AL* q = p->next; q != NULL; q = q->next) {
			if (strcmp(p->name, q->name) > 0) {
				swap(p, q);
			}
		}
	}
	return 1;
}
int save(AL* head) {
	FILE* fp;//定义指向文件型数据的指针变量(是一个结构体变量)fp
	char temp[5] = { 0 };
	int choic;
	int n = 0;
	if (head->next == NULL) {
		return -1;
	}
	if ((fp = fopen("AL.txt", "r+")) == NULL) {//fopen(文件名,使用方式),此处w为write,只写.
		//应返回指向这个文件的指针,文件不存在则建立新文件,既不存在又创建新文件失败则返回NULL
		return 0;//
	}
	getc(fp);
	if (feof(fp)) {
		printf("文件为空,直接保存!\n");
		fclose(fp);
		fp = NULL;
		if ((fp = fopen("AL.txt", "w+")) == NULL) {//fopen(文件名,使用方式),此处w为write,只写.
			//应返回指向这个文件的指针,文件不存在则建立新文件,既不存在又创建新文件失败则返回NULL
			return 0;//
		}
	}
	else {
		fclose(fp);
		fp = NULL;
		printf("1.覆盖 2.并入\n请输入选择\n");
		n = scanf("%d", &choic);
		while (n != 1 || choic < 1 || choic > 2) {
			printf("您的输入有误,请重新输入\n");
			while (getchar() != '\n');
			n = scanf("%d", &choic);
		}
		if (choic == 1) {
			if ((fp = fopen("AL.txt", "w+")) == NULL) {//fopen(文件名,使用方式),此处w为write,只写.
			//应返回指向这个文件的指针,文件不存在则建立新文件,既不存在又创建新文件失败则返回NULL
				return 0;//
			}
		}
		else {
			if ((fp = fopen("AL.txt", "a+")) == NULL) {
				return 0;
			}
		}
	}
	for (AL* p = head->next; p != NULL; p = p->next) {
		#if 0
		fputs(p->name, fp);
		fputc(' ', fp);
		fputc(p->sex, fp);
		fputc(' ', fp);
		sprintf(temp, "%d", p->age);
		fputs(temp, fp);
		fputc(' ', fp);
		fputs(p->Add, fp);
		fputc(' ', fp);
		fputs(p->Tel, fp);
		fputc('\n', fp);
		#endif
		#if 1
		fprintf(fp, "%s ", p->name);
		fprintf(fp, "%c ", p->sex);
		fprintf(fp, "%d ", p->age);
		fprintf(fp, "%s ", p->Add);
		fprintf(fp, "%s\n", p->Tel);
		#endif
	}
	fclose(fp);//关闭
	return 1;
}
void finput(AL* p, FILE* fp) {
	fscanf(fp, "%s", p->name);
	fgetc(fp);
	fscanf(fp, "%c", &p->sex);
	fscanf(fp, "%d", &p->age);
	fscanf(fp, "%s", p->Add);
	fscanf(fp, "%s", p->Tel);
}
AL* read(AL* temphead) {
	FILE* fp;//定义指向文件型数据的指针变量(是一个结构体变量)fp
	AL* p = temphead;
	AL* s = NULL;
	if ((fp = fopen("AL.txt", "r+")) == NULL) {//fopen(文件名,使用方式),此处r为read,只写.
		//应返回指向这个文件的指针,文件不存在则返回NULL
		printf("没有保存的联系人文件!\n");
		return p;//
	}
	getc(fp);
	if (feof(fp)) {//遇见EOF返回非0
		printf("文件为空!\n");
		fclose(fp);
		return p;
	}
	while (1) {
		s = (AL*)malloc(sizeof(AL));
		if (s == NULL) {
			exit(EXIT_FAILURE);
		}
		finput(s, fp);
		if (feof(fp)) {//遇见EOF返回非0
			break;
		}
		s->next = p->next;
		p->next = s;
		p = p->next;
		p->next = NULL;
	}
	fclose(fp);
	printf("读取成功!\n");
	return p;
}
void AddressList() {
	int n = 0;
	int choic_1;
	AL** find = NULL;
	int choic_2;
	int choic_3;
	AL* head = (AL*)malloc(sizeof(AL));//头结点
	head->next = NULL;
	if (head == NULL) {
		exit(EXIT_FAILURE);
	}
	AL* temphead = head;
	while (1) {
		choic_1 = Menu();
		switch (choic_1) {
		case 添加:
			temphead = add(temphead);
			break;
		case 删除:
			if ((find = allfind(head)) == NULL) {
				printf("未找到!\n");
			}
			else {
				printf("请输入需要删除的选项\n");
				n = scanf("%d", &choic_2);
				while (n != 1 || choic_2 < 1 || choic_2 > *(int*)find[0] - 1) {
					printf("您的输入有误,请重新输入\n");
					while (getchar() != '\n');
					n = scanf("%d", &choic_2);
				}
				del(find[choic_2]);
				free(find);
				find = NULL;
				printf("删除成功!\n");
			}
			system("pause");
			system("cls");
			break;
		case 修改:
			if ((find = allfind(head)) == NULL) {
				printf("未找到!\n");
			}
			else {
				printf("请输入需要修改的选项\n");
				n = scanf("%d", &choic_2);
				while (n != 1 || choic_2 < 1 || choic_2 > *(int*)find[0] - 1) {
					printf("您的输入有误,请重新输入\n");
					while (getchar() != '\n');
					n = scanf("%d", &choic_2);
				}
				alter(find[choic_2]);
				free(find);
				find = NULL;
				printf("修改成功!\n");
			}
			system("pause");
			system("cls");
			break;
		case 查找:
			find = allfind(head);
			free(find);
			find = NULL;
			system("pause");
			system("cls");
			break;
		case 显示:
			allprint(head);
			system("pause");
			system("cls");
			break;
		case 清空://全部删除
			if (empty(head)) {
				temphead = head;
				printf("已清空\n");
			}
			else {
				printf("联系人为空\n");
			}
			system("pause");
			system("cls");
			break;
		case 排序:
			if (sort(head)) {
				printf("已排序!\n");
			}
			else {
				printf("联系人为空!\n");
			}
			system("pause");
			system("cls");
			break;
		case 保存:
			n = save(head);
			if (n == 1) {
				printf("保存成功!\n");
			}
			else if (n == 0) {
				printf("打开文件或创建文件失败!\n");
			}
			else {
				printf("联系人为空!\n");
			}
			system("pause");
			system("cls");
			break;
		case 读取:
			if (head->next != NULL) {//已有数据
				printf("已有数据!\n");
				printf("1.覆盖  2.并入\n请输入选项\n");
				n = scanf("%d", &choic_3);
				while (n != 1 || choic_3 < 1 || choic_3 > 2) {
					printf("您的输入有误,请重新输入\n");
					while (getchar() != '\n');
					n = scanf("%d", &choic_3);
				}
				if (choic_3 == 1) {
					temphead = read(head);
				}
				else {
					temphead = read(temphead);
				}
			}
			else {
				temphead = read(head);
			}
			system("pause");
			system("cls");
			break;
		case 退出:
			printf("再见!\n");
			system("pause");
			exit(0);
			break;
		default:
			printf("出错!\n");
			system("pause");
			exit(0);
		}
	}
}

.c文件

#define _CRT_SECURE_NO_WARNINGS
#include"func.h"
int main() {
	AddressList();
	return 0;
}

先输入数据 

 

显示联系人

查找联系人

删除联系人,删除前需要查找,修改也需要查找,这里就不再演示 

删除之后在查看联系人

保存 

我们可以打开创建的AL.txt,发现数据已经保存 

读取文件中的数据,如果我们已经输入了数据, 可以选择覆盖或者并入 

 选择并入可以看到文件中的信息已经读取并加到了后面

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值