文章目录
前言
此项目中我们主要完成一些通讯录的增删查改与保存。此项目我们用C语言在vs2019环境下进行。希望这个小项目能给有需要的同学带来帮助,有错误的地方也欢迎大家指正。
一、通讯录的框架
在这个项目中我们将会创建两个源文件,分别用来测试和放通讯录的主体函数;一个头文件,主要用来声明函数。
废话不多说,我们直接来看框架,也就是测试这一源文件中的代码,是我们通讯录的主要逻辑。
#define _CRT_SECURE_NO_WARNINGS 1//我们在vs2019上写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 ***********\n");
printf("********************************\n");
}
int main()
{
int input = 0;
contact con;//用结构体创建一个通讯录
Init(&con);//对创建的通讯录进行初始化
do
{
Menu();//菜单函数
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
Add(&con);//增加联系人
break;
case 2:
Del(&con);删除联系人
break;
case 3:
Search(&con);查找联系人
break;
case 4:
Modify(&con);删除联系人
break;
case 5:
Show(&con);显示联系人
break;
case 6:
Sort(&con);对联系人排序
break;
case 0:
printf("退出");
Save(&con);//保存联系人
Destory(&con);//因为我们用malloc,realloc来开辟内存,
//因此在程序结束前要将开辟的内存释放,防止内存泄漏。
break;
default :
printf("选择错误,请重新选择:>");
break;
}
} while (input);//菜单中0为退出,while循环也结束。
return 0;
}
二、通讯录的具体实现过程
2.1 定义结构体
这个结构体中定义了我们所写通讯录中每个联系人所需输入的信息,并且为了后期方便修改,其大小我们都用#define进行了定义。
typedef struct peo_infor
{
char name[Name_MAX];//姓名
char sex[Sex_MAX];//性别
char address[Address_MAX];//地址
char numble[Num_MAX];//电话
int age;//年龄
}peoinfor;
此结构体定义了通讯录,里面包含了上述所说描述联系人信息的结构体。并且,由上述结构体类指针定义了一个名字为data的柔性数组。(下一篇文章中我将会介绍)
typedef struct contact
{
peoinfor* data;//人的信息
int num;//当前联系人个数
int capacity;//由于我们会开辟动态内存,因此此变量表示开辟容量。
}contact;
2.2 创建通讯录并进行初始化
通讯录的创建我们在框架部分已经说过,因此我们直接进行通讯录的初始化。
上代码!!!
void Init(contact* pc)
{
assert(pc);//判断pc是否为空指针,若是则进行截断,程序终止。
peoinfor* ptr = (peoinfor*)calloc(DEFAULT_SZ, sizeof(peoinfor));
//开辟DEFAULT_SZ个大小为sizeof(peoinfor)的空间,
//并且calloc会将开辟好的空间全部初始化为0;
if (ptr == NULL)//判断是否开辟成功
{
perror("Init::calloc");//若不成功,此函数将会打印出错误信息。
return;
}
pc->data = ptr;//将开辟好的空间的地址交给data数组。
pc->num = 0;//联系人个数初始化为0
pc->capacity = DEFAULT_SZ;//一次开辟DEFAULT_SZ个空间,因此容量也为DEFAULT_SZ。
LoadContact(pc);//加载文件到通讯录,因为此通讯录由保存信息功能,
//因此,在初始化时要将文件中的信息加载到程序中来。
}
2.3 将信息加载到通讯录
void LoadContact(contact* pc)
{
//打开在contact.c中的contact.txt文件
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL)
{
perror("fopen");//判断文件是否打开成功,若不成功则打印出错误信息。
return;
}
peoinfor tmp = { 0 };//创建一个变量来接受读到的文件数据。
int i = 0;
while (fread(&tmp, sizeof(peoinfor), 1, pf))//将pf指向的文件中的数据,
//以每次读取一个,大小为sizeof(peoinfor)读取到tmp中。
{
check_capacity(pc);//增容。因为我们在初始化时开辟的内存有限,
//防止在将文件中的信息加载到通讯录在内存不够,
//我们要进行判断,若容量不够,要进行增容,此函数将会在后面讲解。
pc->data[i] = tmp;//将tmp中的内容赋给data。
pc->num++;
i++;
}
fclose(pf);//切记在完成结束时被,若打开文件,要及时关闭文件。
pf = NULL;//必将指针置空,以防成野指针。
}
2.4 增容
void check_capacity(contact* pc)
{
assert(pc);//判断是否为空指针。
if (pc->num == pc->capacity)//判断联系人个数是否达到容量
{
//若达到,则用realloc进行扩容。将容量扩大至DEFAULT_SZ + INC_SZ个
peoinfor* ptr = (peoinfor*)realloc(pc->data, (DEFAULT_SZ + INC_SZ) * sizeof(peoinfor));
if (ptr == NULL)
{
perror("Add::realloc");//判断扩容是否成功。
return;
}
pc->data = ptr;
pc->capacity += INC_SZ;//不要忘记容量也要提升。
}
}
2.4 增加联系人
void Add(contact* pc)
{
assert(pc);
check_capacity(pc);//判断是否增容
//增加信息
printf("请输入姓名: ");
scanf("%s", pc->data[pc->num].name);//字符串的变量名称就是其地址,因此不需要加&。
printf("请输入性别: ");
scanf("%s", pc->data[pc->num].sex);
printf("请输入年龄: ");
scanf("%d", &pc->data[pc->num].age);//其为int类型,因此要加&。
printf("请输入地址: ");
scanf("%s", pc->data[pc->num].address);
printf("请输入电话: ");
scanf("%s", pc->data[pc->num].numble);
pc->num++;//不要忘记联系人个数要增加。
}
2.5 删除联系人
void Del(contact* pc)
{
assert(pc);
if (pc->num == 0)
{
printf("通讯录为空\n");
return;
}
printf("请输入要删除人的姓名: ");
char name[Name_MAX] = { 0 };
scanf("%s", name);
int ret=Find_name(pc,name);将输入的姓名与通讯录中的联系人对比。
if (ret == -1)
{
printf("删除的人不存在\n");
return;
}
for (int i = ret; i < pc->num-1; i++)
{
pc->data[i] = pc->data[i + 1];//因为联系人时连续存放,
//因此删除某位联系人后要将后面的联系人都向前挪一个。
}
pc->num--;
printf("删除成功\n");
}
2.6 判断名字是否相同
int Find_name(contact* pc, char* name)
{
assert(pc);
for (int i = 0; i < pc->num;i++)
{
if (strcmp(pc->data[i].name, name) == 0)//用strcmp函数来进行比较,
//其用法我在前面文章中有所讲解。
{
return i;//找到后,返回联系人下表。
}
}
return -1;
}
2.7查找联系人
void Search(contact* pc)
{
assert(pc);
//按名字查找
printf("请输入要查找人的姓名: ");
char name[Name_MAX] = { 0 };
scanf("%s", name);
int i = Find_name(pc, name);
//显示
if (i == -1)
{
printf("要修改的人不存在");
return;
}
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "性别", "年龄", "地址", "电话");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-12s\n", pc->data[i].name,
pc->data[i].sex, pc->data[i].age,
pc->data[i].address,
pc->data[i].numble);
}
2.8修改联系人
void menu2()
{
printf("*****************************\n");
printf("****1.修改姓名 2.修改性别****\n");
printf("****3.修改年龄 3.修改地址****\n");
printf("****4.修改电话 0.退出****\n");
printf("*****************************\n");
}
//修改
void mod1(contact* pc, int i)
{
printf("请输入要修改后的姓名:");
scanf("%s", pc->data[i].name);
}
void mod2(contact* pc, int i)
{
printf("请输入要修改后的性别:");
scanf("%s", pc->data[i].sex);
}
void mod3(contact* pc, int i)
{
printf("请输入要修改后的年龄:");
scanf("%d",&pc->data[i].age);
}
void mod4(contact* pc, int i)
{
printf("请输入要修改后的地址:");
scanf("%s", pc->data[i].address);
}
void mod5(contact* pc, int i)
{
printf("请输入要修改后的电话:");
scanf("%s", pc->data[i].numble);
}
void Modify(contact* pc)
{
assert(pc);
int input;
printf("请输入要修改人的名字:");
char name[Name_MAX] = { 0 };
scanf("%s", name);
int i = Find_name(pc, name);
//显示
if (i == -1)
{
printf("要查找的人不存在\n");
return;
}
menu2();
printf("请选择:>");
scanf("%d",&input);
switch (input)
{
case 1:
mod1(pc, i);
break;
case 2:
mod2(pc, i);
break;
case 3:
mod3(pc, i);
break;
case 4:
mod4(pc, i);
break;
case 5:
mod5(pc, i);
break;
case 0:
printf("退出\n");
break;
default :
printf("请重新选择:");
break;
}
printf("修改成功\n");
}
2.9 显示联系人
void Show(const contact* pc)
{
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "性别", "年龄", "地址", "电话");
assert(pc);
for (int i = 0; i < pc->num; i++)
{
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-12s\n", pc->data[i].name,
pc->data[i].sex, pc->data[i].age,
pc->data[i].address,
pc->data[i].numble);
}
}
2.10 对联系人排序
//本代码中涉及到的qsort的使用,我在前面文章讲过,想详细了解可以去看看。
void menu3()
{
printf("*************************\n");
printf("1.按姓氏排序 2.按年龄排序\n");
printf("*************************\n");
}
int compare1(const void* e1,const void* e2)
{
return strcmp(((peoinfor*)e1)->name,((peoinfor*)e2)->name);
}
int compare2(const void* e1, const void* e2)
{
return ((peoinfor*)e1)->age-((peoinfor*)e2)->age;
}
void Sort(contact* pc)
{
assert(pc);
if (pc->num == 0)
{
printf("通讯录为空\n");
return;
}
menu3();
int input;
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
qsort(pc->data,pc->num,sizeof(pc->data[0]),compare1);
break;
case 2:
qsort(pc->data, pc->num, sizeof(pc->data[0]), compare2);
break;
default :
printf("请重新选择");
break;
}
printf("排序成功\n");
Show(pc);
}
2.11 保存联系人
void Save(contact* pc)
{
FILE* pf = fopen("contact.txt", "wb");
if (pf == NULL)
{
perror("fopen");
return;
}
int i = 0;
for (i = 0; i < pc->num; i++)
{
fwrite(pc->data + i, sizeof(peoinfor), 1, pf);
}
fclose(pf);
pf = NULL;
printf("保存成功");
}
2.12 销毁通讯录
void Destory(contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->num = 0;
}
完整代码
头文件
#include<stdio.h>
#define Name_MAX 20
#define Sex_MAX 5
#define Address_MAX 20
#define Num_MAX 12
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define DEFAULT_SZ 3
#define INC_SZ 2
typedef struct peo_infor
{
char name[Name_MAX];
char sex[Sex_MAX];
char address[Address_MAX];
char numble[Num_MAX];
int age;
}peoinfor;
//静态
//typedef struct contact
//{
// peoinfor data[100];
// int num;
//}contact;
//动态
typedef struct contact
{
peoinfor* data;
int num;
int capacity;
}contact;
void Init(contact* pc);
void Add(contact* pc);
void Show(const contact* pc);
void Del(contact* pc);
void Search(contact* pc);
void Modify(contact* pc);
void Sort(contact* pc);
void Destory(contact* pc);
void LoadContact(contact* pc);
void Save(contact* pc);
contact.c文件
#include"contact.h"
void Init(contact* pc)
{
assert(pc);
peoinfor* ptr = (peoinfor*)calloc(DEFAULT_SZ, sizeof(peoinfor));
if (ptr == NULL)
{
perror("Init::calloc");
return;
}
pc->data = ptr;
pc->num = 0;
pc->capacity = DEFAULT_SZ;
//加载文件到通讯录
LoadContact(pc);
}
void check_capacity(contact* pc)
{
assret(pc);
if (pc->num == pc->capacity)
{
peoinfor* ptr = (peoinfor*)realloc(pc->data, (DEFAULT_SZ + INC_SZ) * sizeof(peoinfor));
if (ptr == NULL)
{
perror("Add::realloc");
return;
}
pc->data = ptr;
pc->capacity += INC_SZ;
}
}
void Add(contact* pc)
{
assert(pc);
check_capacity(pc);
//增加信息
printf("请输入姓名: ");
scanf("%s", pc->data[pc->num].name);
printf("请输入性别: ");
scanf("%s", pc->data[pc->num].sex);
printf("请输入年龄: ");
scanf("%d", &pc->data[pc->num].age);
printf("请输入地址: ");
scanf("%s", pc->data[pc->num].address);
printf("请输入电话: ");
scanf("%s", pc->data[pc->num].numble);
pc->num++;
}
void Show(const contact* pc)
{
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "性别", "年龄", "地址", "电话");
assert(pc);
for (int i = 0; i < pc->num; i++)
{
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-12s\n", pc->data[i].name,
pc->data[i].sex, pc->data[i].age,
pc->data[i].address,
pc->data[i].numble);
}
}
int Find_name(contact* pc, char* name)
{
assert(pc);
for (int i = 0; i < pc->num;i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void Del(contact* pc)
{
assert(pc);
if (pc->num == 0)
{
printf("通讯录为空\n");
return;
}
printf("请输入要删除人的姓名: ");
char name[Name_MAX] = { 0 };
scanf("%s", name);
int ret=Find_name(pc,name);
if (ret == -1)
{
printf("删除的人不存在\n");
return;
}
for (int i = ret; i < pc->num-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->num--;
printf("删除成功\n");
}
void Search(contact* pc)
{
assert(pc);
//按名字查找
printf("请输入要查找人的姓名: ");
char name[Name_MAX] = { 0 };
scanf("%s", name);
int i = Find_name(pc, name);
//显示
if (i == -1)
{
printf("要修改的人不存在");
return;
}
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "性别", "年龄", "地址", "电话");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-12s\n", pc->data[i].name,
pc->data[i].sex, pc->data[i].age,
pc->data[i].address,
pc->data[i].numble);
}
void menu2()
{
printf("*****************************\n");
printf("****1.修改姓名 2.修改性别****\n");
printf("****3.修改年龄 3.修改地址****\n");
printf("****4.修改电话 0.退出****\n");
printf("*****************************\n");
}
//修改
void mod1(contact* pc, int i)
{
printf("请输入要修改后的姓名:");
scanf("%s", pc->data[i].name);
}
void mod2(contact* pc, int i)
{
printf("请输入要修改后的性别:");
scanf("%s", pc->data[i].sex);
}
void mod3(contact* pc, int i)
{
printf("请输入要修改后的年龄:");
scanf("%d",&pc->data[i].age);
}
void mod4(contact* pc, int i)
{
printf("请输入要修改后的地址:");
scanf("%s", pc->data[i].address);
}
void mod5(contact* pc, int i)
{
printf("请输入要修改后的电话:");
scanf("%s", pc->data[i].numble);
}
void Modify(contact* pc)
{
assert(pc);
int input;
printf("请输入要修改人的名字:");
char name[Name_MAX] = { 0 };
scanf("%s", name);
int i = Find_name(pc, name);
//显示
if (i == -1)
{
printf("要查找的人不存在\n");
return;
}
menu2();
printf("请选择:>");
scanf("%d",&input);
switch (input)
{
case 1:
mod1(pc, i);
break;
case 2:
mod2(pc, i);
break;
case 3:
mod3(pc, i);
break;
case 4:
mod4(pc, i);
break;
case 5:
mod5(pc, i);
break;
case 0:
printf("退出\n");
break;
default :
printf("请重新选择:");
break;
}
printf("修改成功\n");
}
void menu3()
{
printf("*************************\n");
printf("1.按姓氏排序 2.按年龄排序\n");
printf("*************************\n");
}
int compare1(const void* e1,const void* e2)
{
return strcmp(((peoinfor*)e1)->name,((peoinfor*)e2)->name);
}
int compare2(const void* e1, const void* e2)
{
return ((peoinfor*)e1)->age-((peoinfor*)e2)->age;
}
void Sort(contact* pc)
{
assert(pc);
if (pc->num == 0)
{
printf("通讯录为空\n");
return;
}
menu3();
int input;
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
qsort(pc->data,pc->num,sizeof(pc->data[0]),compare1);
break;
case 2:
qsort(pc->data, pc->num, sizeof(pc->data[0]), compare2);
break;
default :
printf("请重新选择");
break;
}
printf("排序成功\n");
Show(pc);
}
void Destory(contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->num = 0;
}
void Save(contact* pc)
{
FILE* pf = fopen("contact.txt", "wb");
if (pf == NULL)
{
perror("fopen");
return;
}
int i = 0;
for (i = 0; i < pc->num; i++)
{
fwrite(pc->data + i, sizeof(peoinfor), 1, pf);
}
fclose(pf);
pf = NULL;
printf("保存成功");
}
void LoadContact(contact* pc)
{
//打开文件
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL)
{
perror("fopen");
return;
}
peoinfor tmp = { 0 };
int i = 0;
while (fread(&tmp, sizeof(peoinfor), 1, pf))
{
//增容
check_capacity(pc);
pc->data[i] = tmp;
pc->num++;
i++;
}
fclose(pf);
pf = NULL;
}
test.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#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 ***********\n");
printf("********************************\n");
}
int main()
{
int input = 0;
//创建
contact con;
//初始化
Init(&con);
do
{
Menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
Add(&con);
break;
case 2:
Del(&con);
break;
case 3:
Search(&con);
break;
case 4:
Modify(&con);
break;
case 5:
Show(&con);
break;
case 6:
Sort(&con);
break;
case 0:
printf("退出");
Save(&con);
Destory(&con);
break;
default :
printf("选择错误,请重新选择:>");
break;
}
} while (input);
return 0;
}
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。