几点说明
- 前置知识:结构体、指针、枚举
- 本文只有代码,但代码中注释足够详细
- 本程序以项目形式呈现,如何创建项目在不同IDE中有所不同,请自行解决
main.c文件(主程序)
//引用game.h头文件(在最后)
#include "game.h"
int main(){
menu();
//创建通讯录,并赋空值
contact con = {0}; //通讯录的初始化
contactInit(&con);
while(1){
int op = chooseOption();
switch(op){
case EXIT: //退出
Exit(&con);
return 0;
case ADD: //添加联系人
Add(&con);
break;
case DELE: //删除联系人
Delete(&con);
break;
case SEARCH: //查找联系人
Search(&con);
break;
case MODIFY: //修改联系人信息
Modify(&con);
break;
case SORT: //将联系人按姓名顺序排序
Sort(&con);
break;
case SHOW: //展示全部联系人
Show(&con);
break;
}
}
return 0;
}
func.c文件(函数实现)
#include "game.h"
//设置控制台光标位置
//看不懂可以将Pos相关内容(本函数和menu()函数中部分)全部删除,无影响
void Pos(int x, int y){
COORD pos;
pos.X = x;
pos.Y = y;
HANDLE HandleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(HandleOutput, pos);
}
//菜单界面
void menu(){
Pos(40, 4);
printf("*******************************\n");
Pos(40, 5);
printf("********** 1 EXIT **********\n");
Pos(40, 6);
printf("********** 2 ADD **********\n");
Pos(40, 7);
printf("********** 3 Delete **********\n");
Pos(40, 8);
printf("********** 4 Search **********\n");
Pos(40, 9);
printf("********** 5 Modify **********\n");
Pos(40, 10);
printf("********** 6 Sort **********\n");
Pos(40, 11);
printf("********** 7 Show **********\n");
Pos(40, 12);
printf("*******************************\n");
}
//选择操作
int chooseOption(){
printf("请输入您要进行的操作:");
int x;
scanf("%d", &x);
return x;
}
//通讯录初始化
void contactInit(contact* con){
//以二进制只读方式打开文件
FILE* pf = fopen("contact.txt", "rb");
if(!pf){
//如果打开错误,则返回报错语句
printf("%s\n", strerror(errno));
return;
}
else{
//一定要注意内存的分配!很容易忽略
con->data = (conInfo*)malloc(MAX_NUMBER * sizeof(conInfo));
//创建临时通讯录成员结构体,用以读取文件中的信息
conInfo temp = {0};
while(fread(&temp, sizeof(conInfo), 1, pf)){
//C语言支持将一个结构体赋值给另一个结构体(同类)
con->data[con->size ++] = temp;
}
//关闭文件
fclose(pf);
//将文件指针置为NULL(这里pf指向的地址已经没有意义,防止后续无意间使用pf指针)
pf = NULL;
}
}
void Exit(contact* con){
//以二进制写入模式打开文件
FILE* pf = fopen("contact.txt", "wb");
if(!pf){
//打印错误信息(::是约定俗成的分隔符,没有实际含义)
printf("Save error::%s\n", strerror(errno));
return;
}
int i;
for(i = 0; i < con->size; i ++ ){
//文件以"wb"方式打开,则fwrite()
fwrite(con->data + i, sizeof(conInfo), 1, pf);
}
fclose(pf);
pf = NULL;
}
void Add(contact* con){
if(con->size >= MAX_NUMBER) printf("通讯录已满");
printf("请输入姓名:");
scanf("%s", con->data[con->size].name);
printf("请输入年龄:");
scanf("%d", &con->data[con->size].age);
printf("请输入电话:");
scanf("%s", con->data[con->size].phone);
con->size ++;
printf("增加联系人成功\n");
}
void Delete(contact* con){
printf("请输入要删除的联系人的姓名:");
char deleteName[20];
scanf("%s", deleteName);
int i, flag = 0; //flag用来标记是否存在该联系人
for(i = 0; i < con->size; i ++ )
if(!strcmp(deleteName, con->data[i].name)){ //strcmp()函数比较姓名是否相同
flag = 1;
for(i; i < con->size - 1; i ++ )
con->data[i] = con->data[i + 1]; //将后续结构体成员前移,覆盖删除内容
con->size --;
printf("删除成功\n");
}
if(!flag) printf("该联系人不存在\n");
}
void Search(contact* con){
printf("请输入要查找的联系人的姓名:");
char findName[20];
scanf("%s", findName);
int i, flag = 0;
for(i = 0; i < con->size; i ++ )
if(!strcmp(findName, con->data[i].name)){
printf("查找成功\n");
printf("姓名:%s\n", con->data[i].name);
printf("年龄:%d\n", con->data[i].age);
printf("电话:%s\n", con->data[i].phone);
flag = 1;
}
if(!flag)
printf("该联系人不存在\n");
}
void Modify(contact* con){
printf("请输入要修改的联系人的姓名:");
char findName[20];
scanf("%s", findName);
int i;
for(i = 0; i < con->size; i ++ )
if(!strcmp(findName, con->data[i].name)){
printf("请输入姓名:");
scanf("%s", con->data[i].name);
printf("请输入年龄:");
scanf("%d", &con->data[i].age);
printf("请输入电话:");
scanf("%s", con->data[i].phone);
}
else
printf("该联系人不存在\n");
}
//const void* 为C语言规定的传参方式
int compare(const void* con1, const void* con2){
//进行指针的强制类型转换,注意(conInfo*)con->name的方式是错误的
//这样的话是先->后(conInfo*)
return strcmp(((conInfo*)con1)->name, ((conInfo*)con2)->name);
}
void Sort(contact* con){
//qsort的四个参数分别为:首地址、个数、每个的大小、比较函数
qsort(con->data, con->size, sizeof(con->data[0]), compare);
printf("排序完成!\n");
}
void Show(contact* con){
int i;
for(i = 0; i < con->size; i ++ )
printf("%s %d %s\n", con->data[i].name, con->data[i].age, con->data[i].phone);
}
game.h文件(头文件)
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#define MAX_NUMBER 1000 //最大成员数
#define MAX_NAME 20 //最长名字
#define MAX_PHONE 20 //最长电话号码
typedef struct conInfo{
char name[MAX_NAME];
int age;
char phone[MAX_PHONE];
}conInfo;
typedef struct contact{
conInfo* data;
int size;
}contact;
//枚举,用单词替换常数,增强程序可读性与可维护性
enum Option
{
EXIT = 1,
ADD,
DELE,
SEARCH,
MODIFY,
SORT,
SHOW
}input;
void Pos(int x, int y);
void menu();
int chooseOption();
void Exit(contact* con);
void contactInit(contact* con);
void Add(contact* con);
void Delete(contact* con);
void Search(contact* con);
void Modify(contact* con);
void Show(contact* con);