实现一个通讯录; 通讯录可以用来存储1000个人的信息,每个人的信息包括: 姓名、性别、年龄、电话、住址
提供方法1.添加联系人信息 2.删除指定联系人信息 3.查找指定联系人信息 4.修改指定联系人信息 5.显示所有联系人信息 6.清空所有联系人 7.以名字排序所有联系人 8. 保存联系人到文件 9. 加载联系人
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define PERSON_INFO_MAX_SIZE 1024
typedef struct PersonInfo{
char name[1024];
char phone[1024];
}PersonInfo;
typedef struct AddressBook{//结构体数组
PersonInfo infos[PERSON_INFO_MAX_SIZE];
int size;//描述数组中前多少个元素是被使用的,有效元素区间[0,size)
}AddressBook;
//我们将生活中的常识抽象成计算机中的语言
AddressBook g_address_book;
void Init(AddressBook* addr_book){
assert(addr_book != NULL);
addr_book-> size = 0;
}
void AddPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("插入一个联系人!\n");
if(addr_book->size >= PERSON_INFO_MAX_SIZE){
printf("当前通讯已满,插入失败!\n");
return;
}
//每次都把新的联系人放到有效数组的最后一个元素上
PersonInfo *p = &addr_book->infos[addr_book->size];
printf("请输入新增的联系人姓名:");
scanf("%s",p->name);
printf("请输入新增的联系人的电话:");
scanf("%s",p->phone);
//新增完成后,需要更新size
++addr_book->size;
printf("插入联系人成功!\n");
}
void DelPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("删除联系人!\n");
//根据用户输入的下标来删除联系人
printf("请输入要删除的联系人符号:");
int id = 0;
scanf("%d",&id);
if(id < 0 || id >= addr_book->size){
printf("您输入的序号有误!删除失败!\n");
return;
}
PersonInfo *p = &addr_book->infos[id];
printf("您要删除的联系人为[%d] %s,确认请输入Y:",id,p->name);
char cmd[1024] = {0};
scanf("%s",cmd);
if(strcmp(cmd, "Y") != 0){
printf("删除操作已经取消!\n");
return;
}
PersonInfo* from = &aaddr_book->infos[addr_book->size - 1];
PersonInfo* to = p;
*to = *from;
--addr_book->size;
printf("删除成功!\n");
}
void ModifyPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("修改联系人\n");
printf("请输入需要修改的联系人序号:");
int id = 0;
scanf("%d",&id);
if(id < 0 || id >= addr_book->size){
printf("您输入的序号错误");
return;
}
PersonInfo *p = &addr_book->infos[id];
char input[1024] = {0};
printf("请输入要修改的姓名:");
scanf("%s",input);
if(strcmp(input,"#") != 0){
strcpy(p->name,input);
}
printf("请输入要修改的电话:");
scanf("%s",input);
if(strcmp(input,"#") != 0){
strcpy(p->phone,input);
}
printf("修改成功!\n");
}
void FindPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("开始进行查找!\n");
printf("请输入要查找的姓名:");
char name[1024] = {0};
scanf("%s",name);
int count = 0;
for(int i = 0;i < addr_book->size;++i){
PersonInfo* p = &addr_book->infos[i];
if(strcmp(name,p->name) == 0){
printf("[%d] %s\t%s\n",i,p->name,p->phone);
++count;
}
}
printf("查找完毕!共找到 %d 条记录!\n",count);
}
void SortPersonInfo(AddressBook* addr_book){//只适用于英文名字的排序
assert(addr_book != NULL);
int i = 0;
int j = 0;
for(i = 0;i < addr_book->size;++i){
for(j = 0;j < addr_book->size - 1 - i;j++){
if(strcmp(addr_book->infos[j].name,addr_book->infos[j + 1].name) > 0){
PersonInfo tmp;
tmp = addr_book->infos[j];
addr_book->infos[j] = addr_book->infos[j + 1];
addr_book->infos[j + 1] = tmp;
}
}
}
}
void PrintAllPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
for(int i = 0;i < addr_book->size;++i){
PersonInfo* p = &addr_book->infos[i];
printf("[%d] %s\t%s\n",i ,p->name,p-phone);
}
}
void ClearPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("清空所有记录!\n");
printf("您确认要清空所有记录吗?输入 Y 表示确定");
char cmd[1024] = {0};
scanf("%s",&cmd);
if(strcmp(cmd,"Y") != 0){
printf("清空操作取消");
return;
}
addr_book->size = 0;
printf("清空操作成功!\n");
}
int Menu(){
printf("=================");
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("=================");
int choice = 0;
scanf("%d",&choice);
return choice;
}
int main(){
//1.对通讯录进行初始化
Init(&g_address_book);
typedef void(*pfunc_t)(AddressBook*);
pfunc_t table[] = {
AddPersonInfo,
DelPersonInfo,
ModifyPersonInfo,
FindPersonInfo,
SortPersonInfo,
PrintAllPersonInfo,
ClearPersonInfo
}
while(1){
int choice = Menu();
if(choice < 0 || choice > (int)(sizeof(table) / sizeof(table[0]))){
printf("您的输入有误!\n")
}
if(choice == 0){
printf("goodbye!\n");
break;
}
table[choice - 1](&g_address_book);
}
return 0;
}
这个通讯录只是一个静态的,此时还可以进行一些改版,将其变为动态结合的,这时候可利用到malloc函数
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define PERSON_INFO_MAX_SIZE 1024
typedef struct PersonInfo{
char name[1024];
char phone[1024];
}PersonInfo;
typedef struct AddressBook{//结构体数组
PersonInfo* infos;
int capacity;//容量,infos指针指向的动态数组的长度(元素个数)
int size;//描述数组中前多少个元素是被使用的,有效元素区间[0,size)
}AddressBook;
//我们将生活中的常识抽象成计算机中的语言
AddressBook g_address_book;
void Init(AddressBook* addr_book){
assert(addr_book != NULL);
addr_book-> size = 0;
addr_book->capacity = 10;
addr_book->infos = (PersonInfo*)malloc(sizeof(PersonInfo) * addr_book->capacity);
}
void Realloc(AddressBook* addr_book){
assert(addr_book != NULL);
//此处每次扩容多少,这样的策略完全是我们自定制的
//1.扩大capacity的取值
addr_book->capacity *= 2;
//2.申请一个更大的内存
PersonInfo* old_infos = addr_book->infos;
addr_book->infos = (PersonInfo*)malloc(addr_book->capacity * sizeof(PersonInfo));
//3.把原有的内存中的数据复制过来
for(int i = 0;i < addr_book->size;++i){
addr_book->infos[i] = old_infos[i];
}
//4.释放原有的内存
free(old_infos);
}
void AddPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("插入一个联系人!\n");
if(addr_book->size >= addr_book->capacity){
printf("当前通讯已满,插入失败!进行扩容!\n");
Realloc(addr_book);
}
//每次都把新的联系人放到有效数组的最后一个元素上
PersonInfo *p = &addr_book->infos[addr_book->size];
printf("请输入新增的联系人姓名:");
scanf("%s",p->name);
printf("请输入新增的联系人的电话:");
scanf("%s",p->phone);
//新增完成后,需要更新size
++addr_book->size;
printf("插入联系人成功!\n");
}
void DelPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("删除联系人!\n");
//根据用户输入的下标来删除联系人
printf("请输入要删除的联系人符号:");
int id = 0;
scanf("%d",&id);
if(id < 0 || id >= addr_book->size){
printf("您输入的序号有误!删除失败!\n");
return;
}
PersonInfo *p = &addr_book->infos[id];
printf("您要删除的联系人为[%d] %s,确认请输入Y:",id,p->name);
char cmd[1024] = {0};
scanf("%s",cmd);
if(strcmp(cmd, "Y") != 0){
printf("删除操作已经取消!\n");
return;
}
PersonInfo* from = &aaddr_book->infos[addr_book->size - 1];
PersonInfo* to = p;
*to = *from;
--addr_book->size;
printf("删除成功!\n");
}
void ModifyPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("修改联系人\n");
printf("请输入需要修改的联系人序号:");
int id = 0;
scanf("%d",&id);
if(id < 0 || id >= addr_book->size){
printf("您输入的序号错误");
return;
}
PersonInfo *p = &addr_book->infos[id];
char input[1024] = {0};
printf("请输入要修改的姓名:");
scanf("%s",input);
if(strcmp(input,"#") != 0){
strcpy(p->name,input);
}
printf("请输入要修改的电话:");
scanf("%s",input);
if(strcmp(input,"#") != 0){
strcpy(p->phone,input);
}
printf("修改成功!\n");
}
void FindPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("开始进行查找!\n");
printf("请输入要查找的姓名:");
char name[1024] = {0};
scanf("%s",name);
int count = 0;
for(int i = 0;i < addr_book->size;++i){
PersonInfo* p = &addr_book->infos[i];
if(strcmp(name,p->name) == 0){
printf("[%d] %s\t%s\n",i,p->name,p->phone);
++count;
}
}
printf("查找完毕!共找到 %d 条记录!\n",count);
}
void SortPersonInfo(AddressBook* addr_book){//只适用于英文名字的排序
assert(addr_book != NULL);
int i = 0;
int j = 0;
for(i = 0;i < addr_book->size;++i){
for(j = 0;j < addr_book->size - 1 - i;j++){
if(strcmp(addr_book->infos[j].name,addr_book->infos[j + 1].name) > 0){
PersonInfo tmp;
tmp = addr_book->infos[j];
addr_book->infos[j] = addr_book->infos[j + 1];
addr_book->infos[j + 1] = tmp;
}
}
}
}
void PrintAllPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
for(int i = 0;i < addr_book->size;++i){
PersonInfo* p = &addr_book->infos[i];
printf("[%d] %s\t%s\n",i ,p->name,p-phone);
}
}
void ClearPersonInfo(AddressBook* addr_book){
assert(addr_book != NULL);
printf("清空所有记录!\n");
printf("您确认要清空所有记录吗?输入 Y 表示确定");
char cmd[1024] = {0};
scanf("%s",&cmd);
if(strcmp(cmd,"Y") != 0){
printf("清空操作取消");
return;
}
addr_book->size = 0;
printf("清空操作成功!\n");
}
int Menu(){
printf("=================");
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("=================");
int choice = 0;
scanf("%d",&choice);
return choice;
}
int main(){
//1.对通讯录进行初始化
Init(&g_address_book);
typedef void(*pfunc_t)(AddressBook*);
pfunc_t table[] = {
AddPersonInfo,
DelPersonInfo,
ModifyPersonInfo,
FindPersonInfo,
SortPersonInfo,
PrintAllPersonInfo,
ClearPersonInfo
}
while(1){
int choice = Menu();
if(choice < 0 || choice > (int)(sizeof(table) / sizeof(table[0]))){
printf("您的输入有误!\n")
}
if(choice == 0){
printf("goodbye!\n");
break;
}
table[choice - 1](&g_address_book);
}
return 0;
}
在扩容过程中,我们经过分析之后,当内存不够时,考虑到只有添加才需要开辟新的空间。
所以在第一个静态的版本之上,又加入了动态开辟,这样当添加不够时,我们的程序会自动开辟新的空间,为了当前能够使用。
在代码中有注释,关于开辟的关键。
内存中原先保存的位置我们也要管理,否则会造成内存泄漏。