C语言-《通讯录》
----------------------
--1-- 需求分析1.1 需求1.2 原型展示1.3功能分析--2-- 代码实现2.1外部声明、变量、宏2.2 模块实现----------------------
--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"; //数据库文件 //****
函数声明
//*****函数声明 void doadd(); void dodel(); void doedit(); void dolist(); void dosearch(); void startview(); int writefile(); void init(); int validateinput(int num, int min, int max); //********
联系人结构体
//******联系人结构体 typedef struct{ char telname[namelen]; char telnum[numlen]; }person; person contacts[n]; //联系人数组 //*********2.2 模块实现
1)添加联系人模块
1 /** 2 * 添加联系人 3 */ 4 void doadd(){ 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 void dodel(){ 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 void doedit(){ 5 printf("您选择了修改联系人操作\n"); 6 7 dolist(); 8 printf("请输入要修改的联系人的编号:\n"); 9 scanf("%d", &inputnum); 10 11 //定义临时数组保存新联系人的姓名和电话,不直接修改数组 12 char tempname[namelen]; 13 char temptelnum[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 void dolist(){ 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 void dosearch(){ 5 printf("您当前选择的是搜索联系人操作\n"); 6 7 dolist(); 8 char tempname[namelen]; //临时数组 9 printf("请输入要查找的联系人姓名:\n"); 10 scanf("%s",tempname); 11 12 int i; 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 正常 */ int writefile(){ //打开文件 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, int max){ if (num >= min && num <= max) { return 0; } else{ printf("非法输入!\n"); return 1; } }
分析:
此处为什么一定要将联系人的个数telcount持久化?
因为如果联系人个数如果不持久化,那么每次程序重启后都读取不到联系人了,因为这里使用的是变量数组的形式。所以注意此处一定要持久化个数。
7)自定义初始化函数
/** 初始化 从文件读取联系人和数组 */ void init(){ 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)主界面和主函数
/** * 主界面 */ void startview(){ 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; }
推荐阅读
-
详解C#的排列组合
-
判断内容里有没有汉语言,然后要返回中文字符
-
试读《Objective-C程序设计(第6版)》 ———一本充满“强强”味道的编程书
-
C++实践:正则表达式解析声卡参数
-
栈的实现(C语言实现)
-
More Effective C++----(12)理解"抛出一个异常"与"传递一个参数"或"调用一个虚函数"间的差异
-
《写给大忙人看的Swift》 ——swift和object-c的关系会步C与C++的后尘吗?
-
PHP语言中global跟$GLOBALS[]的分析【转】
-
I2C_SCL 时钟抖动问题之“if条件判断分支” 软件优化
-
ShopNC B2B2C多用户商城网站系统源码,shopncb2b2c