第一段代码是通讯录实现所需要的函数声明和一些值的定义,结构体的创建,详细见代码
#pragma once //这个头文件包括一些库函数的头文件,结构体的创建,还有一些值的定义,还有自定义函数的声明 #define _CRT_SECURE_NO_WARNINGS 1 #pragma warning(disable:6031) #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX 3 #define NAME 20 #define SEX 10 #define ADDR 20 struct sb { char name[NAME]; int age; char sex[SEX]; long long int tele; char addr[ADDR]; }; struct contact { struct sb*data; int contain; int size; }con; int csh(struct contact* ps); void addcontact(struct contact* ps); void menu(); void delcontact(struct contact* ps); void modifycontact(struct contact* ps); void searchcontact(const struct contact* ps); void showcontact(const struct contact* ps); void sortcontact(struct contact* ps); int savecontact(struct contact* ps); void sfnc(struct contact* ps);
第二段代码是整个通讯录实现的逻辑,主要功能等,详细见代码
#include"contact.h"
//枚举:增加代码的可读性
enum u {
EXIT,//0
ADD,//1
DEL,//2
MODIFY,//3
SEARCH,//4
SHOW,//5
SORT//6
};
//整个通讯录的实现过程
int main() {
int input = 0;
struct contact con;
//初始化函数:把上次运行时输入的数据,继承过来,进行判断是防止文件打开有问题,有问题则直接停止
if (csh(&con)) {
return 0;
}
do
{
menu();
scanf("%d", &input);
switch(input) {
//使用枚举代替数字,增加可读性:
case ADD://1
addcontact(&con);
break;
case DEL://2
delcontact(&con);
break;
case MODIFY://3
modifycontact(&con);
break;
case SEARCH://4
searchcontact(&con);
break;
case SHOW://5
showcontact(&con);
break;
case SORT://6
sortcontact(&con);
break;
case EXIT://0
//在通讯录结束时自动保存输入的数据,if语句防止保存失败。
if (savecontact(&con))
continue;
//释放内存,以免泄露。
sfnc(&con);
printf("以退出程序\n");
break;
default:
printf("选择错误:>\n");
break;
}
} while (input);
return 0;
}
第三段是实现通讯录所需函数的定义,也是最重要的部分,里面涉及了动态内存的分配,内存申请,文件的操作等,详细见代码
#pragma warning(disable:6031)
//该文件用于对使用的自定义函数定义
#include"contact.h"
//菜单:
void menu() {
printf("*********************************\n");
printf("***1.add 2.del ***\n");
printf("***3.modify 4.search***\n");
printf("***5.show 6.sort ***\n");
printf("*********** 0.exit ************\n");
printf("*********************************\n");
}
//这个函数用于查找函数和删除函数,加是static可以使这个函数只能在这个源文件使用,在其他的源文件中不能用,以免干扰其他源文件
static int findbyname(const struct contact* s, char name[NAME]) {
for (int i = 0; i < s->size ; i++) {
if (0 == strcmp(s->data[i].name, name)) {
return i;
}
}
return -1;
}
//内存增加,原始内存为3,超过3就加2个空间,再超过则再加2,以此类推
void pdcontact(struct contact *ps) {
if (ps->size == ps->contain) {
ps->contain += 2;
struct sb* pr = (struct sb*)realloc(ps->data, ps->contain * sizeof(struct sb));
if (pr != NULL) {
ps->data = pr;
printf("增容成功\n");
}
else
printf("增容失败\n");
}
}
//判断是否联系人已经重复有了
int cfcontact(struct contact* ps,int count) {
for (int i = 0; i < count; i++) {
if (strcmp(ps->data[i].addr , ps->data[count].addr)==0 && ps->data[i].age == ps->data[count].age
&& strcmp(ps->data[i].name, ps->data[count].name) == 0 && strcmp(ps->data[i].sex, ps->data[count].sex) == 0 &&
ps->data[i].tele == ps->data[count].tele) {
return 1;
}
}
return 0;
}
//把创建的结构体初始化:
int csh(struct contact* ps) {
struct sb* pr = (struct sb*)calloc(MAX, sizeof(struct sb));
if (pr != NULL) {
ps->data = pr;
}
//打开文件,读取上次输入的内容,
FILE* ptr = fopen("test.txt", "rb");
if (ptr == NULL) {
//如果打开失败,告诉原因,并结束。
perror("open file error");
return 1;
}
ps->size = 0;
ps->contain = MAX;
//读取
while (fread(&(ps->data[ps->size]), sizeof(struct sb), 1, ptr)) {
ps->size++;
//判断是否需要增容。
pdcontact(ps);
}
//关闭文件
fclose(ptr);
ptr = NULL;
}
//添加联系人:
void addcontact(struct contact* ps) {
//动态内存增加,以免造成空间的浪费
pdcontact(ps);
printf("请输入联系人信息:>\n");
printf("姓名:>");
scanf("%s",&ps->data[ps->size].name);
printf("年龄:> ");
scanf("%d", &ps->data[ps->size].age);
printf("性别:> ");
scanf("%s", &ps->data[ps->size].sex);
printf("电话号码:> ");
scanf("%lld", &ps->data[ps->size].tele);
printf("地址:> ");
scanf("%s", &ps->data[ps->size].addr);
//判断用户新增的联系人是否重复。
int ret=cfcontact(ps,ps->size);
if (ret) {
//如果重复了,把刚刚输入的数据初始化,并且ps->size不用加1.
memset(&(ps->data[ps->size]), 0, sizeof(struct sb));
printf("该联系人以存在,添加失败:>\n");
}
//没重复则继续
else {
ps->size++;
printf("添加成功\n");
}
}
//删除联系人:
void delcontact(struct contact* ps) {
if (ps->size == 0) {
printf("该通讯录目前无联系人:>\n");
return;
}
char name[NAME];
printf("请输入要删除的姓名:>\n");
scanf("%s", &name);
int ret = findbyname(ps, name);
if (ret == -1)printf("该成员不存在\n");
else {
for (int i = ret; i < ps->size - 1; i++) {
ps->data[i] = ps->data[i + 1];
}
ps->size--;
printf("删除成功:>\n");
}
}
//修改其中的联系人数据:
void modifycontact(struct contact* ps) {
if (ps->size == 0) {
printf("该通讯录目前无联系人:>\n");
return;
}
char name[NAME];
printf("请输入你将修改的姓名:>\n");
scanf("%s", &name);
int ret=findbyname(ps, name);
if (ret == -1)printf("该成员不存在\n");
else {
printf("请重新输入联系人信息:>\n");
printf("姓名 :>");
scanf("%s", &ps->data[ret].name);
printf("年龄 :> ");
scanf("%d", &ps->data[ret].age);
printf("性别 :> ");
scanf("%s", &ps->data[ret].sex);
printf("电话号码:> ");
scanf("%lld", &ps->data[ret].tele);
printf("地址 :> ");
scanf("%s", &ps->data[ret].addr);
printf("修改成功:>\n");
}
}
//查找联系人:
void searchcontact(const struct contact* ps) {
if (ps->size == 0) {
printf("该通讯录目前无联系人:>\n");
return;
}
char name[NAME];
printf("请输入你想查找的联系人姓名:>\n");
scanf("%s", &name);
int ret=findbyname(ps,name);
if (ret == -1) {
printf("该成员不存在\n");
}
else {
printf("%-20s\t%-20s\t%-20s\t%-20s \t%-20s\t\n", "姓名", "年龄", "性别", "电话号码", "地址");
printf("%-20s\t%-20d\t%-20s\t%-20lld\t%-20s\t\n", ps->data[ret].name, ps->data[ret].age, ps->data[ret].sex, ps->data[ret].tele, ps->data[ret].addr);
}
}
//打印已经添加的通讯录
void showcontact(const struct contact* ps) {
if (ps->size == 0) {
printf("该通讯录目前无联系人:>\n");
return;
}
printf("%-20s\t%-20s\t%-20s\t%-20s \t%-20s\t\n", "姓名", "年龄", "性别", "电话号码", "地址");
for (int i = 0; i < ps->size; i++) {
printf("%-20s\t%-20d\t%-20s\t%-20lld\t%-20s\t\n", ps->data[i].name, ps->data[i].age, ps->data[i].sex,ps->data[i].tele, ps->data[i].addr);
}
}
//选择年龄升序
void sortcontact(struct contact* ps) {
if (ps->size == 0) {
printf("该通讯录目前无联系人:>\n");
return;
}
for (int i = 0; i < ps->size; i++) {
for (int j = i+1; j < ps->size; j++) {
//这里不能只改年龄,建立一个临时结构体变量(必须和data类型一样),
if (ps->data[i].age > ps->data[j].age) {
struct sb t = ps->data[i];
ps->data[i] = ps->data[j];
ps->data[j] = t;
}
}
}
//重新打印排序后的通讯录
showcontact(ps);
}
void sfnc(struct contact* ps) {
free(ps->data);
//free会释放掉内存但是ps->data的指针依然会保留,为了防止非法访问,将ps->data变成空指针
ps->data = NULL;
}
int savecontact(struct contact* ps) {
//创建一个二进制文件
FILE* ptr = fopen("test.txt", "wb");
//进行判断是否创建成功
if (ptr == NULL) {
//如果失败了,说明失败原因
perror("save error");
return 1;
}
//保存
for (int i = 0; i < ps->size; i++) {
fwrite(&(ps->data[i]), sizeof(struct sb), 1, ptr);
}
printf("保存成功\n");
//关闭文件
fclose(ptr);
ptr = NULL;
}