目录
程序效果
主页![d677355204974f0ca8b9eff334d2cb11.png](https://i-blog.csdnimg.cn/direct/d677355204974f0ca8b9eff334d2cb11.png)
新建![a94c9b68ae4649bab0f6ff609cf5307c.png](https://i-blog.csdnimg.cn/direct/a94c9b68ae4649bab0f6ff609cf5307c.png)
打印
搜索
删除
修改
排序
![feab4c3543104f208fc96db343e3f9e8.png](https://i-blog.csdnimg.cn/direct/feab4c3543104f208fc96db343e3f9e8.png)
错误
文件保存
代码实现
头文件
contact.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1 //使scanf()、fscanf()函数适用于VS平台
#define MAX_NAME 20//名字最大长度
#define MAX_TELE_NUM 15//电话号码最大长度
#define MAX_ADDR 30//地址最大长度
#define MAX_SEX 5 //性别字符最大长度
#define DEFAULT_CAP 100 //初始空间分配容量
#define INC_CAP 10 //空间不足时增加的单位容量
#include <stdio.h>
#include <string.h>
#include <Windows.h>
#include <stdlib.h>
enum search_type {
name = 1,
tele_num,
addr
};
//搜索类型
enum modify_type {
name_m = 1,
sex_m,
age_m,
tele_num_m,
addr_m
};
//修改类型
enum sort_type {
name_s = 1,
age_s,
tele_num_s,
addr_s
};
//排序类型
typedef struct PeoInfo {
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele_num[MAX_TELE_NUM];
char addr[MAX_ADDR];
}PeoInfo;
//通讯录个人信息
typedef struct Contact {
PeoInfo* data;//数据总体的指针(数组),可变大小
size_t size;//当前通讯录长度
size_t capacity;//当前通讯录容量
}Contact;
//通讯录总体结构
void getchar_clean();//清理缓冲区
void wait_enter();//等待输入回车
void InitContact( Contact* main_con
);//初始化通讯录
void add( Contact* main_con
);//增加联系人
void del( Contact* main_con
);//删除联系人
void del_m( Contact* main_con,
size_t code_m
);//删除联系人算法
void search( const Contact* main_con
);//搜索联系人
int search_m( const Contact* main_con,
enum search_type search_t,
const char* content
);//搜索联系人算法
void modify( Contact* main_con
);//修改联系人信息
void modify_m( Contact* main_con,
enum modify_type modify_t,
const char* content,
size_t i
);//修改联系人信息算法
void sort( Contact* main_con
);//排序
void print( const Contact* main_con
);//展示通讯录
void print_m( const Contact* main_con
);//展示通讯录算法
void exit_m( Contact* main_con
);//回收动态内存空间,指针赋空值
void SaveContact( Contact* main_con
);//保存通讯录信息于文件中
/*代码缺陷:无法避免信息(名字、电话号码)重复问题,
且当重复时(名字、电话号码、地址)使用搜索功能只能找到唯一对象*/
源文件
contact.c
#include "contact.h"
void getchar_clean() {
while (getchar() != '\n');
}
void wait_enter() {
printf("\n\n点击回车以继续...\n");
getchar_clean();
while (getchar() != '\n');//等待回车
system("cls");
}
void InitContact(Contact* main_con) {
FILE* pfile_info = fopen("coninfo.dat", "r");//打开文件
if (pfile_info == NULL) { //第一次使用程序
main_con->size = 0;
main_con->capacity = DEFAULT_CAP;
}
else//第n次使用,继承size和capacity数据
fscanf(pfile_info, "%zd %zd", &(main_con->size), &(main_con->capacity));
//calloc函数分配动态空间
PeoInfo* ptr = (PeoInfo*)calloc(main_con->capacity, sizeof(PeoInfo));
if (ptr != NULL)
main_con->data = ptr;//分配动态内存空间
else
perror("InitContact");//空间不足时报错
if (pfile_info == NULL)
return;//第一次使用程序,函数直接结束
FILE* pfile_data = fopen("condata.dat", "r");
for (size_t i = 0; i < main_con->size; i++)
fread(main_con->data + i, sizeof(PeoInfo), 1, pfile_data);
//第n次使用,将data的数据拷贝
}
void add(Contact* main_con) {
system("cls");
if (main_con->size == main_con->capacity - 1) {
//-1保证有缓冲空间,利于del_m函数稳定实现
PeoInfo* ptr = realloc(main_con->data, (main_con->capacity += INC_CAP) * sizeof(PeoInfo));
//realloc函数调整
if (ptr != NULL)
main_con->data = ptr;
else{
perror("add");
printf("\n _______________________________________\n\n");
printf(" 警告\n\n\t通讯录空间不足,无法增加联系人!\n\n");
printf(" _______________________________________\n");
wait_enter();
return;
}
}
//空间不足时微调
printf(" 新建联系人\n_____________________________\n");
printf("\n姓名:");
scanf("%s", main_con->data[main_con->size].name);
printf("\n年龄:");
scanf("%d", &(main_con->data[main_con->size].age));
printf("\n性别:");
scanf("%s", main_con->data[main_con->size].sex);
printf("\n电话号码:");
scanf("%s", main_con->data[main_con->size].tele_num);
printf("\n地址:");
scanf("%s", main_con->data[main_con->size].addr);
main_con->size++;
printf("\n\n新建联系人成功!\n");
wait_enter();
}
void del_m(Contact* main_con, size_t code_m) {
for (size_t i = code_m; i < main_con->size; i++) {
main_con->data[i] = main_con->data[i + 1];
}
main_con->size--;//size数值减一
}
void del(Contact* main_con) {
system("cls");
if (main_con->size == 0) {
printf(" _______________________________________\n\n");
printf(" 警告\n\n\t通讯录内容空白,无法删除联系人!\n\n");
printf(" _______________________________________\n");
wait_enter();
return;
}
printf(" 删除联系人\n_____________________________\n");
printf("请输入要删除联系人的姓名:");
char search_name[MAX_NAME];
scanf("%s", search_name);
int ret = search_m(main_con, name, search_name);
if (ret == -1) {
printf("\n\n未查找到指定联系人!\n");
wait_enter();
return;
}
system("cls");
printf("\n已找到指定联系人\n\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[ret].name,
main_con->data[ret].sex,
main_con->data[ret].age,
main_con->data[ret].tele_num,
main_con->data[ret].addr);
printf("\n请确认是否将其删除(1:确认/2:取消)\n");
int input;
scanf("%d", &input);
if (input == 1) {
del_m(main_con, ret);
printf("\n\n删除成功!\n");
}
else
printf("\n\n已取消删除\n");
wait_enter();
}
int search_m(const Contact* main_con, enum search_type search_t, const char* content) {
size_t i = 0;
switch (search_t) {
case name:
for (i = 0; i < main_con->size; i++) {
if (strcmp(content, main_con->data[i].name) == 0)
return (int)i;
}
return -1;
break;
case tele_num:
for (i = 0; i < main_con->size; i++) {
if (strcmp(content, main_con->data[i].tele_num) == 0)
return (int)i;
}
return -1;
break;
case addr:
for (i = 0; i < main_con->size; i++) {
if (strcmp(content, main_con->data[i].addr) == 0)
return (int)i;
}
return -1;
break;
default:
return -2;
break;
}
}
void search(const Contact* main_con) {
system("cls");
if (main_con->size == 0) {
printf(" _______________________________________\n\n");
printf(" 警告\n\n\t通讯录内容空白,无法搜索联系人!\n\n");
printf(" _______________________________________\n");
wait_enter();
return;
}
//空白
printf(" \t\t\t搜索联系人\n________________________________________________________\n");
printf("请选择搜索联系人的方式(1:姓名 2:电话号码 3:地址):\n");
int input;
scanf("%d", &input);
if (input != 1 && input != 2 && input != 3) {
printf("\n\n输入错误\n");
wait_enter();
return;
}
//输入
printf("请输入查找内容:");
char src[MAX_ADDR];
scanf("%s", src);
int ret = search_m(main_con, (enum search_type)input, src);
if (ret == -1) {
printf("\n\n未查找到指定联系人!\n");
wait_enter();
return;
}
system("cls");
printf("\n已找到指定联系人\n\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[ret].name,
main_con->data[ret].sex,
main_con->data[ret].age,
main_con->data[ret].tele_num,
main_con->data[ret].addr);
wait_enter();
}
void modify_m(Contact* main_con, enum modify_type modify_t, const char* content, size_t i) {
switch (modify_t) {
case name_m:
strcpy(main_con->data[i].name, content);
break;
case sex_m:
strcpy(main_con->data[i].sex, content);
break;
case tele_num_m:
strcpy(main_con->data[i].tele_num, content);
break;
case addr_m:
strcpy(main_con->data[i].addr, content);
break;
default:
break;
}
}
void modify(Contact* main_con) {
system("cls");
if (main_con->size == 0) {
printf(" _______________________________________\n\n");
printf(" 警告\n\n\t通讯录内容空白,无法修改联系人信息!\n\n");
printf(" _______________________________________\n");
wait_enter();
return;
}
//空白
printf(" 修改联系人信息\n_____________________________\n");
printf("请输入要修改联系人的电话号码:");
char search_tele[MAX_TELE_NUM];
scanf("%s", search_tele);
int ret = search_m(main_con, tele_num, search_tele);
//输入
if (ret == -1) {
printf("\n\n未查找到指定联系人!\n");
wait_enter();
return;
}
system("cls");
printf("\n已找到指定联系人\n\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[ret].name,
main_con->data[ret].sex,
main_con->data[ret].age,
main_con->data[ret].tele_num,
main_con->data[ret].addr);
printf("\n请输入修改类型(1.姓名 2.性别 3.年龄 4.电话号码 5.地址):\n");
int input;
scanf("%d", &input);
if (input != 1 && input != 2 && input != 3 && input != 4 && input != 5) {
printf("\n\n输入错误\n");
wait_enter();
return;
}
(enum modify_type)input;
if (input == age_m) {
printf("请输入修改的值:");
scanf("%d", &(main_con->data[ret].age));
}
else {
printf("请输入修改内容:");
char src[MAX_ADDR];
scanf("%s", src);
modify_m(main_con, input, src, ret);
}
system("cls");
printf("\n修改成功!\n\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[ret].name,
main_con->data[ret].sex,
main_con->data[ret].age,
main_con->data[ret].tele_num,
main_con->data[ret].addr);
wait_enter();
}
static int sort_by_name(const void* p1, const void* p2) {
return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
static int sort_by_age(const void* p1, const void* p2) {
return ((PeoInfo*)p1)->age - ((PeoInfo*)p2)->age;
}
static int sort_by_tele(const void* p1, const void* p2) {
return strcmp(((PeoInfo*)p1)->tele_num, ((PeoInfo*)p2)->tele_num);
}
static int sort_by_addr(const void* p1, const void* p2) {
return strcmp(((PeoInfo*)p1)->addr, ((PeoInfo*)p2)->addr);
}
void sort(Contact* main_con) {
system("cls");
if (main_con->size == 0) {
printf(" _______________________________________\n\n");
printf(" 警告\n\n\t通讯录内容空白,无法修改联系人信息!\n\n");
printf(" _______________________________________\n");
wait_enter();
return;
}
//空白
printf("\n请输入排序标准(1.姓名 2.年龄 3.电话号码 4.地址):\n");
int input;
scanf("%d", &input);
if (input != 1 && input != 2 && input != 3 && input != 4) {
printf("\n\n输入错误\n");
wait_enter();
return;
}
(enum sort_type)input;
int (*sort_func)(const void* p1, const void* p2) = NULL;//比较函数指针变量
if (input == name_s)
sort_func = sort_by_name;
else if (input == age_s)
sort_func = sort_by_age;
else if (input == tele_num_s)
sort_func = sort_by_tele;
else if (input == addr_s)
sort_func = sort_by_addr;
qsort((void*)main_con->data, main_con->size, sizeof(main_con->data[0]), sort_func);
system("cls");
printf("排序成功!\n\n");
print_m((const Contact*)main_con);
wait_enter();
}
void print_m(const Contact* main_con) {
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
for (size_t i = 0; i < main_con->size; i++) {
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[i].name,
main_con->data[i].sex,
main_con->data[i].age,
main_con->data[i].tele_num,
main_con->data[i].addr);
}
}
void print(const Contact* main_con) {
system("cls");
printf(" 通讯录列表\n\n");
print_m(main_con);
wait_enter();
}
void exit_m(Contact* main_con) {
free(main_con->data);
main_con->data = NULL;
}
void SaveContact(Contact* main_con) {
FILE* pfile_data = fopen("condata.dat", "w");
FILE* pfile_info = fopen("coninfo.dat", "w");//打开文件
if (pfile_data == NULL) {
perror("File Open");
return;
}
if (pfile_info == NULL) {
perror("File Open");
return;
}//错误情况
for (size_t i = 0; i < main_con->size; i++)
fwrite(main_con->data + i, sizeof(PeoInfo), 1, pfile_data);
//写data文件
fprintf(pfile_info, "%zd %zd", main_con->size, main_con->capacity);
//写info文件
//关闭文件
fclose(pfile_data);
pfile_data = NULL;
fclose(pfile_info);
pfile_info = NULL;
printf("\n\n通讯录保存成功!程序已退出\n");
wait_enter();
}
test.c
#include "contact.h"
enum choice {
Exit,
Add,
Del,
Search,
Modify,
Sort,
Print
};
//操作选项
void menu() {
printf(" 主页 \n\n");
printf(" 1.新建 2.删除 \n");
printf(" 3.搜索 4.修改 \n");
printf(" 5.排序 6.打印 \n");
printf(" 0.退出 \n");
printf("\n请选择:");
}
//菜单主页
int main() {
Contact con;
InitContact(&con);
//初始化通讯录
int input = 0;
do {
menu();
again:
scanf("%d", &input);
switch ((enum choice)input) {
case Add:
add(&con);
break;
case Del:
del(&con);
break;
case Search:
search(&con);
break;
case Modify:
modify(&con);
break;
case Sort:
sort(&con);
break;
case Print:
print(&con);
break;
case Exit:
SaveContact(&con);
exit_m(&con);
break;
default:
printf("输入错误,请重新输入:\n");
goto again;
break;
}
} while (input);
return 0;
}
//程序入口
代码详解
test.c
主页&main函数
void menu() {
printf(" 主页 \n\n");
printf(" 1.新建 2.删除 \n");
printf(" 3.搜索 4.修改 \n");
printf(" 5.排序 6.打印 \n");
printf(" 0.退出 \n");
printf("\n请选择:");
}
//菜单主页
int main() {
Contact con;
//main函数首先通过通讯录结构体Contact创建con变量,通讯录主体对象
InitContact(&con);
//通过该函数对con初始化,第二次使用则导入文件信息
int input = 0;//接收用户输入内容的变量
do {
menu();//菜单主页
again://输入错误时重新输入
scanf("%d", &input);//用户输入
//switch判断用户输入内容,调用不同的函数程序
switch ((enum choice)input) {
case Add://新建
add(&con);
break;
case Del://删除
del(&con);
break;
case Search://搜索
search(&con);
break;
case Modify://修改
modify(&con);
break;
case Sort://排序
sort(&con);
break;
case Print://展示
print(&con);
break;
case Exit://退出
SaveContact(&con);//保存
exit_m(&con);
break;
default:
printf("输入错误,请重新输入:\n");
goto again;//输入错误时重新输入
break;
}
} while (input);//do_while循环保证程序持续运行
return 0;
}
枚举输入内容
enum choice {
Exit,
Add,
Del,
Search,
Modify,
Sort,
Print
};
//操作选项
contact.h
库函数头文件
#include <stdio.h>
#include <string.h>
#include <Windows.h>
#include <stdlib.h>
参数定义
#define MAX_NAME 20//名字最大长度
#define MAX_TELE_NUM 15//电话号码最大长度
#define MAX_ADDR 30//地址最大长度
#define MAX_SEX 5 //性别字符最大长度
#define DEFAULT_CAP 100 //初始空间分配容量
#define INC_CAP 10 //空间不足时增加的单位容量
枚举类型
enum search_type {
name = 1,
tele_num,
addr
};
//搜索类型
enum modify_type {
name_m = 1,
sex_m,
age_m,
tele_num_m,
addr_m
};
//修改类型
enum sort_type {
name_s = 1,
age_s,
tele_num_s,
addr_s
};
//排序类型
结构体
typedef struct PeoInfo {
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele_num[MAX_TELE_NUM];
char addr[MAX_ADDR];
}PeoInfo;
//通讯录个人信息
typedef struct Contact {
PeoInfo* data;//数据总体的指针(数组),可变大小
size_t size;//当前通讯录长度
size_t capacity;//当前通讯录容量
}Contact;
//通讯录总体结构
功能函数
void getchar_clean();//清理缓冲区
void wait_enter();//等待输入回车
void InitContact(Contact* main_con);//初始化通讯录
主体函数
void add( Contact* main_con//通讯录主体
);//增加联系人
void del( Contact* main_con
);//删除联系人
void del_m( Contact* main_con,
size_t code_m//删除元素下标
);//删除联系人算法
void search( const Contact* main_con//const修饰防止通讯录主体被改变
);//搜索联系人
int search_m( const Contact* main_con,
enum search_type search_t, //搜索方式
const char* content//搜索内容
);//搜索联系人算法
void modify( Contact* main_con
);//修改联系人信息
void modify_m( Contact* main_con,
enum modify_type modify_t, //修改类型
const char* content, //修改内容
size_t i//修改元素下标
);//修改联系人信息算法
void sort( Contact* main_con
);//排序
void print( const Contact* main_con
);//展示通讯录
void print_m( const Contact* main_con
);//展示通讯录算法
void exit_m( Contact* main_con
);//回收动态内存空间,指针赋空值
void SaveContact( Contact* main_con
);//保存通讯录信息于文件中
contact.c
等待回车
void getchar_clean() {
while (getchar() != '\n');
}
void wait_enter() {
printf("\n\n点击回车以继续...\n");
getchar_clean();//清理缓冲区
while (getchar() != '\n');//等待回车
system("cls");//清屏(Windows.h)
}
初始化
void InitContact(Contact* main_con) {
//“初始化”建议与“保存”结合阅读
FILE* pfile_info = fopen("coninfo.dat", "r");//打开info文件
if (pfile_info == NULL) { //第一次使用程序
main_con->size = 0;//初始大小为0
main_con->capacity = DEFAULT_CAP;//默认容量
}
else//第n次使用,继承size和capacity数据
fscanf(pfile_info, "%zd %zd", &(main_con->size), &(main_con->capacity));
//%zd读取size_t类型数据
//calloc函数在堆区分配动态内存空间
PeoInfo* ptr = (PeoInfo*)calloc(main_con->capacity, sizeof(PeoInfo));
if (ptr != NULL)
main_con->data = ptr;//分配动态内存空间
else
perror("InitContact");//空间不足时使用perror函数报错
if (pfile_info == NULL)
return;//第一次使用程序,函数直接结束
FILE* pfile_data = fopen("condata.dat", "r");//打开data文件
for (size_t i = 0; i < main_con->size; i++)
fread(main_con->data + i, sizeof(PeoInfo), 1, pfile_data);
//第n次使用,将data的数据读取
}
新增联系人
void add(Contact* main_con) {
system("cls");//清屏
if (main_con->size == main_con->capacity - 1) {
//空间不足情况,-1保证有缓冲空间,利于del_m函数稳定实现
PeoInfo* ptr = realloc(main_con->data, (main_con->capacity += INC_CAP) * sizeof(PeoInfo));
//realloc函数调整空间大小
if (ptr != NULL)
main_con->data = ptr;
else{
perror("add");
printf("\n _______________________________________\n\n");
printf(" 警告\n\n\t通讯录空间不足,无法增加联系人!\n\n");
printf(" _______________________________________\n");
wait_enter();
return;
}
}
//空间不足时微调
printf(" 新建联系人\n_____________________________\n");
printf("\n姓名:");
scanf("%s", main_con->data[main_con->size].name);
printf("\n年龄:");
scanf("%d", &(main_con->data[main_con->size].age));
printf("\n性别:");
scanf("%s", main_con->data[main_con->size].sex);
printf("\n电话号码:");
scanf("%s", main_con->data[main_con->size].tele_num);
printf("\n地址:");
scanf("%s", main_con->data[main_con->size].addr);
//输入内容
main_con->size++;//空间大小+1
printf("\n\n新建联系人成功!\n");
wait_enter();
}
展示通讯录
void print_m(const Contact* main_con) {
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
//目录栏
for (size_t i = 0; i < main_con->size; i++) {
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[i].name,
main_con->data[i].sex,
main_con->data[i].age,
main_con->data[i].tele_num,
main_con->data[i].addr);
}
//每行打印
}
void print(const Contact* main_con) {
system("cls");//清屏
printf(" 通讯录列表\n\n");//标题
print_m(main_con);
wait_enter();
}
搜索联系人
//搜索算法实现
int search_m(const Contact* main_con, enum search_type search_t, const char* content) {
size_t i = 0;//循环变量
switch (search_t) {
case name:
for (i = 0; i < main_con->size; i++) {
if (strcmp(content, main_con->data[i].name) == 0)//strcmp函数判断字符串是否相同
return (int)i;
}
return -1;
break;
case tele_num:
for (i = 0; i < main_con->size; i++) {
if (strcmp(content, main_con->data[i].tele_num) == 0)
return (int)i;
}
return -1;
break;
case addr:
for (i = 0; i < main_con->size; i++) {
if (strcmp(content, main_con->data[i].addr) == 0)
return (int)i;
}
return -1;
break;
default:
return -2;
break;
}
}
void search(const Contact* main_con) {
system("cls");//清屏
if (main_con->size == 0) {
printf(" _______________________________________\n\n");
printf(" 警告\n\n\t通讯录内容空白,无法搜索联系人!\n\n");
printf(" _______________________________________\n");
wait_enter();
return;
}
//空白情况
printf(" \t\t\t搜索联系人\n________________________________________________________\n");
printf("请选择搜索联系人的方式(1:姓名 2:电话号码 3:地址):\n");
int input;
scanf("%d", &input);
if (input != 1 && input != 2 && input != 3) {
printf("\n\n输入错误\n");
wait_enter();
return;
}
//输入错误情况
printf("请输入查找内容:");
char src[MAX_ADDR];//接收用户输入内容
scanf("%s", src);
int ret = search_m(main_con, (enum search_type)input, src);//搜索算法
if (ret == -1) {
printf("\n\n未查找到指定联系人!\n");
wait_enter();
return;
}
system("cls");
printf("\n已找到指定联系人\n\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[ret].name,
main_con->data[ret].sex,
main_con->data[ret].age,
main_con->data[ret].tele_num,
main_con->data[ret].addr);
//打印对应信息
wait_enter();
}
删除联系人
//删除算法
void del_m(Contact* main_con, size_t code_m) { //code_m为删除元素下标
for (size_t i = code_m; i < main_con->size; i++) {
main_con->data[i] = main_con->data[i + 1];//向前紧排
}
main_con->size--;//size数值减一
}
void del(Contact* main_con) {
system("cls");//清屏
if (main_con->size == 0) {
printf(" _______________________________________\n\n");
printf(" 警告\n\n\t通讯录内容空白,无法删除联系人!\n\n");
printf(" _______________________________________\n");
//printf("\n\n点击回车以继续...\n");
wait_enter();
return;
}
//空白情况
printf(" 删除联系人\n_____________________________\n");
printf("请输入要删除联系人的姓名:");
char search_name[MAX_NAME];//接收输入内容
scanf("%s", search_name);
int ret = search_m(main_con, name, search_name);//调用search_m进行查找
if (ret == -1) {
printf("\n\n未查找到指定联系人!\n");
wait_enter();
return;
}
system("cls");
printf("\n已找到指定联系人\n\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[ret].name,
main_con->data[ret].sex,
main_con->data[ret].age,
main_con->data[ret].tele_num,
main_con->data[ret].addr);
//打印信息
printf("\n请确认是否将其删除(1:确认/2:取消)\n");
int input;
scanf("%d", &input);
//确认过程
if (input == 1) {
del_m(main_con, ret);//删除算法实现
printf("\n\n删除成功!\n");
}
else
printf("\n\n已取消删除\n");
wait_enter();
}
修改联系人信息
//修改算法
void modify_m(Contact* main_con, enum modify_type modify_t, const char* content, size_t i) {
switch (modify_t) {
case name_m:
strcpy(main_con->data[i].name, content);//使用strcpy函数对字符串修改
break;
case sex_m:
strcpy(main_con->data[i].sex, content);
break;
case tele_num_m:
strcpy(main_con->data[i].tele_num, content);
break;
case addr_m:
strcpy(main_con->data[i].addr, content);
break;
default:
break;
}
}
void modify(Contact* main_con) {
system("cls");//清屏
if (main_con->size == 0) {
printf(" _______________________________________\n\n");
printf(" 警告\n\n\t通讯录内容空白,无法修改联系人信息!\n\n");
printf(" _______________________________________\n");
wait_enter();
return;
}
//空白情况
printf(" 修改联系人信息\n_____________________________\n");
printf("请输入要修改联系人的电话号码:");
char search_tele[MAX_TELE_NUM];
scanf("%s", search_tele);
int ret = search_m(main_con, tele_num, search_tele);
//接收用户输入
if (ret == -1) {
printf("\n\n未查找到指定联系人!\n");
wait_enter();
return;
}
//查找失败
system("cls");
printf("\n已找到指定联系人\n\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[ret].name,
main_con->data[ret].sex,
main_con->data[ret].age,
main_con->data[ret].tele_num,
main_con->data[ret].addr);
//打印相关信息
printf("\n请输入修改类型(1.姓名 2.性别 3.年龄 4.电话号码 5.地址):\n");
int input;
scanf("%d", &input);//修改类型
if (input != 1 && input != 2 && input != 3 && input != 4 && input != 5) {
printf("\n\n输入错误\n");
wait_enter();
return;
}//输入错误
(enum modify_type)input;
if (input == age_m) {
printf("请输入修改的值:");
scanf("%d", &(main_con->data[ret].age));//age用scanf函数直接修改
}
else {
printf("请输入修改内容:");
char src[MAX_ADDR];
scanf("%s", src);
modify_m(main_con, input, src, ret);//string类型变量调用修改算法
}
system("cls");
printf("\n修改成功!\n\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
main_con->data[ret].name,
main_con->data[ret].sex,
main_con->data[ret].age,
main_con->data[ret].tele_num,
main_con->data[ret].addr);
//打印修改结果
wait_enter();
}
排序
//静态函数,规定不同方式排序的比较标准
//返回值<0为顺序,反之倒序
static int sort_by_name(const void* p1, const void* p2) {
return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);//strcmp比较字符串大小
}
static int sort_by_age(const void* p1, const void* p2) {
return ((PeoInfo*)p1)->age - ((PeoInfo*)p2)->age;
}
static int sort_by_tele(const void* p1, const void* p2) {
return strcmp(((PeoInfo*)p1)->tele_num, ((PeoInfo*)p2)->tele_num);
}
static int sort_by_addr(const void* p1, const void* p2) {
return strcmp(((PeoInfo*)p1)->addr, ((PeoInfo*)p2)->addr);
}
void sort(Contact* main_con) {
system("cls");
if (main_con->size == 0) {
printf(" _______________________________________\n\n");
printf(" 警告\n\n\t通讯录内容空白,无法修改联系人信息!\n\n");
printf(" _______________________________________\n");
wait_enter();
return;
}
//空白情况
printf("\n请输入排序标准(1.姓名 2.年龄 3.电话号码 4.地址):\n");
int input;
scanf("%d", &input);
if (input != 1 && input != 2 && input != 3 && input != 4) {
printf("\n\n输入错误\n");
wait_enter();
return;
}
//用户输入
(enum sort_type)input;
int (*sort_func)(const void* p1, const void* p2) = NULL;//比较函数的指针变量
if (input == name_s)
sort_func = sort_by_name;
else if (input == age_s)
sort_func = sort_by_age;
else if (input == tele_num_s)
sort_func = sort_by_tele;
else if (input == addr_s)
sort_func = sort_by_addr;
//根据用户输入,sort_func储存不同函数的指针
qsort((void*)main_con->data, main_con->size, sizeof(main_con->data[0]), sort_func);
//qsort函数(stdilib.h)————快速排序
//1.参数1(void*)为排序数组首元素地址
//2.参数2(size_t)为参与排序数组元素的个数
//3.参数3(size_t)为每个数组元素的字节大小
//4.参数4( int (*)(const void*, const void*) )实现比较算法的函数的指针
system("cls");
printf("排序成功!\n\n");
print_m((const Contact*)main_con);//打印排序结果
wait_enter();
}
保存
void SaveContact(Contact* main_con) {
FILE* pfile_data = fopen("condata.dat", "w");//打开(创建)data文件
FILE* pfile_info = fopen("coninfo.dat", "w");//打开(创建)info文件
if (pfile_data == NULL) {
perror("File Open");
return;
}
if (pfile_info == NULL) {
perror("File Open");
return;
}//错误情况
for (size_t i = 0; i < main_con->size; i++)
fwrite(main_con->data + i, sizeof(PeoInfo), 1, pfile_data);
//保存data数据于data文件
fprintf(pfile_info, "%zd %zd", main_con->size, main_con->capacity);
//保存size和capacity数据于info文件
fclose(pfile_data);
pfile_data = NULL;
fclose(pfile_info);
pfile_info = NULL;
//关闭文件
printf("\n\n通讯录保存成功!程序已退出\n");
wait_enter();
}
退出
void exit_m(Contact* main_con) {
free(main_con->data);//释放动态内存空间
main_con->data = NULL;//防止野指针出现,data赋为空指针
}
个人感悟
本人为C语言新手,在B站自学过程中了解了这个项目,于是想自己尝试实现。该程序至少50%以上的设计思路都是自己独立思考并实现的,所有代码都由自己亲手敲出来。
该程序采取了分模块的方式,由一个头文件和两个源文件组成;且在很多细节上有所处理,比如size_t类型的使用、enum枚举的应用、结构体的运用、const、static等关键字的使用等等;同时程序还采用了堆区动态内存分配的方式,使程序的空间使用更为灵活;以及使用了文件操作,可本地保存用户数据,使程序具有更强的实用性。
该程序涉及较多的指针内容,以及部分文件操作的内容,还使用了较多的库函数,需要读者有较强的C语言基础和一定的综合能力。
代码必然在很多方面存在不足,望谅解;文章内容有任何错误,还望指正。感兴趣的读者也可以自行尝试优化。
Github上也有相应的源码和应用程序:Github源码
感谢你的阅读!