当前位置:网站首页>通讯录的实现(文件版本)
通讯录的实现(文件版本)
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
边栏推荐
- Multi line display and single line display of tqdm
- Bedtools tutorial
- The working day of the month is calculated from the 1st day of each month
- liftOver进行基因组坐标转换
- flutter 问题总结
- 可昇級合約的原理-DelegateCall
- Resources reads 2D texture and converts it to PNG format
- bedtools使用教程
- VS2019代码中包含中文内容导致的编译错误和打印输出乱码问题
- PX4 Position_Control RC_Remoter引入
猜你喜欢

Tick Data and Resampling

6方面带你认识LED软膜屏 LED软膜屏尺寸|价格|安装|应用

HOW TO ADD P-VALUES TO GGPLOT FACETS

Wechat applet uses Baidu API to achieve plant recognition

Pit of the start attribute of enumrate

基于Hardhat和Openzeppelin开发可升级合约(一)

How to Create a Nice Box and Whisker Plot in R

HOW TO CREATE A BEAUTIFUL INTERACTIVE HEATMAP IN R

Importerror: impossible d'importer le nom « graph» de « graphviz»

八大排序汇总
随机推荐
liftOver进行基因组坐标转换
flutter 问题总结
How to Easily Create Barplots with Error Bars in R
ROS lacks xacro package
The position of the first underline selected by the vant tabs component is abnormal
Visualization of chip SEQ data by deeptools
Is the stock account given by qiniu business school safe? Can I open an account?
预言机链上链下调研
Is it safe to open a stock account online? I'm a novice, please guide me
Power Spectral Density Estimates Using FFT---MATLAB
CTF record
Never forget, there will be echoes | hanging mirror sincerely invites you to participate in the opensca user award research
Attribute acquisition method and operation notes of C # multidimensional array
On April 17, 2022, the five heart matchmaker team received double good news
Esp32 audio frame esp-adf add key peripheral process code tracking
mmrotate旋转目标检测框架使用记录
ASTParser 解析含有emum 枚举方法的类文件的踩坑记
可昇級合約的原理-DelegateCall
Webauthn - official development document
Mmrotate rotation target detection framework usage record