当前位置:网站首页>通讯录的实现(文件版本)
通讯录的实现(文件版本)
2022-07-02 09:41:00 【每天少点debug】
设计需求
每个人的信息不仅仅有号码,我们还可以设计性别年龄啥的,所以主体我们选择的是一个结构体
struct info
{
char name[MAX_NAME];
char sex[MAX_SEX];
char phone[MAX_PHONENUMBER];
char address[MAX_ADDRESS];
int age;
};
设计通讯录的话动态版本的比较好,所以我们在原来的结构体上再加上一个结构体
struct contact
{
struct info* data;
int sz;
int capacity;
};
其中capacity表示的是容量大小,sz表示的是通讯录中目前的联系人个数,当capacity==sz时此时需要扩容
Test.c
首先我们要写一个枚举常量
enum choice
{
EXIT,//退出
ADD,//添加联系人
DEL,//删除联系人
SEARCH,//查找联系人
MODIFY,//修改通讯录
SHOW,//展示通讯录
CLEAR,//清除通讯录
SORT//给通讯录排序
};
没有赋值的话默认从0开始,这样的话即使其他人只看到我们这一个文件也能马上理解数字的选项所代表的含义。
然后就是一些类似于之前的常规操作
void menu()
{
printf("****************************************************************************\n");
printf("***********************0.退出通讯录*******1.添加联系人***********************\n");
printf("***********************2.删除联系人*******3.查找联系人***********************\n");
printf("***********************4.修改联系人********5.展示通讯录**********************\n");
printf("***********************6.格式化通讯录******7,整理排序联系人*******************\n");
printf("******************************************************************************\n");
}
int main()
{
struct contact con;
//初始化通讯录
Init_Contact(&con);
int input = 0;
int size = 0;//记录当前有多少人
do
{
menu();
printf("请选择->\n");
scanf("%d", &input);
switch (input)
{
case ADD:
Add_Contact(&con);
break;
case DEL:
Del_Contact(&con);
break;
case SEARCH:
Search_Contact(&con);
break;
case MODIFY:
Modify_Contact(&con);
break;
case SHOW:
system("cls");
Show_Contact(&con);
break;
case CLEAR:
Clear_Contact(&con);
break;
case SORT:
Sort_Contact(&con);
default :
printf("选择错误请重新选择->\n");
}
} while (input);
return 0;
}
contact.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<Windows.h>
#define MAX_NAME 20
#define MAX_AGE 20
#define MAX_PHONENUMBER 20
#define MAX_ADDRESS 20
#define MAX_SEX 10
#define DEFAULT_SZ 3
struct info
{
char name[MAX_NAME];
char sex[MAX_SEX];
char phone[MAX_PHONENUMBER];
char address[MAX_ADDRESS];
int age;
};
struct contact
{
struct info* data;
int sz;
int capacity;
};
//初始化通讯录
void Init_Contact(struct contact* pf);
//判断通讯录是否需要扩容
void Check_Capacity(struct contact* pf);
//添加联系人
void Add_Contact(struct contact* pf);
void Show_Contact(struct contact* pf);//打印通讯录
void Del_Contact(struct contact* pf);//删除联系人
void Search_Contact(struct contact* pf);//查找联系人
void Modify_Contact(struct contact* pf);//修改联系人
void Clear_Contact(struct contact* pf);//格式化通讯录
void Sort_Contact(struct contact* pf);//对通讯录中的联系人进行排序
void Save_Contact(struct contact* pf);//将通讯录中的内容保存到文件中
contact.c
重点讲两个函数
1,将通讯录中的内容保存到文件中
存储用的是二进制存储:
因为文本文件与二进制文件的区别仅仅是编码上不同,所以他们的优缺点就是编码的优缺点,这个找本编码的书来看看就比较清楚了。一般认为,文本文件编码基于字符定长,译码容易些;二进制文件编码是变长的,所以它灵活,存储利用率要高些,译码难一些(不同的二进制文件格式,有不同的译码方式)。关于空间利用率,想想看,二进制文件甚至可以用一个比特来代表一个意思(位操作),而文本文件任何一个意思至少是一个字符
即存储不存在转换时间(读写不要编解码,直接写值),所以我们用二进制的存储。其他的话只需要了解fwrite和fread就可以了
void Save_Contact(struct contact* pf)//将通讯录中的内容保存到文件中
{
assert(pf);
FILE* ps = fopen("contact.txt", "wb");
if (ps == NULL)
{
printf("文件打开失败\n");
return;
}
int i = 0;
for (i = 0; i < pf->sz; i++)
{
fwrite(&(pf->data[i]), sizeof(struct info), 1, ps);//将结构体数据写入文件中
}
printf("通讯录保存成功!\n");
fclose(ps);
ps = NULL;
}
2,初始化通讯录
初始化通讯录的时候就要把文件中通讯录的内容导入到结构体中,因为不排除一开始就查看通讯录。
void Init_Contact(struct contact* pf)//初始化通讯录还需要将文件中的内容导入到结构体中
{
pf->data = (struct info*)malloc(sizeof(struct info) * 3);
if (pf->data == NULL)
{
printf("通讯录初始化错误\n");
return 0;
}
pf->sz = 0;
pf->capacity = DEFAULT_SZ;
FILE* ps = fopen("contact.txt", "rb");
if (ps == NULL)
{
printf("文件打开失败\n");
return;
}
while (fread(&(pf->data[pf->sz]), sizeof(struct info), 1, ps))
{
Check_Capacity(pf);
pf->sz++;
}
}
完整contact.c代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
void Init_Contact(struct contact* pf)//初始化通讯录还需要将文件中的内容导入到结构体中
{
pf->data = (struct info*)malloc(sizeof(struct info) * 3);
if (pf->data == NULL)
{
printf("通讯录初始化错误\n");
return 0;
}
pf->sz = 0;
pf->capacity = DEFAULT_SZ;
FILE* ps = fopen("contact.txt", "rb");
if (ps == NULL)
{
printf("文件打开失败\n");
return;
}
while (fread(&(pf->data[pf->sz]), sizeof(struct info), 1, ps))
{
Check_Capacity(pf);
pf->sz++;
}
}
void Check_Capacity(struct contact* pf)
{
assert(pf);
if (pf->capacity == pf->sz)
{
//需要增容
struct inof*cur = (struct info*)realloc(pf->data, (pf->capacity + 2) * sizeof(struct info));
if (cur != NULL)
{
pf->data = cur;
pf->capacity += 2;
printf("增容成功\n");
}
else
{
printf("增容失败\n");
}
}
}
void Add_Contact(struct contact* pf)
{
//只要是添加联系人信息那么就得检查一下是否需要扩容
Check_Capacity(pf);
printf("请输入名字:\n");
scanf("%s", &(pf->data[pf->sz].name));
printf("请输入性别:\n");
scanf("%s", &(pf->data[pf->sz].sex));
printf("请输入年龄:\n");
scanf("%d", &(pf->data[pf->sz].age));
printf("请输入地址:\n");
scanf("%s", &(pf->data[pf->sz].address));
printf("请输入:号码\n");
scanf("%s", &(pf->data[pf->sz].phone));
pf->sz++;
printf("添加联系人成功!\n");
}
void Show_Contact(struct contact* pf)//打印通讯录
{
if (pf->sz == 0)
{
printf("通讯录为空!\n");
}
else
{
printf("%-20s\t%-5s\t%-4s\t%-30s\t%-13s\t\n", "姓名", "性别", "年龄", "地址", "号码");
int i = 0;
while (i < pf->sz)
{
//数据
printf("%-20s\t%-5s\t%-4d\t%-30s\t%-13s\t\n", pf->data[i].name, pf->data[i].sex,
pf->data[i].age, pf->data[i].address, pf->data[i].phone);
i++;
}
}
}
//根据名字查找联系人
int find_by_name(struct contact* pf, char* name)
{
int i = 0;
while (i < pf->sz)
{
if (strcmp(pf->data[i].name, name) == 0)
return i;
}
return -1;
}
void Del_Contact(struct contact* pf)//删除联系人
{
if (pf->sz == 0)
{
printf("通讯录为空,无法删除!\n");
}
else
{
char name[MAX_NAME];
printf("请输入要删除联系人的名字\n");
scanf("%s", name);
int pos = find_by_name(pf,name);
if (pos == -1)
{
printf("联系人不存在,请重新输入\n");
}
else
{
for (int j = pos; j < pf->sz - 1; j++)
pf->data[j] = pf->data[j + 1];
pf->sz--;
printf("删除联系人成功!\n");
}
}
}
void Search_Contact(struct contact* pf)
{
if (pf->sz == 0)
{
printf("通讯录为空,无法查找!\n");
}
else
{
char name[MAX_NAME];
printf("请输入要删除联系人的名字\n");
scanf("%s", name);
int pos = find_by_name(pf, name);
if (pos == -1)
{
printf("联系人不存在,请重新查找\n");
}
else
{
printf("%-20s\t%-5s\t%-4s\t%-30s\t%-13s\t\n", "姓名", "性别", "年龄", "地址", "号码");
printf("%-20s\t%-5s\t%-4d\t%-30s\t%-13s\t\n", pf->data[pos].name, pf->data[pos].sex,
pf->data[pos].age, pf->data[pos].address, pf->data[pos].phone);
}
}
}
void Modify_Contact(struct contact* pf)//修改联系人
{
char name[MAX_NAME];
printf("请输入要修改联系人的姓名:");
scanf("%s", name);
int pos = find_by_name(pf,name);
if (pos == -1)
{
printf("该联系人不存在,请重新输入\n");
return;
}
else
{
printf("请输入姓名:");
scanf("%s", pf->data[pos].name);
printf("请输入性别:");
scanf("%s", pf->data[pos].sex);
printf("请输入年龄:");
scanf("%d", &pf->data[pos].age);
printf("请输入地址:");
scanf("%s", pf->data[pos].address);
printf("请输入号码:");
scanf("%s", pf->data[pos].phone);
printf("修改联系人成功!\n");
}
}
void Clear_Contact(struct contact* pf)//格式化通讯录
{
memset(pf->data, 0, sizeof(pf->data));
pf->sz = 0;
printf("格式化成功!\n");
}
int Compare_by_name(const void* e1, const void* e2)
{
return strcmp(((struct info*)e1)->name, ((struct info*)e2)->name);
}
int Compare_by_age(const void* e1, const void* e2)
{
return ((struct info*)e1)->age - ((struct info*)e2)->age;
}
int Compare_by_address(const void* e1, const void* e2)
{
return strcmp(((struct info*)e1)->address, ((struct info*)e2)->address);
}
void Sort_Contact(struct contact* pf)//对通讯录中的联系人进行排序
{
printf("请选择排序方式1:姓名2:年龄3:家庭住址\n");
int input = 0;
scanf("%d", &input);
switch (input)
{
case 1:
qsort(pf->data, pf->sz, sizeof(pf->data[0]), Compare_by_name);
printf("排序成功!\n");
break;
case 2:
qsort(pf->data, pf->sz, sizeof(pf->data[0]), Compare_by_age);
printf("排序成功!\n");
break;
case 3:
qsort(pf->data, pf->sz, sizeof(pf->data[0]), Compare_by_address);
printf("排序成功!\n");
break;
}
}
void Save_Contact(struct contact* pf)//将通讯录中的内容保存到文件中
{
assert(pf);
FILE* ps = fopen("contact.txt", "wb");
if (ps == NULL)
{
printf("文件打开失败\n");
return;
}
int i = 0;
for (i = 0; i < pf->sz; i++)
{
fwrite(&(pf->data[i]), sizeof(struct info), 1, ps);//将结构体数据写入文件中
}
printf("通讯录保存成功!\n");
fclose(ps);
ps = NULL;
}
其实通讯录的大部分代码不是很难,但是文件的存储可以适当参考一下hh
边栏推荐
- How to Create a Nice Box and Whisker Plot in R
- 在连接mysql数据库的时候一直报错
- Multi line display and single line display of tqdm
- PHP query distance according to longitude and latitude
- Jenkins installation
- 揭露数据不一致的利器 —— 实时核对系统
- Tidb DM alarm DM_ sync_ process_ exists_ with_ Error troubleshooting
- 基于Hardhat编写合约测试用例
- ESP32音频框架 ESP-ADF 添加按键外设流程代码跟踪
- HOW TO EASILY CREATE BARPLOTS WITH ERROR BARS IN R
猜你喜欢

vant tabs组件选中第一个下划线位置异常

GGPLOT: HOW TO DISPLAY THE LAST VALUE OF EACH LINE AS LABEL

PLC-Recorder快速监控多个PLC位的技巧

Never forget, there will be echoes | hanging mirror sincerely invites you to participate in the opensca user award research

R HISTOGRAM EXAMPLE QUICK REFERENCE

How to Create a Beautiful Plots in R with Summary Statistics Labels

GGHIGHLIGHT: EASY WAY TO HIGHLIGHT A GGPLOT IN R

HOW TO EASILY CREATE BARPLOTS WITH ERROR BARS IN R

可昇級合約的原理-DelegateCall

ImportError: cannot import name ‘Digraph‘ from ‘graphviz‘
随机推荐
PowerBI中导出数据方法汇总
GGHIGHLIGHT: EASY WAY TO HIGHLIGHT A GGPLOT IN R
excel表格中选中单元格出现十字带阴影的选中效果
Jenkins installation
Some things configured from ros1 to ros2
数字化转型挂帅复产复工,线上线下全融合重建商业逻辑
Tdsql | difficult employment? Tencent cloud database micro authentication to help you
ros gazebo相关包的安装
Summary of data export methods in powerbi
6. Introduce you to LED soft film screen. LED soft film screen size | price | installation | application
map集合赋值到数据库
Is the Ren domain name valuable? Is it worth investing? What is the application scope of Ren domain name?
念念不忘,必有回响 | 悬镜诚邀您参与OpenSCA用户有奖调研
HOW TO CREATE AN INTERACTIVE CORRELATION MATRIX HEATMAP IN R
MySQL linked list data storage query sorting problem
可昇級合約的原理-DelegateCall
亚马逊云科技 Community Builder 申请窗口开启
ctf 记录
Rest (XOR) position and thinking
How to Create a Beautiful Plots in R with Summary Statistics Labels