功能展示
通讯录用到的知识点
常量,变量的使用
全局变量
分支语句
函数
宏
循环语句
scanf和printf
数据
结构体
文件
指针*
经典的问题(难点)
数组元素的删除(涉及数据结构)
功能分析及实现步骤
//
// main.c
// End_project
// 通讯录
// Created by 自超 陈 on 15/8/31.
// Copyright (c) 2015年 自超 陈. All rights reserved.
//
#include <stdio.h>
#include <string.h>
//宏定义*******************************************************************
#define N 100 //通讯录容量
#define NAMELEN 22 //姓名长度
#define NUMLEN 12 //号码长度
//*********定义部分********************************************************
//定义联系人的结构体
typedef struct{
//联系人
char name[NAMELEN];
//号码
char telNum[NUMLEN];
}Person;
//存储所有联系人,联系人数组
Person contacts[N];//能够存储100个联系人
//定义联系人个数
int totalContactCount = 0;
//接收用户输入的编号
int fno;
//定义数据文件保存的位置
char *filePath = "telbook.data";
//***********函数声明部分***************************************************
int valitataInput(int num, int min, int max);//合法输入
void doAdd();//添加
void doDelete();//删除
void doUpdata();//修改
void doList();//显示联系人
void doSearchByName();//搜索
void init();//初始化
void writeFile();//写数据到文件
//主函数*******************************************************************
int main(int argc, const char * argv[]) {
/*
1、引入头文件
2、进行必要的宏定义
3、定义文件名称变量、联系人数组、联系人结构体
4、定义函数,并进行声明
5、编写循环控制程序
6、现实操作界面
7、根据编号执行不同的函数
*/
init();
printf("通讯录初始化完成!\n");
while (1) {
printf("\n");
//软件的界面显示出来,死循环控制不停地输入
printf("**************************\n");
printf("****** 欢迎使用通讯录 ******\n");
printf("****** 1、添加联系人 ******\n");
printf("****** 2、删除联系人 ******\n");
printf("****** 3、修改联系人 ******\n");
printf("****** 4、查看所有联系人 ****\n");
printf("****** 5、搜素联系人 ******\n");
printf("****** 6、退出系统 ******\n");
printf("**************************\n");
//提示用户选择一个序号
printf("请选择1~6之间的功能编号:\n");
scanf("%d", &fno);
//判断编号是否合法,最好写个函数
valitataInput(fno,1,6);
//做不同的事情,定义不同的函数
switch (fno) {
case 1:
//执行添加
doAdd();
break;
case 2:
//执行删除
doDelete();
break;
case 3:
//执行修改
doUpdata();
break;
case 4:
//执行显示所有联系人
doList();
break;
case 5:
//执行搜索联系人
doSearchByName();
break;
case 6:
printf("系统正在退出...\n");
printf("系统已经退出!");
return 0;
break;
default:
break;
}
}
return 0;
}
//判断编号合法函数**********************************************************
//min-1,max-6
int valitataInput(int num, int min, int max) {
if (num < min || num > max) {
// main.c
// End_project
// 通讯录
// Created by 自超 陈 on 15/8/31.
// Copyright (c) 2015年 自超 陈. All rights reserved.
//
#include <stdio.h>
#include <string.h>
//宏定义*******************************************************************
#define N 100 //通讯录容量
#define NAMELEN 22 //姓名长度
#define NUMLEN 12 //号码长度
//*********定义部分********************************************************
//定义联系人的结构体
typedef struct{
//联系人
char name[NAMELEN];
//号码
char telNum[NUMLEN];
}Person;
//存储所有联系人,联系人数组
Person contacts[N];//能够存储100个联系人
//定义联系人个数
int totalContactCount = 0;
//接收用户输入的编号
int fno;
//定义数据文件保存的位置
char *filePath = "telbook.data";
//***********函数声明部分***************************************************
int valitataInput(int num, int min, int max);//合法输入
void doAdd();//添加
void doDelete();//删除
void doUpdata();//修改
void doList();//显示联系人
void doSearchByName();//搜索
void init();//初始化
void writeFile();//写数据到文件
//主函数*******************************************************************
int main(int argc, const char * argv[]) {
/*
1、引入头文件
2、进行必要的宏定义
3、定义文件名称变量、联系人数组、联系人结构体
4、定义函数,并进行声明
5、编写循环控制程序
6、现实操作界面
7、根据编号执行不同的函数
*/
init();
printf("通讯录初始化完成!\n");
while (1) {
printf("\n");
//软件的界面显示出来,死循环控制不停地输入
printf("**************************\n");
printf("****** 欢迎使用通讯录 ******\n");
printf("****** 1、添加联系人 ******\n");
printf("****** 2、删除联系人 ******\n");
printf("****** 3、修改联系人 ******\n");
printf("****** 4、查看所有联系人 ****\n");
printf("****** 5、搜素联系人 ******\n");
printf("****** 6、退出系统 ******\n");
printf("**************************\n");
//提示用户选择一个序号
printf("请选择1~6之间的功能编号:\n");
scanf("%d", &fno);
//判断编号是否合法,最好写个函数
valitataInput(fno,1,6);
//做不同的事情,定义不同的函数
switch (fno) {
case 1:
//执行添加
doAdd();
break;
case 2:
//执行删除
doDelete();
break;
case 3:
//执行修改
doUpdata();
break;
case 4:
//执行显示所有联系人
doList();
break;
case 5:
//执行搜索联系人
doSearchByName();
break;
case 6:
printf("系统正在退出...\n");
printf("系统已经退出!");
return 0;
break;
default:
break;
}
}
return 0;
}
//判断编号合法函数**********************************************************
//min-1,max-6
int valitataInput(int num, int min, int max) {
if (num < min || num > max) {
printf("非法输入!");
return
1; //返回值1,使while继续执行
}
else
{
return 0;
}
}
//添加联系人函数************************************************************
/*
1、提示用户输入联系人姓名
2、接收联系人
3、提示用户输入电话号码
4、接收电话号码
5、确认添加
6、联系人个数+1
7、把联系人信息写入文件中
*/
void doAdd() {
printf("您选择的是添加联系人,请按提示操作:\n");
// 1、提示用户输入联系人姓名
printf("请输入联系人姓名:(*联系人姓名之间不能有空格)\n");
// 2、接收联系人
scanf("%s", contacts[totalContactCount].name);
// 3、提示用户输入电话号码
printf("请输入联系人号码:(*联系人号码之间不能有空格)\n");
// 4、接收电话号码
scanf("%s", contacts[totalContactCount].telNum);
// 5、确认添加
int flag;
printf("您确认添加吗?1.确认 0.取消\n");
scanf("%d", &flag);
if (flag) {
// 6、联系人个数+1
totalContactCount ++;
// 7、把联系人信息写入文件中
writeFile();
}
}
//删除联系人函数************************************************************
/*
1、提示输入删除的联系人编号
2、判断编号是否合法,编号不能大于联系人个数
3、提示用户再次确认删除
4、开始数组元素
1)删除的元素正好是数组的最后一个元素
只需让联系人数量-1
2)如果删除的元素不是数组的最后一个元素
需移动元素
联系人数量-1
5、同步到文件中
*/
void doDelete() {
printf("您选择的是删除联系人,请按提示操作:\n");
doList();
// 1、提示输入删除的联系人编号
int no;
printf("请输入要删除的联系人编号:\n");
scanf("%d", &no);
// 2、判断编号是否合法,编号不能大于联系人个数
if (valitataInput(no, 1, totalContactCount)) {
return ;
}
// 3、提示用户再次确认删除
int flag;
printf("删除联系人后,数据无法恢复,您确认要删除吗? 1.确认 0.取消\n");
scanf("%d", &flag);
if (flag) {
// 4、开始删除数组元素
// 1)删除的元素正好是数组的最后一个元素
// 只需让联系人数量-1
if (no == totalContactCount) {
totalContactCount --;
} else {
// 2)如果删除的元素不是数组的最后一个元素
// 需移动元素
// 联系人数量-1
for (int i = no; i < totalContactCount; i++) {
//元素的移动和覆盖
contacts[no - 1] = contacts[no];
}
}
// 5、同步到文件中
writeFile();
}
}
//修改联系人函数************************************************************
/*
1、提示用户输入修改的信息编号
2、验证编号是否合法
3、输入新的用户名和新的电话号码
4、让用户确认
5、更新数组信息
*/
void doUpdata() {
printf("您选择的是修改联系人,请按提示操作:\n");
doList();
// 1、提示输入修改的联系人编号
int no;
printf("请输入要修改的联系人编号:\n");
scanf("%d", &no);
// 2、判断编号是否合法,编号不能大于联系人个数
if (valitataInput(no, 1, totalContactCount)) {
return ;
}
// 3、输入新的用户名和新的电话号码
char newName[NAMELEN];
char newTel[NAMELEN];
printf("请输入联系人新的姓名:(*注意联系人姓名之间不能有空格)\n");
scanf("%s", newName);
printf("请输入联系人心的电话:(*注意联系人电话之间不能有空格)\n");
scanf("%s", newTel);
// 4、让用户确认
int flag;
printf("确认后,信息将永久修改,您确认要修改吗? 1.确认 0.取消\n");
scanf("%d", &flag);
if (flag) {
// 5、更新数组信息
strcpy(contacts[no - 1].name, newName);
strcpy(contacts[no - 1].telNum, newTel);
// 6、写入到文件中
writeFile();
}
}
//显示联系人函数************************************************************
/*
如果文件存在则读取文件中的所有数据,遍历
1、判断
totalContactCount == 0 表示没有联系人
2、如果不等于0
开始遍历,并且输出联系人的信息
*/
void doList() {
printf("显示所有联系人,请按提示操作:\n");
if (totalContactCount == 0) {
printf("您的通讯录还没有小伙伴~请添加小伙伴!\n");
} else {
//输出格式
printf("编号\t 姓名\t 电话\t\n");
//遍历联系人数组
for (int i = 0; i < totalContactCount; i++) {
printf("%d\t %s\t %s\t \n", i+1, contacts[i].name, contacts[i].telNum);
}
}
}
//搜索联系人函数************************************************************
/*
根据联系人的姓名查找联系人
1、提示用户输入要查找的联系人姓名
2、遍历数组,查找此人
1)输入的姓名和contacts[i].name比较
3、查找到了,显示电话号码
4、查找不到,提示查无此人
*/
void doSearchByName() {
printf("您选择的是搜索联系人,请按提示操作:\n");
//1、提示用户输入要查找的联系人姓名
char searchName[NAMELEN];
printf("请输入要查找的联系人姓名:\n");
scanf("%s", searchName);
//遍历数组,查找此人
int i;
for (i = 0; i < totalContactCount; i++) {
//比较输入的姓名和contacts[i].name是否相等 返回值==0
if (strcmp(searchName, contacts[i].name) == 0) {
//打印此联系人对应的电话号
printf("您搜索的联系人 %s 电话是:%s\n", searchName, contacts[i].telNum);
break;//查找到了,循环结束
}
}
//查找不到,提示查无此人
if (i == totalContactCount) {
printf("查无此人!请看看是否输错!\n");
}
}
//通讯录初始化函数**********************************************************
/*
1、尝试性读取数据文件
2、如果读取成功,说明文件存在
如果存在,要读取联系人数据,保存到联系人数组中 contacts
3、如果读取失败,说明我们是第一次使用通讯录
如果第一次使用
1)创建联系人数据文件
2)把当前联系人的个数写入文件中 totalContactCount = 0
*/
void init() {
//定义文件指针,并打开
FILE *fp = fopen(filePath, "r");
//判断
if (fp != NULL) {
//第一步:读取联系人个数
fread(&totalContactCount, sizeof(totalContactCount), 1, fp);
//读取每一个联系人
for (int i = 0; i < totalContactCount; i++) {
//读取每个联系人保存到联系人数组
fread(&contacts, sizeof(Person), 1, fp);
}
} else {
//创建文件
fp = fopen(filePath, "wb");
//写入联系人个数
fwrite(&totalContactCount, sizeof(totalContactCount), 1, fp);
printf("通讯录文件创建成功~\n");
}
fclose(fp);
}
//写数据到文件**************************************************************
/*
1、以wb的方式打开
2、先写联系人个数
3、写每个联系人数据
*/
void writeFile() {
// 1、以wb的方式打开
FILE *fp = fopen(filePath, "wb");
if (fp != NULL) {
// 2、先写联系人个数
fwrite(&totalContactCount, sizeof(totalContactCount), 1, fp);
// 3、写每个联系人数据
for (int i = 0; i < totalContactCount; i++) {
//每次都写入一个数据的元素
fwrite(&contacts[i], sizeof(Person), 1, fp);
}
printf("写文件数据更新成功!\n");
}
//关闭文件指针
fclose(fp);
return 0;
}
}
//添加联系人函数************************************************************
/*
1、提示用户输入联系人姓名
2、接收联系人
3、提示用户输入电话号码
4、接收电话号码
5、确认添加
6、联系人个数+1
7、把联系人信息写入文件中
*/
void doAdd() {
printf("您选择的是添加联系人,请按提示操作:\n");
// 1、提示用户输入联系人姓名
printf("请输入联系人姓名:(*联系人姓名之间不能有空格)\n");
// 2、接收联系人
scanf("%s", contacts[totalContactCount].name);
// 3、提示用户输入电话号码
printf("请输入联系人号码:(*联系人号码之间不能有空格)\n");
// 4、接收电话号码
scanf("%s", contacts[totalContactCount].telNum);
// 5、确认添加
int flag;
printf("您确认添加吗?1.确认 0.取消\n");
scanf("%d", &flag);
if (flag) {
// 6、联系人个数+1
totalContactCount ++;
// 7、把联系人信息写入文件中
writeFile();
}
}
//删除联系人函数************************************************************
/*
1、提示输入删除的联系人编号
2、判断编号是否合法,编号不能大于联系人个数
3、提示用户再次确认删除
4、开始数组元素
1)删除的元素正好是数组的最后一个元素
只需让联系人数量-1
2)如果删除的元素不是数组的最后一个元素
需移动元素
联系人数量-1
5、同步到文件中
*/
void doDelete() {
printf("您选择的是删除联系人,请按提示操作:\n");
doList();
// 1、提示输入删除的联系人编号
int no;
printf("请输入要删除的联系人编号:\n");
scanf("%d", &no);
// 2、判断编号是否合法,编号不能大于联系人个数
if (valitataInput(no, 1, totalContactCount)) {
return ;
}
// 3、提示用户再次确认删除
int flag;
printf("删除联系人后,数据无法恢复,您确认要删除吗? 1.确认 0.取消\n");
scanf("%d", &flag);
if (flag) {
// 4、开始删除数组元素
// 1)删除的元素正好是数组的最后一个元素
// 只需让联系人数量-1
if (no == totalContactCount) {
totalContactCount --;
} else {
// 2)如果删除的元素不是数组的最后一个元素
// 需移动元素
// 联系人数量-1
for (int i = no; i < totalContactCount; i++) {
//元素的移动和覆盖
contacts[no - 1] = contacts[no];
}
}
// 5、同步到文件中
writeFile();
}
}
//修改联系人函数************************************************************
/*
1、提示用户输入修改的信息编号
2、验证编号是否合法
3、输入新的用户名和新的电话号码
4、让用户确认
5、更新数组信息
*/
void doUpdata() {
printf("您选择的是修改联系人,请按提示操作:\n");
doList();
// 1、提示输入修改的联系人编号
int no;
printf("请输入要修改的联系人编号:\n");
scanf("%d", &no);
// 2、判断编号是否合法,编号不能大于联系人个数
if (valitataInput(no, 1, totalContactCount)) {
return ;
}
// 3、输入新的用户名和新的电话号码
char newName[NAMELEN];
char newTel[NAMELEN];
printf("请输入联系人新的姓名:(*注意联系人姓名之间不能有空格)\n");
scanf("%s", newName);
printf("请输入联系人心的电话:(*注意联系人电话之间不能有空格)\n");
scanf("%s", newTel);
// 4、让用户确认
int flag;
printf("确认后,信息将永久修改,您确认要修改吗? 1.确认 0.取消\n");
scanf("%d", &flag);
if (flag) {
// 5、更新数组信息
strcpy(contacts[no - 1].name, newName);
strcpy(contacts[no - 1].telNum, newTel);
// 6、写入到文件中
writeFile();
}
}
//显示联系人函数************************************************************
/*
如果文件存在则读取文件中的所有数据,遍历
1、判断
totalContactCount == 0 表示没有联系人
2、如果不等于0
开始遍历,并且输出联系人的信息
*/
void doList() {
printf("显示所有联系人,请按提示操作:\n");
if (totalContactCount == 0) {
printf("您的通讯录还没有小伙伴~请添加小伙伴!\n");
} else {
//输出格式
printf("编号\t 姓名\t 电话\t\n");
//遍历联系人数组
for (int i = 0; i < totalContactCount; i++) {
printf("%d\t %s\t %s\t \n", i+1, contacts[i].name, contacts[i].telNum);
}
}
}
//搜索联系人函数************************************************************
/*
根据联系人的姓名查找联系人
1、提示用户输入要查找的联系人姓名
2、遍历数组,查找此人
1)输入的姓名和contacts[i].name比较
3、查找到了,显示电话号码
4、查找不到,提示查无此人
*/
void doSearchByName() {
printf("您选择的是搜索联系人,请按提示操作:\n");
//1、提示用户输入要查找的联系人姓名
char searchName[NAMELEN];
printf("请输入要查找的联系人姓名:\n");
scanf("%s", searchName);
//遍历数组,查找此人
int i;
for (i = 0; i < totalContactCount; i++) {
//比较输入的姓名和contacts[i].name是否相等 返回值==0
if (strcmp(searchName, contacts[i].name) == 0) {
//打印此联系人对应的电话号
printf("您搜索的联系人 %s 电话是:%s\n", searchName, contacts[i].telNum);
break;//查找到了,循环结束
}
}
//查找不到,提示查无此人
if (i == totalContactCount) {
printf("查无此人!请看看是否输错!\n");
}
}
//通讯录初始化函数**********************************************************
/*
1、尝试性读取数据文件
2、如果读取成功,说明文件存在
如果存在,要读取联系人数据,保存到联系人数组中 contacts
3、如果读取失败,说明我们是第一次使用通讯录
如果第一次使用
1)创建联系人数据文件
2)把当前联系人的个数写入文件中 totalContactCount = 0
*/
void init() {
//定义文件指针,并打开
FILE *fp = fopen(filePath, "r");
//判断
if (fp != NULL) {
//第一步:读取联系人个数
fread(&totalContactCount, sizeof(totalContactCount), 1, fp);
//读取每一个联系人
for (int i = 0; i < totalContactCount; i++) {
//读取每个联系人保存到联系人数组
fread(&contacts, sizeof(Person), 1, fp);
}
} else {
//创建文件
fp = fopen(filePath, "wb");
//写入联系人个数
fwrite(&totalContactCount, sizeof(totalContactCount), 1, fp);
printf("通讯录文件创建成功~\n");
}
fclose(fp);
}
//写数据到文件**************************************************************
/*
1、以wb的方式打开
2、先写联系人个数
3、写每个联系人数据
*/
void writeFile() {
// 1、以wb的方式打开
FILE *fp = fopen(filePath, "wb");
if (fp != NULL) {
// 2、先写联系人个数
fwrite(&totalContactCount, sizeof(totalContactCount), 1, fp);
// 3、写每个联系人数据
for (int i = 0; i < totalContactCount; i++) {
//每次都写入一个数据的元素
fwrite(&contacts[i], sizeof(Person), 1, fp);
}
printf("写文件数据更新成功!\n");
}
//关闭文件指针
fclose(fp);
}