当前位置:网站首页>【C语言】通讯录(动态版+文件版)
【C语言】通讯录(动态版+文件版)
2022-08-05 16:43:00 【沐曦希】
大家好我是沐曦希
1.前言
即便动态版本的通讯录能更改通讯录内存的大小,但是一样具有一定的缺陷,便是不能在程序关闭的时候,对通讯录进行保存。那么现在我们可以根据前面所学到文件操作和动态版本的通讯录进行优化,把通讯录保存在文件中。
2.文件功能实现
2.1 保存通讯录的信息
在退出程序时候,应该进行保存通讯录的信息的操作,那么就需要我们写一个函数来实现这个功能
void SaveContact(const struct Contact* pc)
{
assert(pc);
FILE* pfwrite = fopen("contact.txt", "wb");
if (pfwrite == NULL)
{
perror("SaveContact");
return;
}
//写文件二进制
int i = 0;
for (i = 0; i < pc->count; i++)
{
fwrite(pc->data+i, sizeof(PeoIoFo), 1, pfwrite);
}
fclose(pfwrite);
pfwrite = NULL;
}
通过二进制形式写入,可以一定程度减少内存的占用。
2.2 初始化通讯录
void CheckCapacity(Contact* pc)
{
if (pc->count == pc->capacity)
{
PeoIoFo* ptr = (PeoIoFo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoIoFo));
if (ptr == NULL)
{
printf("AddContact::%s\n", strerror(errno));
return;
}
else
{
pc->data = ptr;
pc->capacity += 2;
printf("增容成功\n");
}
}
}
void LodeContact(struct Contact* pc)
{
FILE* pfread = fopen("Contact.txt", "rb");
if (pfread == NULL)
{
perror("LodeContact");
return;
}
PeoIoFo tmp = {
0 };
while (fread(&tmp, sizeof(PeoIoFo), 1, pfread))
{
CheckCapacity(pc);
pc->data[pc->count] = tmp;
pc->count++;
}
fclose(pfread);
pfread = NULL;
}
int InitContact(struct Contact* pc)
{
assert(pc);
pc->count = 0;
pc->data = (PeoIoFo*)calloc(3, sizeof(PeoIoFo));
if (pc->data == NULL)
{
printf("InitContact:%s\n", strerror(errno));
return 1;
}
pc->capacity = 3;
//加载文件的信息到通讯录中
LodeContact(pc);
return 0;
}
在初始化通讯录后,应该将文件中保存的通讯录信息进行复制到现在的通讯录当中,那么就需要一个函数来实现。
LodeContact中while循环通过判断fread返回值是否为0来确定通讯录的信息是否被读取完。
当然也要检测当前通讯录是否有足够大的空间来存储文件中的通讯录的信息,不够则用realloc函数来增大空间。
3.完整代码
contact.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
typedef struct PeoIoFo
{
char name[20];
int age;
char sex[10];
char tele[12];
char addr[20];
}PeoIoFo;
typedef struct Contact
{
struct PeoIoFo* data;
int count;
//当前通讯录的容量
int capacity;
}Contact;
//初始化通讯录
int InitContact(struct Contact* pc);
//添加联系人信息
void AddContact(struct Contact* pc);
//打印联系人信息
void ShowContact(const struct Contact* pc);
//删除联系人信息
void DelContact(struct Contact* pc);
//查找联系人
void SearchContact(const struct Contact* pc);
//修改联系人信息
void ModifyContact(struct Contact* pc);
//排序联系人信息
void SortContact(struct Contact* pc);
//清空所有联系人
void AlldelContact(struct Contact* pc);
//销毁所有联系人信息
void DestroyContact(struct Contact* pc);
//存储联系人信息
void SaveContact(const struct Contact* pc);
//加载文件的联系人信息
void LodeContact(struct Contact* pc);
test.c
#include"contact.h"
void menu()
{
printf("**********************************\n");
printf("****** 1.Add 2.Del *****\n");
printf("****** 3.search 4.modify *****\n");
printf("****** 5.show 6.sort *****\n");
printf("****** 0.exit 7.alldel ******\n");
printf("**********************************\n");
}
int main()
{
struct Contact Con;
InitContact(&Con);
int input = 0;
do {
menu();
printf("请输入选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
AddContact(&Con);
break;
case 2:
DelContact(&Con);
break;
case 3:
SearchContact(&Con);
break;
case 4:
ModifyContact(&Con);
break;
case 5:
ShowContact(&Con);
break;
case 6:
SortContact(&Con);
break;
case 7:
AlldelContact(&Con);
break;
case 0:
SaveContact(&Con);
printf("退出通讯录\n");
DestroyContact(&Con);
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
return 0;
}
contact.c
#include"contact.h"
void menu1()
{
printf("1.名字\n");
printf("2.年龄\n");
printf("3.性别\n");
printf("4.电话号码\n");
printf("5.地址\n");
printf("0.退出\n");
}
void ModifyName(Contact* pc, int ret)
{
printf("请输入更改后的名字:>");
scanf("%s", pc->data[ret].name);
}
void ModifyAge(Contact* pc, int ret)
{
printf("请输入更改后的年龄:>");
scanf("%d", &(pc->data[ret].age));
}
void ModifySex(Contact* pc, int ret)
{
printf("请输入更改后的性别:>");
scanf("%s", pc->data[ret].sex);
}
void ModifyTele(Contact* pc, int ret)
{
printf("请输入更改后的电话号码:>");
scanf("%s", pc->data[ret].tele);
}
void ModifyAddr(Contact* pc, int ret)
{
printf("请输入更改后的地址:>");
scanf("%s", pc->data[ret].addr);
}
void CheckCapacity(Contact* pc)
{
if (pc->count == pc->capacity)
{
PeoIoFo* ptr = (PeoIoFo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoIoFo));
if (ptr == NULL)
{
printf("AddContact::%s\n", strerror(errno));
return;
}
else
{
pc->data = ptr;
pc->capacity += 2;
printf("增容成功\n");
}
}
}
void LodeContact(struct Contact* pc)
{
FILE* pfread = fopen("Contact.txt", "rb");
if (pfread == NULL)
{
perror("LodeContact");
return;
}
PeoIoFo tmp = {
0 };
while (fread(&tmp, sizeof(PeoIoFo), 1, pfread))
{
CheckCapacity(pc);
pc->data[pc->count] = tmp;
pc->count++;
}
fclose(pfread);
pfread = NULL;
}
int InitContact(struct Contact* pc)
{
assert(pc);
pc->count = 0;
pc->data = (PeoIoFo*)calloc(3, sizeof(PeoIoFo));
if (pc->data == NULL)
{
printf("InitContact:%s\n", strerror(errno));
return 1;
}
pc->capacity = 3;
//加载文件的信息到通讯录中
LodeContact(pc);
return 0;
}
static int FindName(const Contact* pc, char name[])
{
assert(pc);
int i = 0;
for (i = 0; i < pc->count; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
return i;
}
return -1;
}
static void print(const Contact* pc, int ret)
{
printf("%-20s\t%-3s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话号码", "地址");
printf("%-20s\t%-3d\t%-5s\t%-12s\t%-20s\n", pc->data[ret].name,
pc->data[ret].age,
pc->data[ret].sex,
pc->data[ret].tele,
pc->data[ret].addr);
}
void AddContact(struct Contact* pc)
{
assert(pc);
if (pc->capacity == pc->count)
{
PeoIoFo* ptr = (PeoIoFo*)realloc(pc->data, sizeof(PeoIoFo) * (pc->capacity + 2));
if (ptr == NULL)
{
printf("%s\n", strerror(errno));
return;
}
else
{
pc->data = ptr;
pc->capacity += 2;
printf("增容成功!\n");
}
}
printf("请输入需要添加联系人的名字:>");
scanf("%s", pc->data[pc->count].name);
printf("请输入需要添加联系人的年龄:>");
scanf("%d", &(pc->data[pc->count].age));
printf("请输入需要添加联系人的性别:>");
scanf("%s", pc->data[pc->count].sex);
printf("请输入需要添加联系人的电话号码:>");
scanf("%s", pc->data[pc->count].tele);
printf("请输入需要添加联系人的地址:>");
scanf("%s", pc->data[pc->count].addr);
pc->count++;
printf("增加成功!\n");
}
void ShowContact(const struct Contact* pc)
{
assert(pc);
if (pc->count == 0)
{
printf("通讯录为空,没有联系人信息可以打印!\n");
return;
}
int i = 0;
printf("%-20s\t%-3s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话号码", "地址");
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-3d\t%-5s\t%-12s\t%-20s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
void DelContact(struct Contact* pc)
{
char name[20] = {
'\0' };
assert(pc);
if (pc->count == 0)
{
printf("通讯录为空,没有联系人可以删除!\n");
return;
}
printf("请输入需要删除人的名字:>");
scanf("%s", name);
int ret = FindName(pc, name);
if (ret == -1)
{
printf("通讯录上无此联系人!\n");
return;
}
int i = 0;
for (i = ret; i < pc->count - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->count--;
printf("删除联系人成功!\n");
}
void SearchContact(const struct Contact* pc)
{
assert(pc);
char name[20];
if (pc->count == 0)
{
printf("通讯录为空,没有联系人可以查找!\n");
return;
}
printf("请输入需要查找的联系人的姓名:>");
scanf("%s", name);
int ret = FindName(pc, name);
if (ret == -1)
{
printf("通讯录上没有此联系人!\n");
return;
}
printf("找到该联系人:\n");
print(pc, ret);
}
void ModifyContact(struct Contact* pc)
{
assert(pc);
char name[20];
if (pc->count == 0)
{
printf("通讯录为空,没有联系人可以修改!\n");
return;
}
printf("请输入需要修改的联系人的姓名:>");
scanf("%s", name);
int ret = FindName(pc, name);
if (ret == -1)
{
printf("通讯录上无此联系人!\n");
return;
}
printf("找到该联系人:\n");
print(pc, ret);
int input = 0;
do
{
menu1();
printf("请输入选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
ModifyName(pc, ret);
printf("修改后:>\n");
print(pc, ret);
break;
case 2:
ModifyAge(pc, ret);
printf("修改后:>\n");
print(pc, ret);
break;
case 3:
ModifySex(pc, ret);
printf("修改后:>\n");
print(pc, ret);
break;
case 4:
ModifyTele(pc, ret);
printf("修改后:>\n");
print(pc, ret);
break;
case 5:
ModifyAddr(pc, ret);
printf("修改后:>\n");
print(pc, ret);
break;
case 0:
printf("退处修改!\n");
break;
default:
break;
}
} while (input);
}
int cmp_Name(const void* e1, const void* e2)
{
return strcmp(((PeoIoFo*)e1)->name, ((PeoIoFo*)e2)->name);
}
int cmp_int(const void* e1, const void* e2)
{
return (((PeoIoFo*)e1)->age - ((PeoIoFo*)e2)->age);
}
int cmp_Sex(const void* e1, const void* e2)
{
return strcmp(((PeoIoFo*)e1)->sex, ((PeoIoFo*)e2)->sex);
}
int cmp_Tele(const void* e1, const void* e2)
{
return strcmp(((PeoIoFo*)e1)->tele, ((PeoIoFo*)e2)->tele);
}
int cmp_Addr(const void* e1, const void* e2)
{
return strcmp(((PeoIoFo*)e1)->addr, ((PeoIoFo*)e2)->addr);
}
void SortContact(struct Contact* pc)
{
if (pc->count == 0)
{
printf("通讯录为空,无需进行排序!\n");
return;
}
int input = 0;
do
{
menu1();
printf("请输入选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
qsort(pc->data, pc->count, sizeof(PeoIoFo), cmp_Name);
printf("排序后:>\n");
ShowContact(pc);
break;
case 2:
qsort(pc->data, pc->count, sizeof(PeoIoFo), cmp_int);
printf("排序后:>\n");
ShowContact(pc);
break;
case 3:
qsort(pc->data->sex, pc->count, sizeof(PeoIoFo), cmp_Sex);
printf("排序后:>\n");
ShowContact(pc);
break;
case 4:
qsort(pc->data->sex, pc->count, sizeof(PeoIoFo), cmp_Tele);
printf("排序后:>\n");
ShowContact(pc);
break;
case 5:
qsort(pc->data->sex, pc->count, sizeof(PeoIoFo), cmp_Addr);
printf("排序后:>\n");
ShowContact(pc);
break;
case 0:
printf("退处修改!\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
}
void AlldelContact(struct Contact* pc)
{
assert(pc);
realloc(pc->data, sizeof(PeoIoFo) * 3);
memset(pc->data, 0, 3 * sizeof(PeoIoFo));
pc->count = 0;
pc->capacity = 3;
}
void DestroyContact(Contact* pc)
{
assert(pc);
free(pc->data);
pc->data = NULL;
}
void SaveContact(const struct Contact* pc)
{
assert(pc);
FILE* pfwrite = fopen("contact.txt", "wb");
if (pfwrite == NULL)
{
perror("SaveContact");
return;
}
//写文件二进制
int i = 0;
for (i = 0; i < pc->count; i++)
{
fwrite(pc->data+i, sizeof(PeoIoFo), 1, pfwrite);
}
fclose(pfwrite);
pfwrite = NULL;
}
4.写在最后
那么动态版本+文件版本的通讯录到这里就结束啦
边栏推荐
猜你喜欢

HDBaseT是什么协议?与SDI和HDMI比较有哪些区别?

MASA Stack 第三期社区例会

机器人强化学习——COCOI: Contact-aware Online Context Inference for Generalizable Non-planar Pushing(21 ICRA)

stm32f103开发板入门到手进行开发

高质量 DeFi 应用构建指南,助力开发者玩转 DeFi Summer

数据库篇——hash索引

【案例】一个熊在跑的动画animation

解决FileZilla 报错“无法和 SFTP 服务器建立 FTP 连接,请选择合适的协议”

EasyCVR calls the stop real-time recording interface, how to solve the problem that the recording address is not returned?

一个程序员的水平能差到什么程度?
随机推荐
High Numbers_Proof_Intermediate Value Theorem
三菱FX3U PLC模拟量输出FB (FX2N-4DA)
图像处理:边缘检测
eureka服务单节点搭建以及集群的搭建
The annual gas transmission volume of the West-East Gas Pipeline exceeds 100 billion cubic meters for the first time, and Tupu helps pipeline monitoring
25个 Web3 社交项目详细信息汇总(SocialFi)
二叉树高度
【2022新生学习】第四周要点
vu2 尚硅谷 组件化编程
堆叠柱状图轻松高效制图
uniapp中页面跳转的几种方式及生命周期(整理)
图像边缘检测——一阶微分算子 Roberts、Sobel、Prewitt、Kirsch、Robinson
Registered less than a week for data security in the British parliament TikTok dispute the substance is discontinued
[uvm]create_item ???
【Case】Animation animation
Mapping of gpnmb+ gpnmb- AT2 cells on idling Mapping----version 3.2.2seurat
The high number of _ _ the most value theorem
Basic Concepts in Network Communication
【Case】3d photo album
Instant messaging development long connection gateway technology: WebSocket real-time push gateway technology