黑白的通讯录
----------------------
--1-- 需求分析1.1 需求1.2 原型展示1.3 功能分析--2-- 代码实现2.1 外部声明、变量、宏2.2 模块实现
----------------------
【写在开头:】
『在不用UI界面操作的时候,用一个命令行版的通讯录也是很有个性的...』
--1-- 需求分析
1.1 需求
实现简单计算器的计算功能,用命令行的方式选择具体的操作
1.2 原型展示
欢迎界面:
1)添加联系人:
2)删除联系人:
3)修改联系人:
4)查看联系人:
5)搜索联系人:
数据库文件:
1.3 功能分析
按照原型编写相应的流程功能。
/**
分析:
0、初始化
初始化方法,用于初始化数据
思路:
1)尝试性的读取文件
2)如果成功了,说明文件存在,则读取文件内容
3)不成功,说明文件不存在
1)创建文件
2)写入联系人数量
1、添加联系人
思路:
1)提示用户输入姓名和电话号码
2)接收用户输入的内容
3)保存到联系人数组
4)写入到文件中
2、删除联系人
思路:
1)让用户输入要删除的数据的编号
2)判断编号是否合法
3)让用户再次确认删除
4)开始删除数组元素
5)删除文件的内容
3、修改联系人
更新联系人信息
思路:
1)提示用户输入要删除联系人的编号
2)判断编号是否合法
3)让用户再次确认修改
4)开始修改用户信息
5)更新到文件中
4、查看联系人
查看所有联系人
思路:
1)先判断联系人是否为空
2)如果不为空,则遍历数组,列出所有的联系人
5、搜索联系人
根据输入的姓名查找联系人
思路:
1)提示用户要输入查找的人的姓名
2)遍历联系人数组,查找是否有这个人
3)如果找到,就把电话号码显示出来
4)没有找到,则显示没有该联系人信息
6、退出系统
*/
用到的知识点:
常量、变量的使用;全局变量;数组;分支语句;函数;宏;循环语句;scanf和printf;数据;结构体;文件操作;指针*
难点:
数组元素的删除(可变数组,使用链表会更优)
--2-- 代码实现
2.1 外部声明、变量、宏
需定义的宏
//******宏定义
#define N 100 //联系人数组的长度
#define NAMELEN 13 //姓名长度
#define NUMLEN 12 //手机号长度
//**********
全局变量
//******定义变量
int inputNum; //接收键盘输入
int telCount; //联系人个数
int flag; //接收确认标记
char *telBook = "telNumBook.data"; //数据库文件//****
函数声明
//*****函数声明
voiddoAdd();voiddoDel();voiddoEdit();voiddoList();voiddoSearch();voidstartView();intwriteFile();voidinit();int validateInput(int num, int min, intmax);//********
联系人结构体
//******联系人结构体
typedef struct{chartelName[NAMELEN];chartelNum[NUMLEN];
}Person;
Person contacts[N];//联系人数组//*********
2.2 模块实现
1)添加联系人模块
1 /**2 * 添加联系人3 */
4 voiddoAdd(){5 printf("您选择了添加联系人操作\n");6 printf("请输入要添加的联系人的姓名:(*注意联系人姓名中间不能有空格)\n");7 scanf("%s", contacts[telCount].telName); //存入数组
8
9 printf("请输入要添加的联系人的电话号码:(*注意联系人电话号码中间不能有空格)\n");10 scanf("%s", contacts[telCount].telNum);11
12 //提示确认
13 printf("是否确认添加\"%s\"联系人? 1.确认 0.取消\n", contacts[telCount].telName);14 scanf("%d", &flag);15 if(flag) {16 //联系人个数+1
17 telCount++;18 //写入文件中
19 writeFile();20
21 printf("\n");22 }23
24 }
2)删除联系人模块
1 /**2 * 删除联系人3 */
4 voiddoDel(){5 printf("您当前选择的是删除联系人操作\n");6 doList();7 printf("请输入要删除的联系人编号:\n");8
9 scanf("%d", &inputNum);10 if (validateInput(inputNum, 1, telCount)){11 //非法输入则返回
12 return;13 } else{14 printf("数据删除后将不可恢复,您是否确认要删除\"%s\"的信息? 1.确认 0.取消\n",15 contacts[inputNum - 1].telName);16 scanf("%d", &flag);17 if(flag) {18 if (inputNum == telCount){ //要删除的是最后一个元素
19 telCount--;20 } else{ //不是最后一个元素,则要移动数组元素的位置
21 for (int i = inputNum; i < telCount; i++){22 contacts[inputNum - 1] =contacts[inputNum];23 telCount--; //联系人-1
24 }25 }26 //写入文件
27 writeFile();28 }29 }30
31 }
3)修改联系人模块
1 /**2 * 编辑联系人3 */
4 voiddoEdit(){5 printf("您选择了修改联系人操作\n");6
7 doList();8 printf("请输入要修改的联系人的编号:\n");9 scanf("%d", &inputNum);10
11 //定义临时数组保存新联系人的姓名和电话,不直接修改数组
12 chartempName[NAMELEN];13 chartempTelNum[NUMLEN];14 if (validateInput(inputNum, 1, telCount)) {15 return;16 } else{17 printf("您是否确认要修改联系人\"%s\"的信息? 1.确认 0.取消",18 contacts[inputNum - 1].telName);19 scanf("%d", &flag);20
21 if(flag) {22 printf("请输入新的联系人姓名:(*注意姓名中间不能有空格)\n");23 scanf("%s", tempName);24 printf("请输入新的联系人电话号码:(*注意电话号码中间不能有空格)\n");25 scanf("%s", tempTelNum);26
27 //更新数组信息
28 strcpy(contacts[inputNum - 1].telName, tempName);29 strcpy(contacts[inputNum - 1].telNum, tempTelNum);30
31 //保存入文件
32 writeFile();33
34 }35 }36
37 }
4)查看联系人模块
1 /**2 * 显示联系人3 */
4 voiddoList(){5 if (telCount == 0) {6 printf("您的当前的联系人为空,请先添加小伙伴哟~~\n");7 return;8 }9 printf("当前联系人列表:\n");10 for (int i = 0; i < telCount; i++) {11 printf("编号%d 姓名: %s, 电话号码: %s\n", i + 1, contacts[i].telName, contacts[i].telNum);12 }13 }
5)搜索联系人模块
1 /**2 * 搜索联系人3 */
4 voiddoSearch(){5 printf("您当前选择的是搜索联系人操作\n");6
7 doList();8 char tempName[NAMELEN]; //临时数组
9 printf("请输入要查找的联系人姓名:\n");10 scanf("%s",tempName);11
12 inti;13 for (i = 0; i < telCount; i++) {14 if (strcmp(tempName, contacts[i].telName) == 0){15 printf("您搜索的联系人\"%s\"的电话号码是%s\n", contacts[i].telName, contacts[i].telNum);16 break; //找到则循环终止
17 }18 }19 //循环一遍还没有找到
20 if (i ==telCount){21 printf("抱歉!没有找到\"%s\"的记录信息\n", tempName);22 }23 }
6)自定义校验非法数值及写入文件函数
/**
* 将数组和联系人个数写入文件
*
* @return 1 异常 0 正常*/
intwriteFile(){//打开文件
FILE *fp = fopen(telBook, "wb"); //以二进制写入
if (fp !=NULL) {//将联系人个数写入文件
fwrite(&telCount, sizeof(telCount), 1, fp);//数组写入文件
for (int i = 0; i < telCount; i++) {
fwrite(&contacts[i], sizeof(Person), 1, fp);
}
printf("数据更新成功!\n");
}else{
printf("数据写入失败!\n");return 1;
}//关闭指针
fclose(fp);return 0;
}/**
* 验证输入是否合法
*
* @param num 待验证的整数
* @param min 最小值
* @param max 最大值
*
* @return 0.合法 1.非法*/
int validateInput(int num, int min, intmax){if (num >= min && num <=max) {return 0;
}else{
printf("非法输入!\n");return 1;
}
}
分析:
此处为什么一定要将联系人的个数telCount持久化?
因为如果联系人个数如果不持久化,那么每次程序重启后都读取不到联系人了,因为这里使用的是变量数组的形式。所以注意此处一定要持久化个数。
7)自定义初始化函数
/**
初始化
从文件读取联系人和数组*/
voidinit(){
FILE*fp = fopen(telBook, "r"); //打开文件
if (fp !=NULL) {//从文件中读取联系人
fread(&telCount, sizeof(telCount), 1, fp);//读取数组
for (int i = 0; i < telCount; i++) {
fread(&contacts[i], sizeof(Person), 1, fp);
}
}else{ //如果没有文件,则创建
FILE *fp = fopen(telBook, "wr");
fwrite(telBook,sizeof(Person), 1, fp);
printf("通讯录创建成功~\n");
}//关闭指针
fclose(fp);
printf("通讯录初始化成功!~~\n");
}
分析:
为什么要有一个初始化的方法?
因为每次系统启动时都必须从文件中读取联系人数组和联系人个数,所以,要有一个初始化方法。
8)主界面和主函数
/**
* 主界面*/
voidstartView(){
printf("********************************\n");
printf("******** 欢迎使用C通讯录 ******\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");
}/**
* 主函数
*
* @param argc
* @param argv
*
* @return 0 程序正常退出*/
int main(int argc, const char *argv[]) {
init();while (1) {
startView();
scanf("%d", &inputNum);switch(inputNum) {case 1:
doAdd();break;case 2:
doDel();break;case 3:
doEdit();break;case 4:
doList();break;case 5:
doSearch();break;case 6:
printf("系统正在退出...\n");
printf("系统安全退出,感谢您再次使用\n");return 0;default:break;
}
}return 0;
}
【写在结尾:】
『有那么一个时候,真的好想说一声,对不起,谢谢』
原文:http://www.cnblogs.com/wang-biao/p/5662081.html