❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️
❇️❇️❇️❇️ 不同的信念 ❇️❇️❇️❇️
❇️❇️❇️ 决定不同的命运 ❇️❇️❇️
❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️
📖通讯录
✅具备的功能
ℹ️需要的头文件名
#include<stdio.h>//第一个
#include<string.h>//第二个
#include<stdlib.h>//第三个
第一个头文件名是常规的头文件名如:int main()主函数和printf函数等都需要,只要写C语言都需要此头文件名。 |
第二个头文件名是在下面执行通讯录文件时需要使用strcmp函数会用到 |
第三个头文件名也是在下面执行通讯录文件时会用到,如:qsort()函数和free()函数会用到 |
当然这些函数的用途,在讲解通讯录的时候会个哦大家介绍。 |
ℹ️所用到的其它函数和相关结构体
typedef struct Proper//所存储的人的信息
{
char name[20];//姓名
int age;//年龄
char number[20];//电话号码
}Proper;
typedef struct Contact存储人信息的空间
{
Proper* date;//存储人信息的指针
int se;//空间里存储联系人信息的数量
int eff;//空间总的大小
}Contact;
void Inialize(Contact* con)//存储联系人信息的数组初始化
{
con->date = (Proper*)malloc(3 * sizeof(Proper));
if (con->date == NULL)
{
perror("Inialize");
return;
}
con->se = 0;
con->eff = 3;
}
void menu()//游戏菜单
{
printf("*******************************\n");
printf("***** 1、添加联系人 ***********\n");
printf("***** 2、删除联系人 ***********\n");
printf("***** 3、显示联系人 ***********\n");
printf("***** 4、查找联系人 ***********\n");
printf("***** 5、修改联系人 ***********\n");
printf("***** 6、联系人排序 ***********\n");
printf("***** 7、清空联系人 ***********\n");
printf("***** 8、退出通讯录 ***********\n");
printf("*******************************\n");
}
void test()//通讯录函数
{
int input = 0;
Contact con;
Inialize(&con);//通讯录初始化
do
{
menu();//游戏菜单
printf("请作出选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
AddContact(&con);//添加联系人
break;
case 2:
Delete(&con);//删除联系人
break;
case 3:
Display(&con);//显示联系人
break;
case 4:
SeekContact(&con);//查找联系人
break;
case 5:
Modify(&con);//修改联系人
break;
case 6:
SortContact(&con);//联系人排序
break;
case 7:
empty(&con);
break;
case 8:
SaveContact(&con);
realse(&con);
printf("退出通讯录\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
if (input == 8)
input = 0;
} while (input);
}
int main()//主函数
{
test();
return 0;
}
ℹ️添加联系人
int Addeff(Contact* con)//检查存储空间是否满的函数
{
if (con->se == con->eff)//两者相等时会满,除了首次进入两个都为0的情况
{
Proper* per = (Proper*)realloc(con->date, (con->eff + 2) * sizeof(Proper));
if (per == NULL)//判断per空间的创建是否成功
{
perror("Addeff");
return 0;
}
con->date = per;
con->eff = con->eff + 2;
printf("增容成功\n");
}
return 1;
}
void AddContact(Contact* con)//添加联系人函数
{
if (Addeff(con) == 0)//如果Addeff函数如果返回0,则表示空间创建失败,则不可以添加联系人
{
return;
}
printf("输入姓名:>");
scanf("%s", con->date[con->se].name);
printf("输入年龄:>");
scanf("%d", &con->date[con->se].age);//这里会什么会加&(地址符)呢,这是因为输入的是一个数,而上面输入不需要加&,是因为是数组。数组首元素就是该数组的大小
printf("输入电话号码:>");
scanf("%s", con->date[con->se].number);
con->se++;
printf("添加成功\n");
}
Addeff函数是用来检查我们所用来存储联系人的空间有没有满,如果满了,就会利用此函数来增加空间。Contact()函数就是来添加联系人
ℹ️删除联系人
void Delete(Contact* con)//删除联系人函数
{
int i = 0;
char m[20] = { 0 };//创建一个新的数组用来输入你需要查找的联系人的空间
printf("输入你需要删除联系人的姓名:>");
scanf("%s", m);
for (i = 0; i < con->se; i++)//在数据里查找你需要删除的联系人的信息
{
int j = 0;
if (strcmp(m, con->date[i].name) == 0)
{
for (j = i; j < con->se - 1; j++)//当你找到你所要删除的联系人的消息的时候,利用后面的数据把此数据进行覆盖,这样就达到删除的功效
{
con->date[j] = con->date[j + 1];
}
con->se--;//当你删除联系人的时候该联系人后面的数据都往前移了一步,这样最后就多了一个空间,此时我们就需要删掉这个空间
printf("删除成功\n");
}
}
}
此过程还是很好理解的,因为存储联系人的信息是数组,所以我们只能利用覆盖来删除。
ℹ️显示联系人
void Display(Contact* con)//打印通讯录所有联系人信息的函数
{
int i = 0;
printf("%-10s %-10s %-10s\n", "姓名", "年龄", "电话");
for (i = 0; i < con->se; i++)
{
printf("%-10s %-10d %-10s\n", con->date[i].name, con->date[i].age, con->date[i].number);
}
}
ℹ️查找联系人
void SeekContact(Contact* con)
{
int i = 0;
char m[20] = { 0 };//和删除联系人所需创建的变量是同一个意思,在这里它就是存储你需要查找的联系人的信息
printf("输入你要查找的联系人的姓名:>");
scanf("%s", m);
for (i = 0; i < con->se; i++)//遍历一遍
{
if (strcmp(m, con->date[i].name) == 0)//利用了strcmp函数
{
printf("找到了:姓名:%s, 年龄:%d, 号码:%s\n", con->date[i].name, con->date[i].age, con->date[i].number);
}
}
}
strcmp就是用来比较字符串大小的函数,它的用法在我以前写的博客中有介绍大家可以去看看:字符和字符串的库函数模拟(这是一个链接有需要的可以直接点进去看)
ℹ️修改联系人
void Modify(Contact* con)//修改联系人信息的函数
{
char m[20] = { 0 };//这里与上面的用法差不多,用来存储你需要查找联系人的信息
printf("输入你需要修改联系人的姓名:>");
scanf("%s", m);
int i = 0;
for (i = 0; i < con->se; i++)//遍历一遍
{
if (strcmp(m, con->date[i].name) == 0)//利用了strcmp函数
{
printf("重新输入姓名:>");
scanf("%s", con->date[i].name);
printf("重新输入年龄:>");
scanf("%d", &con->date[i].age);//这里会什么会加&(地址符)呢,这是因为输入的是一个数,而上面输入不需要加&,是因为是数组。数组首元素就是该数组的大小
printf("重新输入号码:>");
scanf("%s", con->date[i].number);
printf("修改成功\n");
}
}
}
ℹ️联系人排序
int compare(const void* p1, const void* p2)//比较函数
{
return strcmp(((Proper*)p1)->name, ((Proper*)p2)->name);
}
void SortContact(Contact* con)//用来进行联系人排序的函数
{
qsort(con->date, con->se, sizeof(Proper), compare);//这是一个专门进行排序的函数
printf("成功排序\n");
}
qsort()函数:可以参考相关的博客,也可以百度,在这里就不做过多解释了(抱歉)
compare()函数:此函数是和qsort函数搭配使用。参考相关资料。(抱歉)
ℹ️清空联系人
void empty(Contact* con)//清除联系人的函数
{
con->se = 0;//因为con->se表示的是数组空间类的大小,当空间为0的时候这组也就没有数据了
printf("成功清除\n");
}
ℹ️退出通讯录
当input输入为0的时候程序就退出了
ℹ️通讯录置空
void realse(Contact* con)//通讯录空间置空的函数
{
free(con->date);//置空函数,只要是动态开辟的空间都需要使用该函数进行置空,否者就会有内存泄漏的情况
con->date = NULL;//和free是搭配使用的
con->se = 0;
con->eff = 0;
}
关于free()函数的用法。大家可以看我以前这篇的博客:动态内存管理(c语言)(这是个链接,有不清楚的可以点进去观看,里面对于懂得太内存有详细的介绍)
ℹ️普通的通讯录实现
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct Proper
{
char name[20];
int age;
char number[20];
}Proper;
typedef struct Contact
{
Proper* date;
int se;
int eff;
}Contact;
void menu()
{
printf("*******************************\n");
printf("***** 1、添加联系人 ***********\n");
printf("***** 2、删除联系人 ***********\n");
printf("***** 3、显示联系人 ***********\n");
printf("***** 4、查找联系人 ***********\n");
printf("***** 5、修改联系人 ***********\n");
printf("***** 6、联系人排序 ***********\n");
printf("***** 7、清空联系人 ***********\n");
printf("***** 8、退出通讯录 ***********\n");
printf("*******************************\n");
}
void Inialize(Contact* con)
{
con->date = (Proper*)malloc(3 * sizeof(Proper));
if (con->date == NULL)
{
perror("Inialize");
return;
}
con->se = 0;
con->eff = 3;
}
int Addeff(Contact* con)
{
if (con->se == con->eff)
{
Proper* per = (Proper*)realloc(con->date, (con->eff + 2) * sizeof(Proper));
if (per == NULL)
{
perror("Addeff");
return 0;
}
con->date = per;
con->eff = con->eff + 2;
printf("增容成功\n");
}
return 1;
}
void AddContact(Contact* con)
{
if (Addeff(con) == 0)
{
return;
}
printf("输入姓名:>");
scanf("%s", con->date[con->se].name);
printf("输入年龄:>");
scanf("%d", &con->date[con->se].age);
printf("输入电话号码:>");
scanf("%s", con->date[con->se].number);
con->se++;
printf("添加成功\n");
}
void Display(Contact* con)
{
int i = 0;
printf("%-10s %-10s %-10s\n", "姓名", "年龄", "电话");
for (i = 0; i < con->se; i++)
{
printf("%-10s %-10d %-10s\n", con->date[i].name, con->date[i].age, con->date[i].number);
}
}
void Delete(Contact* con)
{
int i = 0;
char m[20] = { 0 };
printf("输入你需要删除联系人的姓名:>");
scanf("%s", m);
for (i = 0; i < con->se; i++)
{
int j = 0;
if (strcmp(m, con->date[i].name) == 0)
{
for (j = i; j < con->se - 1; j++)
{
con->date[j] = con->date[j + 1];
}
con->se--;
printf("删除成功\n");
}
}
}
void SeekContact(Contact* con)
{
int i = 0;
char m[20] = { 0 };
printf("输入你要查找的联系人的姓名:>");
scanf("%s", m);
for (i = 0; i < con->se; i++)
{
if (strcmp(m, con->date[i].name) == 0)
{
printf("找到了:姓名:%s, 年龄:%d, 号码:%s\n", con->date[i].name, con->date[i].age, con->date[i].number);
}
}
}
void Modify(Contact* con)
{
char m[20] = { 0 };
printf("输入你需要修改联系人的姓名:>");
scanf("%s", m);
int i = 0;
for (i = 0; i < con->se; i++)
{
if (strcmp(m, con->date[i].name) == 0)
{
printf("重新输入姓名:>");
scanf("%s", con->date[i].name);
printf("重新输入年龄:>");
scanf("%d", &con->date[i].age);
printf("重新输入号码:>");
scanf("%s", con->date[i].number);
printf("修改成功\n");
}
}
}
int compare(const void* p1, const void* p2)
{
return strcmp(((Proper*)p1)->name, ((Proper*)p2)->name);
}
void SortContact(Contact* con)
{
qsort(con->date, con->se, sizeof(Proper), compare);
printf("成功排序\n");
}
void empty(Contact* con)
{
con->se = 0;
printf("成功清除\n");
}
void realse(Contact* con)
{
free(con->date);
con->date = NULL;
con->se = 0;
con->eff = 0;
}
void test()
{
int input = 0;
Contact con;
Inialize(&con);//通讯录初始化
do
{
menu();//游戏菜单
printf("请作出选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
AddContact(&con);//添加联系人
break;
case 2:
Delete(&con);//删除联系人
break;
case 3:
Display(&con);//显示联系人
break;
case 4:
SeekContact(&con);//查找联系人
break;
case 5:
Modify(&con);//修改联系人
break;
case 6:
SortContact(&con);//联系人排序
break;
case 7:
empty(&con);
break;
case 8:
realse(&con);
printf("退出通讯录\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
if (input == 8)
input = 0;
} while (input);
}
int main()
{
test();
return 0;
}
上面就是普通的通讯录的实现代码了。有需要的直接复制粘贴就可以了。
✅动态文件操作实现过程
ℹ️联系人信息保存在文件中
void SaveContact(Contact* con)
{
FILE* fp = fopen("C:\\Users\\杨沛琪\\Desktop\\contact.txt", "wb");//这就是文件的创建
if (fp == NULL)//这是文件的判断,如果创建的文件为空,则直接结束该函数,不会进行下一步
{
perror("fopen");
return;
}
for (int i = 0; i < con->se; i++)
{
fwrite(&(con->date[i]), sizeof(Proper), 1, fp);//这是把数组的数据存储到我们刚才创建的文件fp中
}
fclose(fp);//文件置空,和free用法一样只不过fclose是文件置空使用,free是动态空间使用
fp = NULL;//和fclose两者是搭配使用的
}
大家如果对于文件方面的操作不太了解的话,如:FILE,fwrite,fread等的用法,大家可以观看我的这篇博客文件详细操作过程(C语言)(这是一个链接,大家对于文件方面知识的欠缺可以点进去看)。
ℹ️从文件中读取联系人的信息
void LoadContact(Contact* con)//读取文件中联系人的信息
{
FILE* fp = fopen("C:\\Users\\杨沛琪\\Desktop\\contact.txt", "rb");
if (fp == NULL)
{
perror("LoadContact");
return;
}
Proper tem = { 0 };
while (fread( & tem, sizeof(Proper), 1, fp))//fread()函数是读取文件的函数
{
if (0 == Addeff(con))
return;
con->date[con->se] = tem;
con->se++;
}
//为什么要把函数放在while循环中呢?这是因为fread的返回值是整数型。它读取一个数据就会返回1,读取两个就返回2,以此类推,当读取的数据为空时就会返回0.
fclose(fp);//置空函数,和free用法一样,只不过fclose是文件置空而free是动态空间置空
fp = NULL;//和fclose搭配使用
}
void Inialize(Contact* con)//存储联系人信息的数组初始化
{
con->date = (Proper*)malloc(3 * sizeof(Proper));
if (con->date == NULL)
{
perror("Inialize");
return;
}
con->se = 0;
con->eff = 3;
LoadContact(con);//和普通的通讯录实现中的初始化仅仅多了这一个函数,当我们需要在程序执行前读取文件中所存储的联系人信息,只能放在初始化过程中实现。
}
大家如果对于文件方面的操作不太了解的话,如:FILE,fwrite,fread等的用法,大家可以观看我的这篇博客文件详细操作过程(C语言)(这是一个链接,大家对于文件方面知识的欠缺可以点进去看)。
ℹ️通讯录(文件形式)实现过程
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct Proper
{
char name[20];
int age;
char number[20];
}Proper;
typedef struct Contact
{
Proper* date;
int se;
int eff;
}Contact;
void menu()
{
printf("*******************************\n");
printf("***** 1、添加联系人 ***********\n");
printf("***** 2、删除联系人 ***********\n");
printf("***** 3、显示联系人 ***********\n");
printf("***** 4、查找联系人 ***********\n");
printf("***** 5、修改联系人 ***********\n");
printf("***** 6、联系人排序 ***********\n");
printf("***** 7、清空联系人 ***********\n");
printf("***** 8、退出通讯录 ***********\n");
printf("*******************************\n");
}
int Addeff(Contact* con);//因为Addeff函数在创建的时候是在下面,而在它之前的函数需要调用的时候就会找不到,所以就需要提前写一个声明。在C语言中函数执行顺序是从上往下。
void LoadContact(Contact* con)
{
FILE* fp = fopen("C:\\Users\\杨沛琪\\Desktop\\contact.txt", "rb");
if (fp == NULL)
{
perror("LoadContact");
return;
}
Proper tem = { 0 };
while (fread( & tem, sizeof(Proper), 1, fp))
{
if (0 == Addeff(con))
return;
con->date[con->se] = tem;
con->se++;
}
fclose(fp);
fp = NULL;
}
void Inialize(Contact* con)
{
con->date = (Proper*)malloc(3 * sizeof(Proper));
if (con->date == NULL)
{
perror("Inialize");
return;
}
con->se = 0;
con->eff = 3;
LoadContact(con);
}
int Addeff(Contact* con)
{
if (con->se == con->eff)
{
Proper* per = (Proper*)realloc(con->date, (con->eff + 2) * sizeof(Proper));
if (per == NULL)
{
perror("Addeff");
return 0;
}
con->date = per;
con->eff = con->eff + 2;
printf("增容成功\n");
}
return 1;
}
void AddContact(Contact* con)
{
if (Addeff(con) == 0)
{
return;
}
printf("输入姓名:>");
scanf("%s", con->date[con->se].name);
printf("输入年龄:>");
scanf("%d", &con->date[con->se].age);
printf("输入电话号码:>");
scanf("%s", con->date[con->se].number);
con->se++;
printf("添加成功\n");
}
void Display(Contact* con)
{
int i = 0;
printf("%-10s %-10s %-10s\n", "姓名", "年龄", "电话");
for (i = 0; i < con->se; i++)
{
printf("%-10s %-10d %-10s\n", con->date[i].name, con->date[i].age, con->date[i].number);
}
}
void Delete(Contact* con)
{
int i = 0;
char m[20] = { 0 };
printf("输入你需要删除联系人的姓名:>");
scanf("%s", m);
for (i = 0; i < con->se; i++)
{
int j = 0;
if (strcmp(m, con->date[i].name) == 0)
{
for (j = i; j < con->se - 1; j++)
{
con->date[j] = con->date[j + 1];
}
con->se--;
printf("删除成功\n");
}
}
}
void SeekContact(Contact* con)
{
int i = 0;
char m[20] = { 0 };
printf("输入你要查找的联系人的姓名:>");
scanf("%s", m);
for (i = 0; i < con->se; i++)
{
if (strcmp(m, con->date[i].name) == 0)
{
printf("找到了:姓名:%s, 年龄:%d, 号码:%s\n", con->date[i].name, con->date[i].age, con->date[i].number);
}
}
}
void Modify(Contact* con)
{
char m[20] = { 0 };
printf("输入你需要修改联系人的姓名:>");
scanf("%s", m);
int i = 0;
for (i = 0; i < con->se; i++)
{
if (strcmp(m, con->date[i].name) == 0)
{
printf("重新输入姓名:>");
scanf("%s", con->date[i].name);
printf("重新输入年龄:>");
scanf("%d", &con->date[i].age);
printf("重新输入号码:>");
scanf("%s", con->date[i].number);
printf("修改成功\n");
}
}
}
int compare(const void* p1, const void* p2)
{
return strcmp(((Proper*)p1)->name, ((Proper*)p2)->name);
}
void SortContact(Contact* con)
{
qsort(con->date, con->se, sizeof(Proper), compare);
printf("成功排序\n");
}
void empty(Contact* con)
{
con->se = 0;
printf("成功清除\n");
}
void realse(Contact* con)
{
free(con->date);
con->date = NULL;
con->se = 0;
con->eff = 0;
}
void SaveContact(Contact* con)
{
assert(con);
FILE* fp = fopen("C:\\Users\\杨沛琪\\Desktop\\contact.txt", "wb");
if (fp == NULL)
{
perror("fopen");
return;
}
for (int i = 0; i < con->se; i++)
{
fwrite(&(con->date[i]), sizeof(Proper), 1, fp);
}
fclose(fp);
fp = NULL;
}
void test()
{
int input = 0;
Contact con;
Inialize(&con);//通讯录初始化
do
{
menu();//游戏菜单
printf("请作出选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
AddContact(&con);//添加联系人
break;
case 2:
Delete(&con);//删除联系人
break;
case 3:
Display(&con);//显示联系人
break;
case 4:
SeekContact(&con);//查找联系人
break;
case 5:
Modify(&con);//修改联系人
break;
case 6:
SortContact(&con);//联系人排序
break;
case 7:
empty(&con);
break;
case 8:
SaveContact(&con);
realse(&con);
printf("退出通讯录\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
if (input == 8)
input = 0;
} while (input);
}
int main()
{
test();
return 0;
}
✏️✏️✏️✏️📖📖✏️✏️✏️✏️✏️✏️✏️📖📖✏️✏️
✏️✏️✏️✏️📖📖我们一起加油哈!!📖📖✏️✏️
✏️✏️✏️✏️📖📖✏️✏️✏️✏️✏️✏️📖📖✏️✏️