功能
- 添加联系人(Addcontacts)
- 载入联系人信息(Loadcontacts)
- 查找联系人(Searchtacts)
- 通过姓名关键字查找
- 通过手机号码关键字查找
- 修改联系人(Modifytacts)
- 排序联系人(Sortcontacts)
- 删除联系人(Deletecontacts)
- 显示联系人(Showcontacts)
- 保存并退出(Savecontacts)
- 回收站(TRASH)
思路和关键模块介绍
思路
用C语言实现通讯录,那么最先知道每个联系人得信息:
- 姓名
- 性别
- 年龄
- 电话
所以我们需要先定义一个结构体struct Peinfo
来存储每个联系人得基本信息,再通过结构体数组得方式把联系人信息存储起来.在操作结束得时候,通过fwirte
函数将有效得联系人信息写入到文件里,再次打开得时候通过fread
函数将联系人信息导入,实现了基本通讯录得搭建流程。
关键模块介绍
为了不让空间浪费,我们不能直接通过指定结构体数组得方式来进行定义,为了解决这个问题,通过calloc
和ralloc
函数来动态开辟存储联系人信息。所以,在我们需要再次定义一个结构体,用于记录当前通讯录得各种基本状态。
#define FILENAME "r.dat"
#define NAME_MAX 20
#define SEX_LEN 6
#define TEL_LEN 11
#define DEFAU_SIZE 3
#define UP_SUCCESS 1
#define UP_FAIL -1
typedef struct Peinfo
{
char name[NAME_MAX];
int age;
char sex[SEX_LEN];
char tel[TEL_LEN];
int flag;
}Peinfo;
typedef struct contact
{
Peinfo* data;//用于存储联系人信息得结构体指针。
int count;//当前联系人个数
int cap;//扩容边界
int trash;//回收站信息计数。
}
void Trash(pCTT p)
回收站功能
对于顺序表结构,删除元素十分麻烦。既然要实现通讯录得删除联系人功能并且具有回收站,那么只需要在联系人信息得结构体里定义个删除标记,即FLAG
,当要删除联系人时,直接将flag置1,在通过trash
来记录即可。当要彻底删除时,使用qsort
以每个联系得flag来进行排序,那么有删除标记的联系人就将在最后,讲count减去trash最后写出count个进入文件,即实现了回收站的功能。
void Trash(pCTT p)
{
if (0 == p->count || p->trash == 0)
{
printf("Nothing here.\n");
}
else
{
printf("contacts in Trash->%d \n", p->trash);
printf("\n******\n");
int i = 0;
int choose = 0;
for (i = 0; i < p->count; i++)//打印信息
{
if (1 == p->data[i].flag)
{
printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
printf("\n******\n");
}
}
printf("1. remove all \n2. recover all ");
scanf("%d", &choose);
switch (choose)
{
case 1:
move(p);
break;
case 2:
recover(p);
break;
default:
printf("IPUT ERROR");
break;
}
}
}
int cmptrash(const void* str1, const void* str2)
{
return ((Peinfo*)str1)->flag - ((Peinfo*)str2)->flag;
}
void move(pCTT p)
{
qsort(p->data, p->count, sizeof(Peinfo), cmptrash);//将有删除标记得放在最后
p->count -= p->trash;
p->trash = 0;
printf("Trash has been cleaned up");
}
void recover(pCTT p)
{
int i = 0;
for (i = 0; i < p->count; i++)
{
if (1 == p->data[i].flag)
{
p->data[i].flag = 0;
p->trash--;
}
}
printf("Recover done");
}
void Searchcontact(pCTT p);
·搜索联系人
对于搜索而言,部分关键字查找既方便又可以实现多个预览。使用strstr函数来进行关键字查找
void Searchcontact(pCTT p)
{
if (0 == p->count)
{
printf("There have no contact\n ");
}
else
{
int key = 0;
printf("1.Searching by TEL \n2.Searching by Name\n ");
scanf("%d", &key);
switch (key)
{
case 1:
Telsearch(p);
break;
case 2:
Namesearch(p);
break;
}
}
}
void Telsearch(pCTT p)
{
char find[TEL_LEN] = { 0 };
int flag = 0;
printf("Pleasr enter TEL in part or full->");
scanf("%s", find);
int i = 0;
for (i = 0; i < p->count; i++)
{
if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
{
continue;
}
if (strstr(p->data[i].tel, find) != NULL)
{
printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
printf("\n******\n");
flag++;
}
}
if (0 == flag)
{
printf("No result from your enter ");
}
}
void Namesearch(pCTT p)
{
char find[NAME_MAX] = { 0 };
int flag = 0;
printf("Please enter Name->");
scanf("%s", find);
int i = 0;
for (i = 0; i < p->count; i++)
{
if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
{
continue;
}
if (strstr(p->data[i].name, find) != NULL)
{
printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
printf("\n******\n");
flag++;
}
}
if (0 == flag)
{
printf("No result from your enter ");
}
}
程序代码
contact.h函数原型
#pragma once
#define FILENAME "r.dat"
#define NAME_MAX 20
#define SEX_LEN 6
#define TEL_LEN 11
#define DEFAU_SIZE 3
#define UP_SUCCESS 1
#define UP_FAIL -1
typedef struct Peinfo
{
char name[NAME_MAX];
int age;
char sex[SEX_LEN];
char tel[TEL_LEN];
int flag;
}Peinfo;
typedef struct contact
{
Peinfo* data;
int count;
int cap;
int trash;//用于记录回收站是否有内容
}CTT,*pCTT;
//初始化通讯录
//添加信息
//查找信息
//修改信息
//排序
//删除
//回收站
//显示
//文件写入写出
void Init(pCTT p);
void Showcontact(pCTT p);
void Addcontact(pCTT p);
int Checkcontact(pCTT p);
void Loadcontact(pCTT p);
void Searchcontact(pCTT p);
void Savecontact(pCTT p);
void Telsearch(pCTT p);
void Namesearch(pCTT p);
void modify(pCTT p);
void Sortcon(pCTT p);
int cmp(const void* str1, const void* str2);
void Delete(pCTT p);
void Trash(pCTT p);
void move(pCTT p);
int cmptrash(const void* str1, const void* str2);
void recover(pCTT p);
contact.c函数定义
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include "contact.h"
#include<string.h>
void Init(pCTT p)
{
p->cap = DEFAU_SIZE;
p->count = 0;
p->data = (Peinfo*)calloc(sizeof(Peinfo), p->cap); //此处每次更新后需要初始化空间
p->trash = 0;
Loadcontact(p);
}
void Showcontact(pCTT p)
{
if (0 == p->count)
{
printf("There have no contact.\n");
}
else
{
printf("Number of contacts->%d \n", p->count - p->trash);//有效信息数目
printf("\n******\n");
int i = 0;
for (i = 0; i < p->count; i++)
{
if (0 == p->data[i].flag)
{
printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
printf("\n******\n");
}
}
}
}
void Addcontact(pCTT p)
{
if (UP_FAIL == Checkcontact(p))
{
printf("Increase capacity failed");
return;
}
else if (UP_SUCCESS == Checkcontact(p))
{
printf("Increase capacity success");
}
printf("Please enter Name:>");
scanf("%s", p->data[p->count].name);
printf("Please enter Age:>");
scanf("%d", &(p->data[p->count].age));
printf("Please enter sex:>");
scanf("%s", p->data[p->count].sex);
printf("Please enter TEL:>");
scanf("%s", p->data[p->count].tel);
p->data[p->count].flag = 0;//至关重要relloc后新内存flag为随机值
p->count++;//有效大小加1
printf("Add acontact success.\n");
}
int Checkcontact(pCTT p)
{
if (p->count >= p->cap)
{
Peinfo* tmp = (Peinfo*)realloc(p->data, sizeof(Peinfo)*(p->count + 2));
if (tmp != NULL)
{
p->data = tmp;
tmp = NULL;
p->cap =p->count+2;//在进行扩容后更新cap大小。
//切记,relloc后空间内容为随机值
return UP_SUCCESS;
}
else {
printf("contacts increase failed");
return UP_FAIL;
}
}
return 0;
}
void Loadcontact(pCTT p)
{
FILE *fp = (FILENAME, "r");
if (NULL == fp)
{
perror("Load data");
exit(EXIT_FAILURE);
}
Peinfo tmp = { 0 };
while (fread(&tmp, sizeof(Peinfo), 1, fp))//防止文件为空或者出错读取
{
Checkcontact(p);
p->data[p->count] = tmp;
if (p->data[p->count].flag == 1)
{
p->trash++;
}
p->count++;
}
fclose(fp);
fp = NULL;
}
void Searchcontact(pCTT p)
{
if (0 == p->count)
{
printf("There have no contact\n ");
}
else
{
int key = 0;
printf("1.Searching by TEL \n2.Searching by Name\n ");
scanf("%d", &key);
switch (key)
{
case 1:
Telsearch(p);
break;
case 2:
Namesearch(p);
break;
}
}
}
void Savecontact(pCTT p)
{
FILE *fp=fopen(FILENAME, "W");
int i = 0;
for (i = 0; i < p->count; i++)
{
fwrite(p->data + i, sizeof(Peinfo), 1, fp);
}
fclose(fp);
fp = NULL;
free(p->data); //别忘了释放
p->data = NULL;
}
void Telsearch(pCTT p)
{
char find[TEL_LEN] = { 0 };
int flag = 0;
printf("Pleasr enter TEL in part or full->");
scanf("%s", find);
int i = 0;
for (i = 0; i < p->count; i++)
{
if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
{
continue;
}
if (strstr(p->data[i].tel, find) != NULL)
{
printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
printf("\n******\n");
flag++;
}
}
if (0 == flag)
{
printf("No result from your enter ");
}
}
void Namesearch(pCTT p)
{
char find[NAME_MAX] = { 0 };
int flag = 0;
printf("Please enter Name->");
scanf("%s", find);
int i = 0;
for (i = 0; i < p->count; i++)
{
if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
{
continue;
}
if (strstr(p->data[i].name, find) != NULL)
{
printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
printf("\n******\n");
flag++;
}
}
if (0 == flag)
{
printf("No result from your enter ");
}
}
void modify(pCTT p)
{
if (0 == p->count)
{
printf("There have no contact.\n");
}
else
{
char find[NAME_MAX] = { 0 };
int i = 0;
printf("Please enter name whose you wanna modify\n");
scanf("%s", find);
int key = 0;
for (i = 0; i < p->count; i++)
{
if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
{
continue;
}
if (strcmp(p->data[i].name, find) == 0)
{
printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
printf("\nModify select:\n1.Name\n2.tel\n");
scanf("%d", &key);
switch (key)
{
case 1:
printf("Please enter Name:>");
scanf("%s", p->data[i].name);
break;
case 2:
printf("Please enter TEL:>");
scanf("%s", p->data[i].tel);
break;
default:
printf("WRONG NUM");
break;
}
return;
}
}
printf("No result");
}
}
void Sortcon(pCTT p)
{
if (2 >= p->count)
{
printf("There have no contact.");
}
else
{
qsort(p->data, p->count, sizeof(Peinfo), cmp);
printf("Sort done");
}
}
int cmp(const void* str1, const void* str2)
{
return strcmp(((Peinfo*)str1)->name, ((Peinfo*)str2)->name);
}
void Delete(pCTT p)
{
if (0 == p->count)
{
printf("There have no contact.\n");
}
else
{
char find[NAME_MAX] = { 0 };
int i = 0;
printf("Just give me a exact name\n");
scanf("%s", find);
for (i = 0; i < p->count; i++)
{
if (0 == strcmp(p->data[i].name, find))
{
p->data[i].flag = 1; //将目标单元信息组中得删除标记置1
p->trash++;
printf("Target has been remove to TRASH\n");
return;
}
}
printf("Not found\n");
}
}
void Trash(pCTT p)
{
if (0 == p->count || p->trash == 0)
{
printf("Nothing here.\n");
}
else
{
printf("contacts in Trash->%d \n", p->trash);
printf("\n******\n");
int i = 0;
int choose = 0;
for (i = 0; i < p->count; i++)//打印信息
{
if (1 == p->data[i].flag)
{
printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
printf("\n******\n");
}
}
printf("1. remove all \n2. recover all ");
scanf("%d", &choose);
switch (choose)
{
case 1:
move(p);
break;
case 2:
recover(p);
break;
default:
printf("IPUT ERROR");
break;
}
}
}
void move(pCTT p)
{
qsort(p->data, p->count, sizeof(Peinfo), cmptrash);//将有删除标记得放在最后
p->count -= p->trash;
p->trash = 0;
printf("Trash has been cleaned up");
}
void recover(pCTT p)
{
int i = 0;
for (i = 0; i < p->count; i++)
{
if (1 == p->data[i].flag)
{
p->data[i].flag = 0;
p->trash--;
}
}
printf("Recover done");
}
int cmptrash(const void* str1, const void* str2)
{
return ((Peinfo*)str1)->flag - ((Peinfo*)str2)->flag;
}
main.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Windows.h>
#include<stdlib.h>
#include "contact.h"
void menu()
{
printf("***********************************\n");
printf("********1. ADD contacts *******\n");
printf("********2.Search contacts *******\n");
printf("********3.Modify contacts *******\n");
printf("********4. Sort contacts *******\n");
printf("********5. Show contacts *******\n");
printf("********6.Delete contacts *******\n");
printf("********7. TRASH *******\n");
printf("******** 0.SAVE AND EXIT ********\n");
printf("***********************************\n");
}
int main()
{
int option;
CTT contact;
Init(&contact);
char a = 0;
do
{
menu();
printf("Enter right sequence number to operate->");
while (scanf("%d", &option) != 1)
{
printf("input error\n");
scanf("%*[^\n]*c");
}
void(*arrfun[])(pCTT) = { Savecontact, Addcontact,Searchcontact,modify,Sortcon,Showcontact,Delete,Trash };
if (option >= 0 && option < sizeof(arrfun))
{
arrfun[option](&contact);
}
} while (option);
system("pause");
return 0;
}