问题要求:
使用C语言实现一个通讯录,通讯中每个人的信息包括:姓名、性别、年龄、电话、住址
通讯录需要实现以下功能:
- 添加联系人信息
- 删除指定联系人信息
- 查找指定联系人信息
- 修改指定联系人信息
- 显示所有联系人信息
- 清空所有联系人
- 以名字排序所有联系人
另外要求:a 当通讯录的人数容量满时自动扩充容量. b 每次对通讯录内容的更新都要自动保存至本地的磁盘文件,以供下次使用。
思路:首先每个联系人需要建立一个结构体来包含联系人信息; 其次,通讯录需要建立一个结构体, 成员中包括联系人那个结构体。
然后使用逐步实现以所述1-7的功能函数。
最后通过动态内存管理和文件操作来实现通讯录容量的自动扩容和文件的保存和读取。
C语言实现代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义每个人信息
typedef struct PersonInfo{
char name[1024];
char gender[100];
char age[100];
char phonenum [1024];
char address[1024];
}PersonInfo;
// 定义通讯录
typedef struct AddressBook {
PersonInfo* person;
int capacity; // 通讯录容量
int size;
}AddressBook;
// 初始化通讯录
void Inint(AddressBook* address) {
address->size = 0;
address->capacity = 20;
address->person = (PersonInfo*)malloc(address->capacity*sizeof(PersonInfo)); // 首次开辟这么多空间
for (int i = 0; i < address->capacity; i++) {
strcpy(address->person[i].name, "");
strcpy(address->person[i].gender, "");
strcpy(address->person[i].age,"");
strcpy(address->person[i].phonenum, "");
strcpy(address->person[i].address, "");
}
}
// 菜单
int Menu() {
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;
scanf("%d", &choice);
return choice;
}
// 增加通讯录空间
void RellocPerson(AddressBook* address) {
address->size += 20;
PersonInfo* newperson = (PersonInfo*)malloc(sizeof(PersonInfo)*address->capacity);
// 将旧的拷贝到新的
memcpy(newperson,address->person, address->size * sizeof(PersonInfo));
// 释放内存
free(address->person);
}
// 保存文件
void Save(AddressBook* address) {
FILE* fq;
int i;
fq = fopen("e:/AddressBook.txt", "w");
if (fq == NULL) {
perror("文件打开失败!\n");
return;
}
for (i = 0; i < address->size; i++) {
if (fwrite(&address->person[i], sizeof(PersonInfo), 1, fq) != 1) {
printf("写入错误!\n");
}
}
fclose(fq);
printf("写入成功\n");
}
void Load(AddressBook* address) {
FILE* fq;
PersonInfo temp = { 0 };
fq = fopen("e:/AddressBook.txt", "r");
if (fq == NULL) {
perror("文件打开失败!\n");
}
while(1){
int n = fread(&temp, sizeof(PersonInfo), 1, fq);
if (n < 1) {
break;
}
if (address->size >= address->capacity) {
RellocPerson(address);
}
address->person[address->size] = temp;
address->size++;
}
fclose(fq);
}
/*转移表函数*/
// 添加联系人
void AddPerson(AddressBook* address) {
if (address->size >= address->capacity) {
// 开辟新空间
RellocPerson(address);
}
PersonInfo* info = &address->person[address->size];
printf("输入联系人姓名:");
scanf("%s", info->name);
printf("请输入联系人电话:");
scanf("%s", info->phonenum);
printf("输入联系人性别(*表示不填)");
char gender[100] = { 0 };
scanf("%s", &gender);
if (strcmp(gender, "*") != 0) {
strcpy(info->gender, gender);
}
else {
strcpy(info->gender, "无");
}
printf("输入联系人年龄(*表示不填)");
char age[100] = { 0 };
scanf("%s", &age);
if (strcmp(age, "*") != 0) {
strcpy(info->age, age);
}
else {
strcpy(info->age, "无");
}
printf("输入联系人地址(*表示不填)");
char addres[1024] = { 0 };
scanf("%s", &addres);
if (strcmp(addres, "*") != 0) {
strcpy(info->address, addres);
}
else {
strcpy(info->address, "无");
}
printf("添加联系人成功\n");
address->size++;
return;
}
void DelPerson(AddressBook* address) {
// 将要最后一个有效元素代替要删除的元素
if (address->size <= 0) {
printf("通讯录为空\n");
return;
}
printf("请输入要删除的联系人序号:");
int i;
scanf("%d", &i);
if (i < 0 || i > address->size) {
printf("输入有误,删除失败");
}
if (i >= 0 && i <= address->size) {
address->person[i] = address->person[address->size-1];
printf("删除成功");
address->size--;
}
return;
}
void FindPerson(AddressBook* address) {
if (address->size <= 0) {
printf("通讯录为空\n");
return;
}
printf("输入要删除联系人姓名:");
char name[1024] = { 0 };
scanf("%s", &name);
for (int i = 0; i < address->size; i++) {
if (strcmp(address->person[i].name, name) == 0) {
printf("[%d]姓名:%s\n 电话:%s\n 性别:%s\n 年龄:%s\n 住址:%s\n", i, address->person[i].name, address->person[i].phonenum,
address->person[i].gender, address->person[i].age, address->person[i].address);
}
}
}
void ModiPerson(AddressBook* address) {
if (address->size <= 0) {
printf("通讯录为空\n");
return;
}
printf("请输入要修改的联系人序号:");
int i;
scanf("%d", &i);
if (i < 0 || i > address->size) {
printf("输入有误,删除失败");
}
if (i >= 0 && i <= address->size) {
char name[1024] = { 0 };
printf("输入新的联系人姓名(*表示不变):");
scanf("%s", &name);
if (strcmp(name, "*") != 0) {
strcpy(address->person[i].name, name);
}
char phone[1024] = { 0 };
printf("输入新的联系人电话(*表示不变):");
scanf("%s", &phone);
if (strcmp(phone, "*") != 0) {
strcpy(address->person[i].phonenum, phone);
}
char gender[100] = { 0 };
printf("输入新的联系人性别(*表示不变):");
scanf("%s", &gender);
if (strcmp(gender, "*") != 0) {
strcpy(address->person[i].gender, gender);
}
char age[100] = { 0 };
printf("输入新的联系人年龄(*表示不变):");
scanf("%s", age);
if (strcmp(age, "*") != 0) {
strcpy(address->person[i].age, age);
}
char addres[1024] = { 0 };
printf("输入新的联系人地址(*表示不变):");
scanf("%s", addres);
if (strcmp(addres, "*") != 0) {
strcpy(address->person[i].address, addres);
}
printf("修改联系人成功\n");
return;
}
}
// 打印通讯录
void PrintPerson(AddressBook* address) {
int size = address->size;
for (int i = 0; i < size; i++) {
printf("[%d]姓名:%s\n 电话:%s\n 性别:%s\n 年龄:%s\n 住址:%s\n", i, address->person[i].name, address->person[i].phonenum,
address->person[i].gender, address->person[i].age, address->person[i].address);
}
return;
}
void SortPerson(AddressBook* address) {
int size = address->size;
for (int i = 0; i < size-1; i++) {
for (int j = 0; j < size - i - 1; j++) {
if (strcmp(address->person[j].name, address->person[j + 1].name) > 0) {
PersonInfo temp = address->person[j];
address->person[j] = address->person[j + 1];
address->person[j + 1] = temp;
}
}
}
return;
}
void ClearPerson(AddressBook* address) {
printf("清空通讯录,为危险操作!\n 1:清空 0:不清空\n");
int h = 0;
printf("请输入您的选择:");
scanf("%d", &h);
if (h == 0) {
return;
}
if (h == 1) {
for (int i = 0; i < address->size; i++) {
strcpy(address->person[i].name, "");
strcpy(address->person[i].gender, "");
strcpy(address->person[i].age, "");
strcpy(address->person[i].phonenum, "");
strcpy(address->person[i].address, "");
}
address->size = 0;
return;
}
}
AddressBook address; // 为全局变量,如果是局部变量,存放在栈里会内存不够。
int main() {
Inint(&address);
Load(&address); // 开始之读取之前的内容
// 建立转移表
typedef void(*Func)(AddressBook*);
Func fun_table[] = {
NULL,
AddPerson,
DelPerson,
FindPerson,
ModiPerson,
PrintPerson,
SortPerson,
ClearPerson,
};
while (1) {
int choice = Menu();
if (choice < 0 || choice >= sizeof(fun_table)/sizeof(fun_table[0])) {
printf("您的输入有误\n");
continue;
}
if (choice == 0) {
printf("退出!");
Save(&address); // 每次退出之前保存所有操作
break;
}
// 执行选择
if (choice > 0 && choice <= 7) {
fun_table[choice](&address);
}
continue;
}
system("pause");
return 0;
}
写代码的过程中需要注意结构之间成员的调用和复制问题,什么时候应该取地址复制,什么时候应该直接结构体成员赋值;注意函数调用中形参是实参的拷贝这一点;还有循环中多1 少 1 的问题。
代码只是实现问题的所述功能,当然还有更优化的代码和界面设计;如果该代码有错误,也请同志们多多指教,多多交流。