此次给大家带来的是可以动态扩容并把联系人信息用文本保存到本地的通讯录。
相比静态通讯录的话,如果联系人容量满了,再添加联系人程序会动态申请内存,得以继续添加联系人。
并且每次添加联系人后,程序自动保存到本地,并在下次启动自动从本地读取,保证程序可用性。因此,我并没有在界面单独设置导入和导出功能,而是在程序测试文件开头直接加入。
这个通讯录写成三个文件,一个头文件,一个功能函数文件,一个测试文件
Contact.h(头文件)
//写在开头,在输入内容时,中间不可以加空格,输入完毕直接回车结束,否则的话会直接存到下一个内容里,造成影响。
//因为输入空格和回车都是系统认为的字符串结束符,一段内容中间加空格,则后面内容到回车,存入缓冲区传入下一段内容,造成错误
//此通讯录可以重名,但会提示你重名。但是电话号码不可以重复,因为电话号码是唯一的
#define _CRT_SECURE_NO_WARNINGS
#ifndef __Test_h__
#define __Test_h__
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#define DefaultCapicity 10//默认通讯录初始可存人数
#define EnlargeCapicity 5//每次扩容增加可存人数
typedef struct People
{
char name[10];
char sex[8];
int age;
char telephone_number[11];
char address[20];
}People;
typedef struct Contact
{
People *people;
int number;
int capicity;
}Contact;
void InitContact(Contact *pCon);//初始化通讯录
void DestoryMalloc(Contact *pCon);//销毁动态申请的内存
void EnlargeContact(Contact *pCon);//扩容
void SaveContact(Contact *pCon);//保存联系人信息到文件
void LoadContact(Contact *pCon);//读取联系人信息到屏幕
int MyCmp(const void *a, const void *b);//对名字对应字符串大小比较的函数
int JudgeSameTelephone(Contact *pCon, char *TelNumber);//判定电话号码是否存在重复的
int JudgeSameName(Contact *pCon, char *Name);//判断是否有相同名字
int JudgeContacts(Contact *pCon, char *Name);//判定联系人是否存在
void AddContacts(Contact *pCon);//添加联系人信息
void DeleteContcts(Contact *pCon, char *Name);//删除联系人信息
void SearchContacts(Contact *pCon, char *Name);//查找指定联系人信息
void AmendContacts(Contact *pCon, char *Nmae);//修改联系人信息
void ShowAllContacts(Contact *pCon);//显示所有联系人信息
void ClearContacts(Contact *pCon);//清空联系人信息
#endif//!__Test_h__
Contact.c(功能函数文件)
#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
void InitContact(Contact *pCon)//初始化通讯录
{
pCon->people = (People*)malloc(sizeof(People)*DefaultCapicity);
memset(pCon->people, 0, sizeof(People)*DefaultCapicity);//变量内容全部清零
//空间开辟失败,退出表示程序没有成功执行
if (pCon->people == NULL)
{
printf("Malloc fail!\n");
perror("Reason");
exit(EXIT_FAILURE);
}
pCon->capicity = DefaultCapicity;
pCon->number = 0;
}
void EnlargeContact(Contact *pCon)//对通讯录进行扩容
{
People *tmp = (People*)realloc(pCon->people, sizeof(People)*(pCon->capicity + EnlargeCapicity));
if (tmp == NULL)
{
printf("Enlarge fail,please resume enlarge.\n");
perror("Reason");
return;
}
pCon->people = tmp;
pCon->capicity = pCon->capicity + EnlargeCapicity;
printf("Enlarge successfully!\n");
}
void SaveContact(Contact *pCon)//导出
{
int i = 0;
FILE *pFile = fopen("Contact.txt", "w");
if (pFile == NULL)
{
perror("Open fail");
return;
}
for(i = 0; i < pCon->number; i++)
{
fwrite(&(pCon->people[i]), sizeof(People), 1, pFile);
}
printf("Export successfully.\n");
fclose(pFile);
}
void LoadContact(Contact *pCon)//导入
{
assert(pCon);
int lSize = 0, cSize = 0;
int i = 0, sz = 0;
FILE *pFile = fopen("Contact.txt", "r");
if (pFile == NULL)
{
perror("Open fail");
return;
}
fseek(pFile, 0, SEEK_END);//找到指针指向内容的结尾
lSize = ftell(pFile);//得到当前指针距首地址字节数
rewind(pFile);//指针指向首地址
sz = lSize / sizeof(People);
while (sz != i)
{
cSize = fread(&(pCon->people[i]), sizeof(People), 1, pFile);
i++;
(pCon->number)++;
if (i == pCon->capicity)//表示要存的数据多于通讯录的容量,要进行扩容
{
EnlargeContact(pCon);
}
}
if (cSize == 0)
{
perror("Load fail");
return;
}
printf("Import successfully.\n");
fclose(pFile);
}
int MyCmp(const void *a, const void *b)//根据姓名比较函数
{
People *p1 = (People *)a;
People *p2 = (People *)b;
return strcmp(p1->name, p2->name);
}
int JudgeSameName(Contact *pCon, char *Name)//判断是否有相同的名字
{
int j = 0;
for (j = 0; j < pCon->number; j++)
{
if (0 == (strcmp(pCon->people[j].name, Name)))
return 0;
}
return -1;
}
int JudgeSameTelephone(Contact *pCon, char *TelNumber)//判断是否有相同的的电话号码
{
int j = 0;
for (j = 0; j < pCon->number; j++)
{
if (0 == (strcmp(pCon->people[j].telephone_number, TelNumber)))
return 0;
}
return -1;
}
int JudgeContacts(Contact *pCon, char *Name)//判定联系人是否存在,找到返回下标
{
int j = 0;
for (j = 0; j < pCon->number; j++)
{
if (0 == strcmp(pCon->people[j].name, Name))
return j;
}
return -1;
}
void AddContacts(Contact *pCon)//添加联系人
{
assert(pCon);
char TelNumber[11];
if (pCon->number != pCon->capicity)
{
printf("Input name:");
scanf("%s", pCon->people[pCon->number].name);
if (0 == JudgeSameName(pCon, pCon->people[pCon->number].name))
{
printf("Have same Name,suggest you choose 4 to exchange.\n");
}
printf("Input sex:");
scanf("%s", pCon->people[pCon->number].sex);
printf("Input age:");
scanf("%d", &(pCon->people[pCon->number].age));
printf("Input telephone_number:");
scanf("%s", TelNumber);
if (0 != JudgeSameTelephone(pCon, TelNumber))
{
strcpy(pCon->people[pCon->number].telephone_number, TelNumber);
}
else
{
printf("Have same Telephone Number,please resume input people information.\n");
return;
}
printf("Input address:");
scanf("%s", pCon->people[pCon->number].address);
printf("Add success!\n");
pCon->number++;//联系人数加1
}
else
{
printf("Contacts is full,please choose 7 to enlarge capicity.\n");
}
}
void DeleteContcts(Contact *pCon, char *Name)//删除联系人
{
int ret = 0;
if (-1 != (ret = JudgeContacts(pCon, Name)))
{
pCon->people[ret] = pCon->people[pCon->number - 1];//最后一个变量的内容直接覆盖所要删除联系人的变量内容
pCon->number--;//联系人个数减1
printf("Delete success!\n");
}
else
printf("No such people...\n");
}
void SearchContacts(Contact *pCon, char *Name)//查找指定联系人信息
{
int j = 0;
int ret = 0;
int flag = 0;
if (-1 != (ret = JudgeContacts(pCon, Name)))
{
flag = 1;
printf("Name is :%s\n", pCon->people[ret].name);
printf("Sex is :%s\n", pCon->people[ret].sex);
printf("Age is %d\n", pCon->people[ret].age);
printf("TeleponeNumber is %s\n", pCon->people[ret].telephone_number);
printf("Address is %s\n\n", pCon->people[ret].address);
}
if (0 == flag)
printf("No such people.\n");
}
void AmendContacts(Contact *pCon, char *Name)//修改联系人信息
{
int ret = 0;
char TelNumber[11];
if (-1 != (ret = JudgeContacts(pCon, Name)))
{
printf("Input changed name is:");
scanf("%s", pCon->people[ret].name);
if (0 == JudgeSameName(pCon, TelNumber))
{
printf("Have same Name,suggest you choose 4 to exchange.\n");
}
printf("Input changed sex is:");
scanf("%s", pCon->people[ret].sex);
printf("Input changed age is:");
scanf("%d", &(pCon->people[ret].age));
printf("Input changed telephone_number is:");
scanf("%s", TelNumber);
if (0 != JudgeSameTelephone(pCon, TelNumber))
{
strcpy(pCon->people[ret].telephone_number, TelNumber);
}
else
{
printf("Have same Telephone Number,please resume input information.\n");
return;
}
printf("Input changed address is:");
scanf("%s", pCon->people[ret].address);
printf("Change success!\n");
}
else
printf("No such people.\n");
}
void ShowAllContacts(Contact *pCon)//显示所有联系人信息
{
assert(pCon);
int j = 0;
qsort(pCon->people, pCon->number, sizeof(People), MyCmp);//使用qsort函数根据姓名对结构体数组内容进行排序
if (0 == pCon->number)
{
printf("No contact.\n");
}
else
{
for (j = 0; j < pCon->number; j++)
{
printf("Name is :%s\n", pCon->people[j].name);
printf("Sex is :%s\n", pCon->people[j].sex);
printf("Age is %d\n", pCon->people[j].age);
printf("TeleponeNumber is %s\n", pCon->people[j].telephone_number);
printf("Address is %s\n\n", pCon->people[j].address);
}
}
}
void ClearContacts(Contact *pCon)//清空所有联系人
{
memset(pCon->people, 0, sizeof(People)*pCon->number);//变量内容全部清零
pCon->number = 0;//联系人个数置为0
printf("Empty success!\n");
}
void DestoryMalloc(Contact *pCon)//销毁动态申请的内存
{
if (pCon != NULL)
free(pCon->people);
pCon->people = NULL;
}
Test.c(测试文件)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"Contact.h"
#include<windows.h>
void test(Contact *pCon)
{
char Name[10];
int choice = 0;
InitContact(pCon);//初始化通讯录
LoadContact(pCon);//在每次进入程序,都从本地读取联系人给程序
do {
printf("**********************************************\n");
printf("1. 添加联系人信息 2. 删除指定联系人信息\n");
printf("3. 查找指定联系人信息 4. 修改指定联系人信息\n");
printf("5. 显示当前/文本联系人 6. 清空所有联系人 \n");
printf("7. 扩容 8.清空屏幕 \n");
printf(" 9. 退出 \n");
printf("**********************************************\n");
printf("Input choice:");
scanf("%d", &choice);
printf("-----------------------------------------------\n");
switch (choice)
{
case 1:
{
AddContacts(pCon);//添加联系人信息
}break;
case 2:
{
printf("Input name:");
scanf("%s", Name);
DeleteContcts(pCon, Name);//删除联系人信息
}break;
case 3:
{
printf("Input name:");
scanf("%s", Name);
SearchContacts(pCon, Name);//查找指定联系人信息
}break;
case 4:
{
printf("Input name:");
scanf("%s", Name);
AmendContacts(pCon, Name);//修改联系人信息
}break;
case 5:
{
ShowAllContacts(pCon);//显示所有联系人信息
}break;
case 6:
{
ClearContacts(pCon);//清空所有联系人信息
}break;
case 7:
{
EnlargeContact(pCon);//通讯录扩容
}break;
case 8:
{
system("cls");//清空屏幕
}break;
case 9://退出
{
SaveContact(pCon);//导出
DestoryMalloc(pCon);//退出时释放空间
}break;
default:
{
printf("Input Error.\n");
}break;
}
system("pause");
} while (9 != choice);
}
int main()
{
Contact contact;
test(&contact);
return 0;
}
函数功能实现难懂的地方,我都有注释,如果还有不懂的话,欢迎评论区留言给我。