今天学完了c语言,这是我编写的通讯录管理系统,亲测有效,没有问题:

基本功能有:

1、添加联系人

2、查找一个联系人

3、修改联系人

4、删除一个联系人

5、展示所有联系人

6、清空所有联系人

7、以名字排序所有联系人

此外,此程序还支持动态扩容和文件操作(保存和读取功能),注意文件位置,得先创建。这里还有一点需要注意,我在对文件操作的时候直接复制了它的路径,结果程序报错,后来把‘\’改成了‘/’就可以了。

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<windows.h>
#include<math.h>
//描述了一个联系人
typedef struct Linkman {
	char name[1024];
	char gender[1024];
	char age[1024];
	char number[1024];
	char address[1024];
}Linkman;

//描述了一个通讯录,里面包含了多个联系人,size是当前联系人数
typedef struct AddressList {
	//把这个数组改成指针,通过malloc来动态分配内存
	Linkman* persons;
	//表示当前这个指针指向的数组的最大容量
	int capacity;
	int size;
}AddressList;

//创建一个全局变量
AddressList addressList;

//保存内容到文件(存档)
void save(AddressList* list) {
	FILE* fp = fopen("E:/address_list.txt", "w");
	//查看是否打开成功
	if (fp == NULL) {
		printf("打开存档文件失败\n");
		return;
	}
	//使用fwrite来写
	fwrite(list->persons, sizeof(Linkman), list->size, fp);
	fclose(fp);
	printf("存档成功\n");
}

//函数声明
//extern void save(AddressList* list);

//把文件中数据加载到内存中(读档)
void load(AddressList* list) {
	FILE* fp = fopen("E:/address_list.txt", "r");
	if (fp == NULL) {
		printf("打开存档文件失败\n");
		return;
	}
	//写文件中,一共要读多少个元素,直接通过size就知道了
	//读文件中,一共要读多少元素就不好确定,只能一个一个读,直到读到文件末尾 
	while (1) {
		if (list->size > list->capacity) {
			list->capacity += 100;
			list->persons = realloc(list->persons, sizeof(Linkman) * list->capacity);
		}
		size_t n = fread(&list->persons[list->size], sizeof(Linkman), 1, fp);
		if (n == 0) {
			//读到文件末尾了
			break;
		}
		list->size++;
	}
	fclose(fp);
	printf("读档成功!\n");
}

//初始化
void init(AddressList* list) {
	list->size = 0;
	list->capacity = 100;
	list->persons = (Linkman*)malloc(sizeof(Linkman) * list->capacity);
	//(list->num).name = { 0 };
}

int menu() {
	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("|    7、以名字排序所有联系人 |\n");
	printf("|    0、退出                 |\n");
	printf("+----------------------------+\n");
	printf("请输入你的选择:");
	int choice = 0;
	scanf("%d", &choice);
	return choice;
}

//添加联系人
void insert(AddressList* list) {
	assert(list != NULL);
	//通讯录满了的话就返回
	/*if (list->size >= 1000) {
		printf("通讯录已满\n");
		return;
	}*/
	//进行扩容
	if (list->size > list->capacity) {
		list->capacity += 100;
		list->persons = (Linkman*)realloc(list->persons, sizeof(Linkman) * list->capacity);
	}
	Linkman person = { 0 };
	printf("请输入联系人姓名:");
	scanf("%s", person.name);
	printf("请输入联系人性别:");
	scanf("%s", person.gender);
	printf("请输入联系人年龄:");
	scanf("%s", person.age);
	printf("请输入联系人电话:");
	scanf("%s", person.number);
	printf("请输入联系人住址:");
	scanf("%s", person.address);
	//把联系人放在通讯录中
	list->persons[list->size] = person;
	list->size++;
	printf("新增联系人成功\n");
	//Sleep(2000); //显示两秒
	//system("cls");
	save(list);
}
//修改联系人
void change(AddressList* list) {
	int id = 0;
	printf("请输入你要修改的联系人的序号:");
	scanf("%d", &id);
	if (id < 0 || id > list->size - 1) {
		printf("你的输入有误");
		return;
	}
	Linkman* p = &list->persons[id];
	printf("请输入修改后的联系人的姓名:");
	scanf("%s", p->name);
	printf("请输入修改后的联系人的性别:");
	scanf("%s", p->gender);
	printf("请输入修改后的联系人的年龄:");
	scanf("%s", p->age);
	printf("请输入修改后的联系人的电话:");
	scanf("%s", p->number);
	printf("请输入修改后的联系人的住址:");
	scanf("%s", p->address);
	printf("修改联系人成功!\n");
	save(list);
}

//查找联系人
void find(AddressList* list) {
	int id = 0;
	printf("请输入要查看联系人的序号:");
	scanf("%d", &id);
	if (id < 0 || id > list->size - 1) {
		printf("你的输入有误");
		return;
	}
	for (int i = 0; i < list->size; i++) {
		if (id == i) {
			Linkman* p = &list->persons[i];
			printf("姓名:%s\t性别:%s\t年龄:%s\t电话:%s\t住址:%s\n", p->name, p->gender, p->age, p->number, p->address);
			printf("%s", list->persons[i].name);
		}
	}
}
//查看所有联系人
void show(AddressList* list) {
	//printf("查看所有联系人\n");
	for (int i = 0; i < list->size; i++) {
		Linkman* p = &list->persons[i];
		printf("[%d]\t%s\t%s\n", i, p->name, p->number);
	}
	printf("一共有%d个联系人\n", list->size);
}
//清空所有联系人
void empty(AddressList* list) {
	int i = 0;
	printf("确定要清空所有联系人吗,确定请按1,按其余键返回\n");
	scanf("%d", &i);
	if (i == 1) {
		list->size = 0;
		printf("删除成功!\n");
	}
	return;
	save(list);
}
//按照姓名排序
void sort(AddressList* list) {
	for (int i = 0; i < list->size - 1; i++) {
		for (int j = 0; j < list->size - 1 - i; j++) {
			Linkman* p1 = &list->persons[j];
			Linkman* p2 = &list->persons[j + 1];
			if (memcmp(p1->name, p2->name, sizeof(p1->name)) > 0) {
				Linkman tmp = list->persons[j];
				list->persons[j] = list->persons[j + 1];
				list->persons[j + 1] = tmp;
			}
		}
	}
	printf("排序成功!\n");
	save(list);
}

//删除一个联系人(逻辑删除)
void update(AddressList* list) {
	int id = 0;
	printf("请输入要删除的联系人的序号:\n");
	scanf("%d", &id);
	if (id < 0 || id > list->size) {
		printf("你的输入有误\n");
		return;
	}
	else if (id == list->size - 1) {//要删除的是最后一个联系人
		list->size--;
		printf("删除成功!\n");
	}
	//取出最后一个联系人的地址
	Linkman* p = &list->persons[list->size - 1];
	list->persons[id] = *p;
	list->size--;
	printf("删除成功!\n");
	save(list);
}


//定义一个函数指针
typedef void(*Func)(AddressList*);

int main() {
	init(&addressList);
	//定义一个函数指针数组
	load(&addressList);//程序启动前进行一次读档即可
	//为了降低圈复杂度,采用转移表的方式
	Func func[] = { NULL,insert,find,change,update,show,empty,sort };//NULL纯粹为了占位
	while (1) {
		int choice = menu();
		if (choice == 0) {
			printf("goodbye\n");
			break;
		}
		else if (choice < 0 || choice > 7) {
			printf("你的输入有误,请重新输入\n");
			continue;
		}
		func[choice](&addressList);
		system("pause");
		system("cls");
		//Func func = func[choice]
		//func(&addressList)
	}
	system("pause");
	//当前这个数组的生命周期本就应该跟随整个程序,既然这个数组一直不需要用,就不能提前释放
	//当程序结束,内存会被系统自动回收
}

如果有什么问题,欢迎大家指出! 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐