黑白的通讯录

--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 外部声明、变量、宏

需定义的宏

  1. //******宏定义
  2. #define N 100 //联系人数组的长度
  3. #define NAMELEN 13 //姓名长度
  4. #define NUMLEN 12 //手机号长度
  5. //**********

全局变量

  1. //******定义变量
  2. int inputNum; //接收键盘输入
  3. int telCount; //联系人个数
  4. int flag; //接收确认标记
  5. char *telBook = "telNumBook.data"; //数据库文件
  6. //****

函数声明

  1. //*****函数声明
  2. void doAdd();
  3. void doDel();
  4. void doEdit();
  5. void doList();
  6. void doSearch();
  7. void startView();
  8. int writeFile();
  9. void init();
  10. int validateInput(int num, int min, int max);
  11. //********

联系人结构体

  1. //******联系人结构体
  2. typedef struct{
  3. char telName[NAMELEN];
  4. char telNum[NUMLEN];
  5. }Person;
  6.  
  7. Person contacts[N]; //联系人数组
  8. //*********

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, , telCount)){
  11. //非法输入则返回
  12. return;
  13. } else{
  14. printf("数据删除后将不可恢复,您是否确认要删除\"%s\"的信息? 1.确认 0.取消\n",
  15. contacts[inputNum - ].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 - ] = 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, , telCount)) {
  15. return;
  16. } else{
  17. printf("您是否确认要修改联系人\"%s\"的信息? 1.确认 0.取消",
  18. contacts[inputNum - ].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 - ].telName, tempName);
  29. strcpy(contacts[inputNum - ].telNum, tempTelNum);
  30.  
  31. //保存入文件
  32. writeFile();
  33.  
  34. }
  35. }
  36.  
  37. }

4)查看联系人模块

  1. /**
  2. * 显示联系人
  3. */
  4. void doList(){
  5. if (telCount == ) {
  6. printf("您的当前的联系人为空,请先添加小伙伴哟~~\n");
  7. return;
  8. }
  9. printf("当前联系人列表:\n");
  10. for (int i = ; i < telCount; i++) {
  11. printf("编号%d 姓名: %s, 电话号码: %s\n", i + , 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 = ; i < telCount; i++) {
  14. if (strcmp(tempName, contacts[i].telName) == ){
  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)自定义校验非法数值及写入文件函数

  1. /**
  2. * 将数组和联系人个数写入文件
  3. *
  4. * @return 1 异常 0 正常
  5. */
  6. int writeFile(){
  7. //打开文件
  8. FILE *fp = fopen(telBook, "wb"); //以二进制写入
  9. if (fp != NULL) {
  10. //将联系人个数写入文件
  11. fwrite(&telCount, sizeof(telCount), , fp);
  12. //数组写入文件
  13. for (int i = ; i < telCount; i++) {
  14. fwrite(&contacts[i], sizeof(Person), , fp);
  15. }
  16. printf("数据更新成功!\n");
  17.  
  18. } else{
  19. printf("数据写入失败!\n");
  20. return ;
  21. }
  22.  
  23. //关闭指针
  24. fclose(fp);
  25. return ;
  26. }
  27.  
  28. /**
  29. * 验证输入是否合法
  30. *
  31. * @param num 待验证的整数
  32. * @param min 最小值
  33. * @param max 最大值
  34. *
  35. * @return 0.合法 1.非法
  36. */
  37. int validateInput(int num, int min, int max){
  38. if (num >= min && num <= max) {
  39. return ;
  40. } else{
  41. printf("非法输入!\n");
  42. return ;
  43. }
  44. }

分析:

此处为什么一定要将联系人的个数telCount持久化?

因为如果联系人个数如果不持久化,那么每次程序重启后都读取不到联系人了,因为这里使用的是数组变量。所以注意此处一定要将联系人个数存入文件。

7)自定义初始化函数

  1. /**
  2. 初始化
  3. 从文件读取联系人和数组
  4. */
  5. void init(){
  6.  
  7. FILE *fp = fopen(telBook, "r"); //打开文件
  8. if (fp != NULL) {
  9. //从文件中读取联系人
  10. fread(&telCount, sizeof(telCount), , fp);
  11. //读取数组
  12. for (int i = ; i < telCount; i++) {
  13. fread(&contacts[i], sizeof(Person), , fp);
  14. }
  15. } else{ //如果没有文件,则创建
  16. FILE *fp = fopen(telBook, "wr");
  17. fwrite(telBook, sizeof(Person), , fp);
  18. printf("通讯录创建成功~\n");
  19. }
  20.  
  21. //关闭指针
  22. fclose(fp);
  23. printf("通讯录初始化成功!~~\n");
  24.  
  25. }

分析:

为什么要有一个初始化的方法?

因为每次系统启动时都必须从文件中读取联系人数组和联系人个数。

8)主界面和主函数

  1. /**
  2. * 主界面
  3. */
  4. void startView(){
  5. printf("********************************\n");
  6. printf("******** 欢迎使用C通讯录 ******\n");
  7. printf("******** 1、添加联系人 ******\n");
  8. printf("******** 2、删除联系人 ******\n");
  9. printf("******** 3、修改联系人 ******\n");
  10. printf("******** 4、查看所有联系人 ******\n");
  11. printf("******** 5、搜索联系人 ******\n");
  12. printf("******** 6、退出系统 ******\n");
  13. printf("********************************\n");
  14. printf("请选择1-6之间您要进行的操作\n");
  15. }
  16.  
  17. /**
  18. * 主函数
  19. *
  20. * @param argc
  21. * @param argv
  22. *
  23. * @return 0 程序正常退出
  24. */
  25. int main(int argc, const char * argv[]) {
  26. init();
  27. while () {
  28. startView();
  29. scanf("%d", &inputNum);
  30. switch (inputNum) {
  31. case :
  32. doAdd();
  33. break;
  34. case :
  35. doDel();
  36. break;
  37. case :
  38. doEdit();
  39. break;
  40. case :
  41. doList();
  42. break;
  43. case :
  44. doSearch();
  45. break;
  46. case :
  47. printf("系统正在退出...\n");
  48. printf("系统安全退出,感谢您再次使用\n");
  49. return ;
  50. default:
  51. break;
  52. }
  53. }
  54. return ;
  55. }

【写在结尾:】

『有那么一个时候,真的好想说一声,对不起,谢谢』

C语言-《通讯录》的更多相关文章

  1. c语言:<tchar.h>

    头文件“<tchar.h>”作用就是为了进行ASCII码和UNICODE(wide-character)码的头文件(该头文件由微软提供): 这样我们就可以使用TCHAR.H头文件中的定义的 ...

  2. 如何使用微软提供的TCHAR.H头文件?

    转载:https://www.cnblogs.com/flyingspark/archive/2012/03/16/2399788.html 如何使用微软提供的TCHAR.H头文件? 如果你现在写的代 ...

  3. C语言math.h库函数中atan与atan2的区别

    源: C语言math.h库函数中atan与atan2的区别 C语言中的atan和atan2

  4. c语言string.h和memory.h某些函数重复问题

    在C语言中,为了使用memset()函数,你是选择#include <string.h>还是<memory.h>?两个都可以,如何选择? <string.h>,标准 ...

  5. C语言string.h中常用字符函数介绍

    原文:http://www.cnblogs.com/xuwenmin888/archive/2013/05/03/3057883.html strcpy 函数名: strcpy 功 能: 拷贝一个字符 ...

  6. C语言ctype.h字符函数和字符串

    ctype.h存的是与字符相关的函数: 这些函数虽然不能处理整个字符串,但是可以处理字符串中的字符: ToUpper()函数,利用toupper()函数处理字符串中的每个字符,转换成大写: Punct ...

  7. C语言函数--H

    函数名: harderr 功 能: 建立一个硬件错误处理程序 用 法: void harderr(int (*fptr)()); 程序例: /*This program will trap disk ...

  8. C语言conio.h部分解释

    #include <conio.h> int getch(void);// 从控制台得到下一个字符,以ASCII值返回,并不在屏幕显示该字符 int getche(void);// 从控制 ...

  9. C语言——stdio.h

        int fgetc(FILE * stream); get character from stream 返回流中的一个字符,并以int的类型返回,如果碰到文件的结尾,或者一个错误发生,函数返回 ...

  10. C语言string.h常用函数总结

    void *memcpy(void *dest, const void *src, size_t n); 从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中. ...

随机推荐

  1. MVC入门第一天

    一.异步的两种方法 用jQ的异步  返回content controllor:return Content(sum.ToString());//这里涉及到一个自动封装的问题 html页:<for ...

  2. jiajianhao

    #include<stdio.h> int map[4][4]={ 0,1,0,0, 0,0,0,0, 0,0,0,0, 0,1,0,0}; int flag=0; int minci=9 ...

  3. Mysql中字段类型不一致导致索引无效

    修改后 详细见楼下链接 http://ustb80.blog.51cto.com/6139482/1287847

  4. xcode8升级后问题总汇

    一.注释快捷键无法使用 command + / 快捷键无法使用,在终端执行以下命令,然后重启Xcode即可.   1 sudo /usr/libexec/xpccachectl 二.注释快捷键 Xco ...

  5. 如何给main传参数

    main 函数的参数有连个argc argcv[]  argc 是参数个数 argcv是参数的数组指针,且argcv的第一个参数是默认程序路径加程序名 给main传参数,需要在命令行启动程序时设置 如 ...

  6. ajax跨域通过 Cors跨域资源共享 进行GetPost请求

    using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Ne ...

  7. test for cvx library in matlab - windows

    Download the zip file of cvx http://cvxr.com/cvx/download/ by downloading cvx-w64.zip Require a lice ...

  8. iOS webView与H5的交互(返回页面的处理)

    摘自:http://blog.csdn.net/qq_29284809/article/details/50548413 调用 H5页面的同名返回方法(必须保证名字一致)!!!

  9. Cen0S下挂载设备

    在CentOS中,如果我们要查看光驱,U盘或者要把安装包挂载到某个文件夹,我写下我的一些理解. 所谓的挂载,就是把物理设备或者文件(包含安装文件,压缩包等等),与系统中的某个目录建立一个快捷方式,然后 ...

  10. iPhone CSS media query(媒体查询)

    iPhone5  iPhone6  iPhone6Plus iPad设备 media query(媒体查询)代码. iPhone < 5: @media screen and (device-a ...