效果展示
实现功能:
1.添加联系人信息
2.删除联系人信息
3.查找指定联系人信息
4.修改指定联系人信息
5.显示所有联系人信息
6.清空所有联系人信息
7.排序所有联系人
8.自动保存读取通讯录内容
设计思路:
动态思想:
1.储存类型:当然是结构体了;
2.动态存储:实现动态存储即需要用到空间的申请malloc和修改relloc(这两个函数前面博客有提到哦),这两个函数提供了增长的能力,那么怎么进行增长呢,这时候就需要两个结构体了。
一个用来囊括所需要的所有成员变量,另一个囊括用来指向第一个结构体的指针,当前成员个数的计数器,当前开辟多少空间的计数器;
通过两个计数器的比较就知道是否需要开辟空间了;
功能实现:
首先得先写一个空间开辟函数,即给定义的结构体变量先开辟一块内存空间;
1.添加联系人信息:
这里得先写一个空间判断函数,判断当前开辟的空间容量是否足够,不够就再开辟2个联系人空间,再进行数据输入,每输入一个人的信息,计数器加1;
2.删除联系人信息:
删除之前写一个通过名字查询联系人的函数,通过返回值判断是否找到,找到了再执行删除,这里删除的方式是进行覆盖,即将后面空间的内容覆盖掉前面的内容,同时当前成员计数器的数值减1
3.查找指定联系人信息:
通过输入名字,利用strcmp函数进行比较,找到了就返回下标进行打印出来
4.修改联系人信息:
利用查找联系人函数来返回找到的下标,再利用switch进行循环选择修改的信息
5.显示所有成员信息:
通过当前的成员计数器,利用for函数将全部成员信息进行输出(指针+数字的方式访问元素);
6.清空所有联系人:
将申请的动态空间利用free函数释放掉,再将两个计数器重置;
7.排序所有联系人:
利用qsort函数进行排序操作
8.内容储存
创建一个记事本,在程序退出之前写入记事本之内,程序读取开辟空间的时候将数据读取出来;
#ifndef _TEST_H_
#define _TEST_H_
#include <stdio.h>
#include <windows.h>
#pragma warning (disable :4996)
#include <stdlib.h>
#define TWO 2
#define NUM 20
typedef struct LIST //可以储存的成员信息列表
{
char name[20];
char sex[20];
int age;
char tel[20];
char address[50];
}list;
typedef struct ADDRESS_BOOK
{
list *call;//调用信息表
int count;//表明存储个数
int capacity;//当前通讯录容量
}address;
void Menu();//菜单
void Add();//添加联系人信息
void Delect();//删除联系人信息
int Found();//找到并打印联系人信息
void Alter();//修改联系人信息
void Show();//显示所有联系人
void Empty();//清空所有联系人
void Rank();//以姓氏排序
void Open();//开辟空间函数
void Save_book();//将数据保存到磁盘之中
#endif
#include "test.h"
int main()
{
address book;//创建通讯录book
Open(&book);//给通讯录开辟空间
int select = 0;
while (!select)
{
Menu();
printf("请输入你的选择\n");
scanf("%d", &select);
getchar();
switch (select)
{
case 1:
system("cls");
Add(&book);//添加联系人,传址
select = 0;
break;
case 2:
system("cls");
Delect(&book);//删除联系人
select = 0;
break;
case 3:
system("cls");
Found(&book);//查找
select = 0;
break;
case 4:
system("cls");
Alter(&book);//修改
select = 0;
break;
case 5:
system("cls");
Show(&book);//显示
select = 0;
break;
case 6:
system("cls");
Empty(&book);//清空
select = 0;
break;
case 7:
system("cls");
Rank(&book);//以姓氏排序
select = 0;
break;
case 8:
select = 1;
Save_book(&book);
break;//退出
default:
printf("输入有误\n");
select = 0;
}
}
system("pause");
return 0;
}
#include "test.h"
void Menu()
{
printf("###1.添加联系人信息############2.删除指定联系人信息####################\n");
printf("###3.查找指定联系人信息#########4.修改指定人信息#######################\n");
printf("###5.显示所有联系人信息#########6.清空所有联系人#######################\n");
printf("###7.以名字排序所有联系人#######8.退出#################################\n");
}
int Comp(char name[],address *sp)//寻找对应的名字;
{
int i = 0;
for (i = 0; i < sp->count; i++)
{
if ((strcmp(sp->call[i].name, name)) == 0)
return i;//返回找到的下标;
}
return -1;//找不到返回-1
}
void Save_book(address *sp)//存储信息函数
{
FILE *fp = fopen("book.log", "wb");//打开文件
if (fp == NULL)
{
return ;
}
fwrite(sp, sizeof(address), 1, fp);//保存通讯录
fwrite(sp->call, sizeof(list), sp->capacity, fp);//保存开辟出来的空间之中的内容
fclose(fp);
}
void Open(address *p)//开辟空间函数
{
FILE *fp = fopen("book.log", "rb");//打开文件
if (fp == NULL)//没有文件则开辟空间
{
p->call = (list *)malloc(TWO*sizeof(list));//宏TWO=2,给调用信息表的指针分配内存
if (p->call != NULL)
{
p->count = 0;//记录存储个数的计数器count
p->capacity = 2;//开辟空间容量计数器,每次开辟空间提供2次存储机会;
}
}
else//有文件则读取数据
{
printf("读取数据中\n");
address temp;
fread(&temp, sizeof(address), 1, fp);//读取通讯录address
int size = sizeof(list)*temp.capacity;//读取出来的空间大小
p->capacity = temp.capacity;
p->count = temp.count;
p->call= (list *)malloc(size);//开辟空间
if (p->call == NULL)
{
exit(1);
}
fread(p->call, sizeof(list), p->capacity, fp);
fclose(fp);
printf("读取成功\n");
}
}
static void Judge(address *sp)//进行空间容量判断
{
if (sp->capacity == 0)//清空了通讯录重新开辟空间;
{
sp->call = (list *)malloc(TWO*sizeof(list));//宏TWO=2,给调用信息表的指针分配内存
if (sp->call != NULL)
{
sp->count = 0;//记录存储个数的计数器count
sp->capacity = 2;//开辟空间容量计数器,每次开辟空间提供2次存储机会;
}
}
else if (sp->count == sp->capacity)//上次开辟的内存满了
{
list *dst = (list *)realloc(sp->call,(sp->capacity+TWO)*sizeof(list));//增加两个空间;
if (dst != NULL)
{
sp->call = dst;//将开辟成功的地址返回给原指针
sp->capacity += 2;//空间容量计数器+2;
}
}
}
void Add(address *p)//增加函数
{
Judge(p);//进行空间判断是否足够;
printf("请输入联系人姓名\n");
scanf("%s", p->call[p->count].name);
printf("请输入联系人性别\n");
scanf("%s", p->call[p->count].sex);
printf("请输入联系人年龄\n");
scanf("%d", &(p->call[p->count].age));
printf("请输入联系人电话\n");
scanf("%s", p->call[p->count].tel);
printf("请输入联系人住址\n");
scanf("%s", p->call[p->count].address);
p->count++;//计数器+1;
}
void Delect(address *p)//删指定人函数
{
int i = 0;//接收查找的人
char name[20];
printf("请输入要删除的指定人的名字\n");
scanf("%s", name);
i = Comp(name,p);
if (i == -1)
{
printf("查无此人\n");
}
else
{
Judge(p);//进行空间判定,避免越界;
for (i; i < p->count; i++)//覆盖,利用后面的数据将前面的数据全部覆盖;
{
p->call[i] = p->call[i + 1];
}
p->count--;//成员减1,计数器减1
printf("删减成功\n");
}
}
int Found(address *p)//查找成员
{
char name[NUM];
printf("请输入你要查找的名字\n");
scanf("%s", name);
int j = Comp(name,p);//接收返回值,找到返回值为对应的成员下标
if (j == -1)
{
printf("查无此人\n");
}
else
printf("姓名:%s 性别:%s 年龄:%d 电话:%s 住址:%s\n", p->call[j].name,
p->call[j].sex,p->call[j].age,p->call[j].tel,p->call[j].address);
return j;//方便Alter函数调用
}
void Alter(address *p)//修改指定人信息
{
int select = 0;
char newname[NUM];//需要修改的名字
char newsex[NUM];//需要修改的性别
int neweag;//需要修改的年龄
char newtel[NUM];//需要修改的电话
char newaddress[NUM];//需要修改的地址;
int j=Found(p);//先找到这个人
if (j !=-1)
{
while (!select)
{
printf("请选择需要修改的信息\n");
printf("********************************\n");
printf("**1.姓名**********2.性别*********\n");
printf("**3.年龄**********4.电话*********\n");
printf("**5.住址**********6.退出*********\n");
printf("********************************\n");
scanf("%d", &select);
switch (select)
{
case 1:
printf("请输入新的姓名\n");
scanf("%s", newname);
strcpy(p->call[j].name, newname);
select = 0;
break;
case 2:
printf("请输入新的性别\n");
scanf("%s", newsex);
strcpy(p->call[j].sex, newsex);
select = 0;
break;
case 3:
printf("请输入新的年龄\n");
scanf("%d", &neweag);
p->call[j].age = neweag;
select = 0;
break;
case 4:
printf("请输入新的电话\n");
scanf("%s", newtel);
strcpy(p->call[j].tel, newtel);
select = 0;
break;
case 5:
printf("请输入新的住址\n");
scanf("%s", newaddress);
strcpy(p->call[j].address, newaddress);
select = 0;
break;
case 6:
select = 1;
break;
default:
printf("输入有误,从新输入\n");
select = 0;
break;
}
}
}
}
void Show(address *p)//显示所有人信息
{
if (p->count == 0)
printf("联系人列表为空\n");
for (int j = 0; j < p->count; j++)//将第一个到最后一个有信息的名单打印出来
{
printf("姓名:%s 性别:%s 年龄:%d 电话:%s 住址:%s\n", p->call[j].name,
p->call[j].sex, p->call[j].age, p->call[j].tel, p->call[j].address);
}
}
void Empty(address *p)//清空通讯录
{
free(p->call);//释放掉申请的内存
p->count = 0;//计数器归零
p->capacity;//容量计数器归零
}
static int Compar(const list *x, const list *y)//排序回调函数
{
return strcmp(x->name, y->name);
}
void Rank(address *p)
{
if (p->count==0)
{
printf("联系人列表为空\n");
}
else
qsort(p->call->name, p->count, sizeof(list), Compar);//利用qsort进行排序;
}