• 通讯录-C/C++


    问题描述

    设计一个通讯录管理程序,要求程序采用模块化设计方法,程序应采用由主控程序调用各模块实现各个功能的方式。程序应具有如下功能:输入记录显示记录查找记录插入记录记录排序删除记录等。数据存储采用外存存储形式,存放于外存的数据应进行加密处理。

    设计分析

    通讯录中的数据可以看作是由多条记录组成的一个二维表格,一行对应一条记录,每条记录都有同样的字段序列。在管理程序中对数据进行组织时,可以使用结构体(struct)来描述记录,结构体中的成员即就是记录中的各个字段。通过结构体数组即可以存放通讯录中的多条记录。数据在外存进行存取操作时,可以使用按记录存取的方式进行。

    例如,可以采用如下形式定义通讯录对应的结构体:

    1. struct record {// 记录
    2. char name[20];
    3. char phone[12];
    4. char adress[50];
    5. char postcode[8];
    6. char e_mail[20];
    7. }student[SIZE];

    解决方案

    通过定义以下各函数实现程序功能模块的功能,在主函数中调用各函数:

    (1)通讯录管理菜单

    1. int menu_select() {// 菜单选择
    2. char s[80];
    3. int a;
    4. system("cls");// 清屏
    5. printf("\t\t***********欢迎进入通讯管理界面********\n\n");
    6. printf("\t\t\t0. 输入记录\n");
    7. printf("\t\t\t1. 显示记录\n");
    8. printf("\t\t\t2. 按姓名查找\n");
    9. printf("\t\t\t3. 按电话号码查找\n");
    10. printf("\t\t\t4. 插入记录 \n");
    11. printf("\t\t\t5. 按姓名排序\n");
    12. printf("\t\t\t6. 删除记录\n");
    13. printf("\t\t\t7. Quit\n");
    14. printf("\t\t***********************************************\n\n");
    15. do {
    16. printf("Enter you choice(0~7):");
    17. scanf("%s", s);
    18. a = atoi(s);// 将字符串转化成整型值
    19. } while (a < 0 || a>7);// 当输入小于0或大于7,将循环输入
    20. return a;
    21. }

    (2)输入记录

    1. int adduser() {// 添加记录
    2. printf("\t\t\t**************** 请输入用户信息 ****************\n");
    3. printf("\t\t\t输入姓名:\n");
    4. scanf("%s", student[num].name);
    5. printf("\t\t\t输入电话号码:\n");
    6. scanf("%s", student[num].phone);
    7. printf("\t\t\t输入地址:\n");
    8. scanf("%s", student[num].adress);
    9. printf("\t\t\t输入邮编:\n");
    10. scanf("%s", student[num].postcode);
    11. printf("\t\t\t输入e-mail:\n");
    12. scanf("%s", student[num].e_mail);
    13. num++;
    14. printf("\t\t\t是否继续添加?(Y/N):\n");
    15. if (getch() == 'y' || getch() == 'Y')// 输入大写和小写字母y都行
    16. adduser();// 再次调用添加记录
    17. return(0);
    18. }

    (3)显示记录

    1. void list() {// 显示记录
    2. int i;
    3. system("cls");// 清屏
    4. if (num != 0) {// 如果记录的数字不为0,逐个打印记录
    5. printf("\t\t\t*************** 以下为通讯录所有信息************\n");
    6. for (i = 0; i < num; i++) {
    7. printf("\t\t\t姓名:%s\n", student[i].name);
    8. printf("\t\t\t电话:%s\n", student[i].phone);
    9. printf("\t\t\t地址:%s\n", student[i].adress);
    10. printf("\t\t\t邮编:%s\n", student[i].postcode);
    11. printf("\t\t\te-mail:%s\n", student[i].e_mail);
    12. if (i + 1 < num) {
    13. system("pause");// 程序暂停
    14. }
    15. }
    16. printf("\t\t\t************************************************\n");
    17. }
    18. else// 如果记录数字为0,则程序中无记录
    19. printf("\t\t\t通讯录中无任何纪录\n");
    20. printf("\t\t\t按任意键返回主菜单:\n");
    21. getch();// 获取按下的任意键
    22. return;
    23. }

    (4)按姓名查找记录

    1. int searchbyname() {// 按姓名查找
    2. int mark = 0;// 定义一个变量作为标记
    3. int i;// 定义一个循环辅助变量
    4. printf("\t\t\t***************** 按姓名查找 *******************\n");
    5. char name[20];
    6. printf("\t\t\t请输入姓名:\n");
    7. scanf("%s", name);
    8. for (i = 0; i < num; i++) {
    9. if (strcmp(student[i].name, name) == 0) {// 将输入的姓名与存入的比较,相同为0进行打印
    10. printf("\t\t\t************* 以下是您查找的用户信息 ***********\n");
    11. printf("\t\t\t姓名: %s", student[i].name);
    12. printf("\t\t\t电话: %s", student[i].phone);
    13. printf("\t\t\t地址: %s", student[i].adress);
    14. printf("\t\t\te-mail:%s", student[i].e_mail);
    15. printf("\t\t\t************************************************\n");
    16. mark++;// 标记加1
    17. if ((i + 1) < num) {// 如果遍历到某一位置加1还是比所有记录的数小,选择继续查找或终止查找
    18. printf("\t\t\t是否继续查找相同名字的用户信息:(y/n)\n");
    19. if (getch() == 'y' || getch() == 'Y') {// 输入y则继续查找
    20. continue;
    21. }
    22. else
    23. return(0);
    24. }
    25. else {
    26. printf("\t\t\t按任意键返回主菜单");
    27. getch();// 获取按下的任意键
    28. return(0);
    29. }
    30. }
    31. }
    32. if (mark == 0) {// 如果mark的值为0,表示没有此名字的用户记录
    33. printf("\t\t\t没有相同姓名的用户纪录\n");
    34. printf("\t\t\t按任意键返回主菜单\n");
    35. getch();// 获取按下的任意键
    36. return(0);
    37. }
    38. return 0;
    39. }

    (5)按电话号码查找记录

    1. int searchbyphone() {// 按电话号码查找
    2. int mark = 0;// 定义一个变量用于标记
    3. int i;// 定义一个循环辅助变量
    4. printf("\t\t\t****************** 按电话查找 ******************\n");
    5. char phone[10];
    6. printf("\t\t\t请输入电话号码:\n");
    7. scanf("%s", phone);
    8. for (i = 0; i < num; i++) {
    9. if (strcmp(student[i].phone, phone) == 0) {// 将输入的电话号码与存入的比较,相同为0进行打印
    10. printf("\t\t\t************** 以下是您查找的用户信息 **********\n");
    11. printf("\t\t\t姓名: %s", student[i].name);
    12. printf("\t\t\t电话: %s", student[i].phone);
    13. printf("\t\t\t地址: %s", student[i].adress);
    14. printf("\t\t\te-mail:%s", student[i].e_mail);
    15. printf("\t\t\t************************************************\n");
    16. printf("\t\t\t按任意键返回主菜单\n");
    17. mark++;// 标记加1
    18. getch();// 获取按下的任意键
    19. return(0);
    20. }
    21. }
    22. if (mark == 0) {// 如果mark的值为0,表示没有此电话号码的记录
    23. printf("\t\t\t没有改用户的信息\n");
    24. printf("\t\t\t按任意键返回主菜单\n");
    25. getch();// 获取按下的任意键
    26. return(0);
    27. }
    28. return(0);
    29. }

    (6)按电话号码删除记录

    1. void deletebyphone() {// 按电话号码删除记录
    2. int i, j;// 定义循环辅助变量
    3. int deletemark = 0;// 定义变量用于标记
    4. char phone[20];
    5. printf("\t\t\t请输入要删除用户电话号码:\n");
    6. scanf("%s", phone);
    7. if (num == 0) {// 记录变量为0,则无输入记录
    8. printf("\t\t\t对不起,文件中无任何纪录\n");
    9. printf("\t\t\t按任意键返回主菜单\n");
    10. getch();// 获取按下的任意键
    11. return;
    12. }
    13. for (i = 0; i < num; i++) {
    14. if (strcmp(student[i].phone, phone) == 0) {// 比较输入的电话号码与存入的电话号码比较,相同为0
    15. printf("\t\t\t以下是您要删除的用户纪录:\n");
    16. printf("\t\t\t姓名: %s", student[i].name);
    17. printf("\t\t\t电话: %s", student[i].phone);
    18. printf("\t\t\t地址: %s", student[i].adress);
    19. printf("\t\t\te-mail:%s", student[i].e_mail);
    20. printf("\t\t\t是否删除?(y/n)");
    21. if (getch() == 'y' || getch() == 'Y') {// 判断是否确认删除
    22. for (j = i; j < num - 1; j++)// 循环将后一条记录前移1个
    23. student[j] = student[j + 1];
    24. num--;
    25. deletemark++;// 删除标记加1
    26. printf("\t\t\t删除成功");
    27. printf("\t\t\t是否继续删除?(y/n)");
    28. if (getch() == 'y' || getch() == 'Y')// 判断是否继续删除
    29. deletebyphone();// 调用按电话号码删除记录
    30. return;
    31. }
    32. else
    33. return;
    34. }
    35. continue;
    36. }
    37. if (deletemark == 0) {// 判断是否有此电话号码的用户信息
    38. printf("\t\t\t没有该用户的纪录");
    39. printf("\t\t\t是否继续删除?(y/n)");
    40. if (getch() == 'y' || getch() == 'Y')// 判断是否继续删除
    41. deletebyphone();// 调用按电话号码删除记录
    42. return;
    43. }
    44. return;
    45. }

    (7)按姓名删除记录

    1. void deletebyname() {// 按姓名删除记录
    2. int a = 0;// 循环辅助变量
    3. int findmark = 0;// 查找标记
    4. int j;// 循环辅助变量
    5. int deletemark = 0;// 删除标记
    6. int i;// 循环辅助变量
    7. char name[20];
    8. printf("\t\t\t请输入要删除用户姓名:\n");
    9. scanf("%s", name);
    10. for (i = a; i < num; i++) {
    11. if (strcmp(student[i].name, name) == 0) {// 比较输入的姓名与存入的姓名比较,相同为0
    12. printf("\t\t\t以下是您要删除的用户纪录:");
    13. findmark++;// 查找标记加1
    14. printf("\t\t\t________________________________");
    15. printf("\t\t\t姓名: %s", student[i].name);
    16. printf("\t\t\t电话: %s", student[i].phone);
    17. printf("\t\t\t地址: %s", student[i].adress);
    18. printf("\t\t\te-mail:%s", student[i].e_mail);
    19. printf("\t\t\t________________________________");
    20. printf("\t\t\t是否删除?(y/n)");
    21. if (getch() == 'y' || getch() == 'Y') {
    22. for (j = i; j < num - 1; j++)// 遍历记录个数-1,将后一个数据逐个替代前一个数据
    23. student[j] = student[j + 1];
    24. num--;// 总记录数减1
    25. deletemark++;// 删除标记加1
    26. printf("\t\t\t删除成功");
    27. if ((i + 1) < num) {
    28. printf("\t\t\t是否继续删除相同姓名的用户信息?(y/n)");
    29. if (getch() == 'y') {
    30. a = i;// 将当前i值赋给a用于后续继续删除相同姓名的用户信息
    31. continue;
    32. }
    33. }
    34. printf("\t\t\t是否继续删除?(y/n)");
    35. if (getch() == 'y')// 判断是否继续删除
    36. deletebyname();// 调用按姓名删除记录
    37. return;
    38. }
    39. if ((i + 1) < num) {// 判断是否将所有用户信息遍历完
    40. printf("\t\t\t是否继续删除相同姓名的用户信息?(y/n)");
    41. if (getch() == 'y' || getch() == 'Y') {// 判断是否继续删除相同姓名的用户信息
    42. a = i;// 将当前i值赋给a用于后续继续删除相同姓名的用户信息
    43. continue;
    44. }
    45. }
    46. }
    47. else
    48. continue;
    49. }
    50. if ((deletemark == 0) && (findmark == 0)) {// 判断删除标记和查找标记是否同时为0,为0则没有该用户信息
    51. printf("\t\t\t没有该用户的纪录");
    52. printf("\t\t\t是否继续删除?(y/n)");
    53. if (getch() == 'y' || getch() == 'Y')// 判断是否继续删除
    54. deletebyname();// 调用按姓名删除记录
    55. return;
    56. }
    57. else if (findmark != 0) {// 判断查找标记不为0,则没有重名
    58. printf("\t\t\t没有重名信息");
    59. printf("\t\t\t没有该用户的纪录");
    60. printf("\t\t\t是否继续删除?(y/n)");
    61. if (getch() == 'y' || getch() == 'Y')// 判断是否继续删除
    62. deletebyname();// 调用按姓名删除记录
    63. return;
    64. }
    65. }

    (8)删除记录

    1. int dele() {// 删除记录
    2. char choic;
    3. printf("\t\t\t1-按电话号码删除 2-按姓名删除");
    4. printf("\t\t\t请选择:");
    5. choic = getch();// 从键盘获取字符
    6. switch (choic) {
    7. case '1':deletebyphone(); break;// 按电话号码删除
    8. case '2':deletebyname(); break;// 按姓名删除
    9. }
    10. return(0);
    11. }

    (9)按姓名排序

    1. int sortbyname() {// 按姓名排序
    2. int i, j;// 循环辅助变量
    3. struct record tmp;
    4. for (i = 1; i < num; i++) {
    5. if (strcmp(student[i].name, student[i - 1].name) < 0) {// 比较相邻两个姓名小于0时,则i位置的姓名要排在前面
    6. tmp = student[i];
    7. j = i - 1;
    8. do {
    9. student[j + 1] = student[j];
    10. j--;
    11. } while ((strcmp(tmp.name, student[j].name) < 0 && j >= 0));
    12. student[j + 1] = tmp;
    13. }
    14. }
    15. printf("\t\t\t排序成功,是否显示?(y/n)");
    16. if (getch() == 'y')// 是否显示
    17. list();// 调用显示记录
    18. return(0);
    19. }

    (10)读取外存文件数据

    1. void readfile() {
    2. /*从文件student_address_book.dat首部开始,按记录长度sizeof(struct record)*/
    3. /*循环读出每条记录,直至文件尾部;每读出一条记录,则调用encrypt()函数*/
    4. /*对相应字段进行解密处理,并使记录计数器num加1,统计出记录总数。 */
    5. FILE* ptr = fopen("student_address_book.dat", "r");//打开文件
    6. if (ptr == NULL) {//判断文件是否成功打开
    7. printf("open file student_address_book.dat打开失败");
    8. return;
    9. }
    10. num = 0;
    11. while (fread(&student[num], sizeof(struct record), 1, ptr) == 1) {//循环读取每条记录并进行解密
    12. encrypt(student[num].name);
    13. encrypt(student[num].phone);
    14. encrypt(student[num].adress);
    15. encrypt(student[num].postcode);
    16. encrypt(student[num].e_mail);
    17. num++;
    18. }
    19. fclose(ptr);//关闭文件
    20. ptr = NULL;//将文件设置为空
    21. }

    (11)向外存文件写入数据

    1. void writefile() {
    2. /*根据记录总数num,从首条记录即结构体数组首元素student[0]开始, */
    3. /*调用encrypt()函数对相应字段进行加密处理,并将当前记录整体写入*/
    4. /*文件student_address_book.dat中,直至最后一条记录。 */
    5. /*也可以先对所有记录进行加密处理,然后整体一次性写入文件。 */
    6. FILE* ptw = fopen("student_address_book.dat", "w");//打开文件
    7. if (ptw == NULL) {//判断文件是否成功打开
    8. printf("open file student_address_book.dat打开失败");
    9. return;
    10. }
    11. int i = 0;//循环辅助变量
    12. for (i = 0; i < num; i++) {//把联系人信息循环写入文件中并进行加密处理
    13. encrypt(student[i].name);
    14. encrypt(student[i].phone);
    15. encrypt(student[i].adress);
    16. encrypt(student[i].postcode);
    17. encrypt(student[i].e_mail);
    18. fwrite(&student[i], sizeof(struct record), 1, ptw);//将数据整体写入文件
    19. }
    20. fclose(ptw);//关闭文件
    21. ptw = NULL;//将文件设置为空
    22. }

    (12)用户信息加密处理

    1. void encrypt(char* pwd) {//对数据进行加密操作
    2. /*与15(二进制码是00001111)异或,实现低四位取反,高四位保持不变*/
    3. while (*pwd != '\0') {//循环遍历数组
    4. *pwd = *pwd ^ 15;//将每条数据与15进行异或
    5. pwd++;
    6. }
    7. }

    (13)主函数

    1. int main() {
    2. printf("\t\t************************************************\n");
    3. printf("\t\t***************欢迎进入通讯录*******************\n");
    4. printf("\t\t*************************************************\n");
    5. printf("按任意键进入主菜单\n");
    6. readfile();//读取文件里的内容
    7. getch();
    8. int selectnum;
    9. while (1) {
    10. selectnum = menu_select();
    11. switch (selectnum) {
    12. case 0:
    13. {
    14. adduser();// 调用添加记录
    15. break;
    16. }
    17. case 1:
    18. {
    19. list();// 调用显示记录
    20. break;
    21. }
    22. case 2:
    23. {
    24. searchbyname();// 调用按姓名查找
    25. break;
    26. }
    27. case 3:
    28. {
    29. searchbyphone();// 调用按电话号码查找
    30. break;
    31. }
    32. case 4:
    33. {
    34. adduser();// 调用添加记录
    35. break;
    36. }
    37. case 5:
    38. {
    39. sortbyname();// 调用按姓名排序
    40. break;
    41. }
    42. case 6:
    43. {
    44. dele();// 调用删除记录
    45. break;
    46. }
    47. case 7:
    48. {
    49. printf("BYE BYE!\n");
    50. system("pause");// 程序暂停
    51. writefile();//将程序中的数据写入文件
    52. getchar();// 从缓冲区读取一个字符
    53. exit(0);// 退出程序
    54. }
    55. }
    56. }
    57. getchar();// 从缓冲区读取一个字符
    58. return 0;
    59. }

    最终整合代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #define SIZE 100
    6. struct record {// 记录
    7. char name[20];
    8. char phone[12];
    9. char adress[50];
    10. char postcode[8];
    11. char e_mail[20];
    12. }student[SIZE];
    13. int num;
    14. int menu_select() {// 菜单选择
    15. char s[80];
    16. int a;
    17. system("cls");// 清屏
    18. printf("\t\t***********欢迎进入通讯管理界面********\n\n");
    19. printf("\t\t\t0. 输入记录\n");
    20. printf("\t\t\t1. 显示记录\n");
    21. printf("\t\t\t2. 按姓名查找\n");
    22. printf("\t\t\t3. 按电话号码查找\n");
    23. printf("\t\t\t4. 插入记录 \n");
    24. printf("\t\t\t5. 按姓名排序\n");
    25. printf("\t\t\t6. 删除记录\n");
    26. printf("\t\t\t7. Quit\n");
    27. printf("\t\t***********************************************\n\n");
    28. do {
    29. printf("Enter you choice(0~7):");
    30. scanf("%s", s);
    31. a = atoi(s);// 将字符串转化成整型值
    32. } while (a < 0 || a>7);// 当输入小于0或大于7,将循环输入
    33. return a;
    34. }
    35. int adduser() {// 添加记录
    36. printf("\t\t\t**************** 请输入用户信息 ****************\n");
    37. printf("\t\t\t输入姓名:\n");
    38. scanf("%s", student[num].name);
    39. printf("\t\t\t输入电话号码:\n");
    40. scanf("%s", student[num].phone);
    41. printf("\t\t\t输入地址:\n");
    42. scanf("%s", student[num].adress);
    43. printf("\t\t\t输入邮编:\n");
    44. scanf("%s", student[num].postcode);
    45. printf("\t\t\t输入e-mail:\n");
    46. scanf("%s", student[num].e_mail);
    47. num++;
    48. printf("\t\t\t是否继续添加?(Y/N):\n");
    49. if (getch() == 'y' || getch() == 'Y')// 输入大写和小写字母y都行
    50. adduser();// 再次调用添加记录
    51. return(0);
    52. }
    53. void list() {// 显示记录
    54. int i;
    55. system("cls");// 清屏
    56. if (num != 0) {// 如果记录的数字不为0,逐个打印记录
    57. printf("\t\t\t*************** 以下为通讯录所有信息************\n");
    58. for (i = 0; i < num; i++) {
    59. printf("\t\t\t姓名:%s\n", student[i].name);
    60. printf("\t\t\t电话:%s\n", student[i].phone);
    61. printf("\t\t\t地址:%s\n", student[i].adress);
    62. printf("\t\t\t邮编:%s\n", student[i].postcode);
    63. printf("\t\t\te-mail:%s\n", student[i].e_mail);
    64. if (i + 1 < num) {
    65. system("pause");// 程序暂停
    66. }
    67. }
    68. printf("\t\t\t************************************************\n");
    69. }
    70. else// 如果记录数字为0,则程序中无记录
    71. printf("\t\t\t通讯录中无任何纪录\n");
    72. printf("\t\t\t按任意键返回主菜单:\n");
    73. getch();// 获取按下的任意键
    74. return;
    75. }
    76. int searchbyname() {// 按姓名查找
    77. int mark = 0;// 定义一个变量作为标记
    78. int i;// 定义一个循环辅助变量
    79. printf("\t\t\t***************** 按姓名查找 *******************\n");
    80. char name[20];
    81. printf("\t\t\t请输入姓名:\n");
    82. scanf("%s", name);
    83. for (i = 0; i < num; i++) {
    84. if (strcmp(student[i].name, name) == 0) {// 将输入的姓名与存入的比较,相同为0进行打印
    85. printf("\t\t\t************* 以下是您查找的用户信息 ***********\n");
    86. printf("\t\t\t姓名: %s", student[i].name);
    87. printf("\t\t\t电话: %s", student[i].phone);
    88. printf("\t\t\t地址: %s", student[i].adress);
    89. printf("\t\t\te-mail:%s", student[i].e_mail);
    90. printf("\t\t\t************************************************\n");
    91. mark++;// 标记加1
    92. if ((i + 1) < num) {// 如果遍历到某一位置加1还是比所有记录的数小,选择继续查找或终止查找
    93. printf("\t\t\t是否继续查找相同名字的用户信息:(y/n)\n");
    94. if (getch() == 'y' || getch() == 'Y') {// 输入y则继续查找
    95. continue;
    96. }
    97. else
    98. return(0);
    99. }
    100. else {
    101. printf("\t\t\t按任意键返回主菜单");
    102. getch();// 获取按下的任意键
    103. return(0);
    104. }
    105. }
    106. }
    107. if (mark == 0) {// 如果mark的值为0,表示没有此名字的用户记录
    108. printf("\t\t\t没有相同姓名的用户纪录\n");
    109. printf("\t\t\t按任意键返回主菜单\n");
    110. getch();// 获取按下的任意键
    111. return(0);
    112. }
    113. return 0;
    114. }
    115. int searchbyphone() {// 按电话号码查找
    116. int mark = 0;// 定义一个变量用于标记
    117. int i;// 定义一个循环辅助变量
    118. printf("\t\t\t****************** 按电话查找 ******************\n");
    119. char phone[10];
    120. printf("\t\t\t请输入电话号码:\n");
    121. scanf("%s", phone);
    122. for (i = 0; i < num; i++) {
    123. if (strcmp(student[i].phone, phone) == 0) {// 将输入的电话号码与存入的比较,相同为0进行打印
    124. printf("\t\t\t************** 以下是您查找的用户信息 **********\n");
    125. printf("\t\t\t姓名: %s", student[i].name);
    126. printf("\t\t\t电话: %s", student[i].phone);
    127. printf("\t\t\t地址: %s", student[i].adress);
    128. printf("\t\t\te-mail:%s", student[i].e_mail);
    129. printf("\t\t\t************************************************\n");
    130. printf("\t\t\t按任意键返回主菜单\n");
    131. mark++;// 标记加1
    132. getch();// 获取按下的任意键
    133. return(0);
    134. }
    135. }
    136. if (mark == 0) {// 如果mark的值为0,表示没有此电话号码的记录
    137. printf("\t\t\t没有改用户的信息\n");
    138. printf("\t\t\t按任意键返回主菜单\n");
    139. getch();// 获取按下的任意键
    140. return(0);
    141. }
    142. return(0);
    143. }
    144. void deletebyphone() {// 按电话号码删除记录
    145. int i, j;// 定义循环辅助变量
    146. int deletemark = 0;// 定义变量用于标记
    147. char phone[20];
    148. printf("\t\t\t请输入要删除用户电话号码:\n");
    149. scanf("%s", phone);
    150. if (num == 0) {// 记录变量为0,则无输入记录
    151. printf("\t\t\t对不起,文件中无任何纪录\n");
    152. printf("\t\t\t按任意键返回主菜单\n");
    153. getch();// 获取按下的任意键
    154. return;
    155. }
    156. for (i = 0; i < num; i++) {
    157. if (strcmp(student[i].phone, phone) == 0) {// 比较输入的电话号码与存入的电话号码比较,相同为0
    158. printf("\t\t\t以下是您要删除的用户纪录:\n");
    159. printf("\t\t\t姓名: %s", student[i].name);
    160. printf("\t\t\t电话: %s", student[i].phone);
    161. printf("\t\t\t地址: %s", student[i].adress);
    162. printf("\t\t\te-mail:%s", student[i].e_mail);
    163. printf("\t\t\t是否删除?(y/n)");
    164. if (getch() == 'y' || getch() == 'Y') {// 判断是否确认删除
    165. for (j = i; j < num - 1; j++)// 循环将后一条记录前移1个
    166. student[j] = student[j + 1];
    167. num--;
    168. deletemark++;// 删除标记加1
    169. printf("\t\t\t删除成功");
    170. printf("\t\t\t是否继续删除?(y/n)");
    171. if (getch() == 'y' || getch() == 'Y')// 判断是否继续删除
    172. deletebyphone();// 调用按电话号码删除记录
    173. return;
    174. }
    175. else
    176. return;
    177. }
    178. continue;
    179. }
    180. if (deletemark == 0) {// 判断是否有此电话号码的用户信息
    181. printf("\t\t\t没有该用户的纪录");
    182. printf("\t\t\t是否继续删除?(y/n)");
    183. if (getch() == 'y' || getch() == 'Y')// 判断是否继续删除
    184. deletebyphone();// 调用按电话号码删除记录
    185. return;
    186. }
    187. return;
    188. }
    189. void deletebyname() {// 按姓名删除记录
    190. int a = 0;// 循环辅助变量
    191. int findmark = 0;// 查找标记
    192. int j;// 循环辅助变量
    193. int deletemark = 0;// 删除标记
    194. int i;// 循环辅助变量
    195. char name[20];
    196. printf("\t\t\t请输入要删除用户姓名:\n");
    197. scanf("%s", name);
    198. for (i = a; i < num; i++) {
    199. if (strcmp(student[i].name, name) == 0) {// 比较输入的姓名与存入的姓名比较,相同为0
    200. printf("\t\t\t以下是您要删除的用户纪录:");
    201. findmark++;// 查找标记加1
    202. printf("\t\t\t________________________________");
    203. printf("\t\t\t姓名: %s", student[i].name);
    204. printf("\t\t\t电话: %s", student[i].phone);
    205. printf("\t\t\t地址: %s", student[i].adress);
    206. printf("\t\t\te-mail:%s", student[i].e_mail);
    207. printf("\t\t\t________________________________");
    208. printf("\t\t\t是否删除?(y/n)");
    209. if (getch() == 'y' || getch() == 'Y') {
    210. for (j = i; j < num - 1; j++)// 遍历记录个数-1,将后一个数据逐个替代前一个数据
    211. student[j] = student[j + 1];
    212. num--;// 总记录数减1
    213. deletemark++;// 删除标记加1
    214. printf("\t\t\t删除成功");
    215. if ((i + 1) < num) {
    216. printf("\t\t\t是否继续删除相同姓名的用户信息?(y/n)");
    217. if (getch() == 'y') {
    218. a = i;// 将当前i值赋给a用于后续继续删除相同姓名的用户信息
    219. continue;
    220. }
    221. }
    222. printf("\t\t\t是否继续删除?(y/n)");
    223. if (getch() == 'y')// 判断是否继续删除
    224. deletebyname();// 调用按姓名删除记录
    225. return;
    226. }
    227. if ((i + 1) < num) {// 判断是否将所有用户信息遍历完
    228. printf("\t\t\t是否继续删除相同姓名的用户信息?(y/n)");
    229. if (getch() == 'y' || getch() == 'Y') {// 判断是否继续删除相同姓名的用户信息
    230. a = i;// 将当前i值赋给a用于后续继续删除相同姓名的用户信息
    231. continue;
    232. }
    233. }
    234. }
    235. else
    236. continue;
    237. }
    238. if ((deletemark == 0) && (findmark == 0)) {// 判断删除标记和查找标记是否同时为0,为0则没有该用户信息
    239. printf("\t\t\t没有该用户的纪录");
    240. printf("\t\t\t是否继续删除?(y/n)");
    241. if (getch() == 'y' || getch() == 'Y')// 判断是否继续删除
    242. deletebyname();// 调用按姓名删除记录
    243. return;
    244. }
    245. else if (findmark != 0) {// 判断查找标记不为0,则没有重名
    246. printf("\t\t\t没有重名信息");
    247. printf("\t\t\t没有该用户的纪录");
    248. printf("\t\t\t是否继续删除?(y/n)");
    249. if (getch() == 'y' || getch() == 'Y')// 判断是否继续删除
    250. deletebyname();// 调用按姓名删除记录
    251. return;
    252. }
    253. }
    254. int dele() {// 删除记录
    255. char choic;
    256. printf("\t\t\t1-按电话号码删除 2-按姓名删除");
    257. printf("\t\t\t请选择:");
    258. choic = getch();// 从键盘获取字符
    259. switch (choic) {
    260. case '1':deletebyphone(); break;// 按电话号码删除
    261. case '2':deletebyname(); break;// 按姓名删除
    262. }
    263. return(0);
    264. }
    265. int sortbyname() {// 按姓名排序
    266. int i, j;// 循环辅助变量
    267. struct record tmp;
    268. for (i = 1; i < num; i++) {
    269. if (strcmp(student[i].name, student[i - 1].name) < 0) {// 比较相邻两个姓名小于0时,则i位置的姓名要排在前面
    270. tmp = student[i];
    271. j = i - 1;
    272. do {
    273. student[j + 1] = student[j];
    274. j--;
    275. } while ((strcmp(tmp.name, student[j].name) < 0 && j >= 0));
    276. student[j + 1] = tmp;
    277. }
    278. }
    279. printf("\t\t\t排序成功,是否显示?(y/n)");
    280. if (getch() == 'y')// 是否显示
    281. list();// 调用显示记录
    282. return(0);
    283. }
    284. void encrypt(char* pwd) {//对数据进行加密操作
    285. /*与15(二进制码是00001111)异或,实现低四位取反,高四位保持不变*/
    286. while (*pwd != '\0') {//循环遍历数组
    287. *pwd = *pwd ^ 15;//将每条数据与15进行异或
    288. pwd++;
    289. }
    290. }
    291. void readfile() {
    292. /*从文件student_address_book.dat首部开始,按记录长度sizeof(struct record)*/
    293. /*循环读出每条记录,直至文件尾部;每读出一条记录,则调用encrypt()函数*/
    294. /*对相应字段进行解密处理,并使记录计数器num加1,统计出记录总数。 */
    295. FILE* ptr = fopen("student_address_book.dat", "r");//打开文件
    296. if (ptr == NULL) {//判断文件是否成功打开
    297. printf("open file student_address_book.dat打开失败");
    298. return;
    299. }
    300. num = 0;
    301. while (fread(&student[num], sizeof(struct record), 1, ptr) == 1) {//循环读取每条记录并进行解密
    302. encrypt(student[num].name);
    303. encrypt(student[num].phone);
    304. encrypt(student[num].adress);
    305. encrypt(student[num].postcode);
    306. encrypt(student[num].e_mail);
    307. num++;
    308. }
    309. fclose(ptr);//关闭文件
    310. ptr = NULL;//将文件设置为空
    311. }
    312. void writefile() {
    313. /*根据记录总数num,从首条记录即结构体数组首元素student[0]开始, */
    314. /*调用encrypt()函数对相应字段进行加密处理,并将当前记录整体写入*/
    315. /*文件student_address_book.dat中,直至最后一条记录。 */
    316. /*也可以先对所有记录进行加密处理,然后整体一次性写入文件。 */
    317. FILE* ptw = fopen("student_address_book.dat", "w");//打开文件
    318. if (ptw == NULL) {//判断文件是否成功打开
    319. printf("open file student_address_book.dat打开失败");
    320. return;
    321. }
    322. int i = 0;//循环辅助变量
    323. for (i = 0; i < num; i++) {//把联系人信息循环写入文件中并进行加密处理
    324. encrypt(student[i].name);
    325. encrypt(student[i].phone);
    326. encrypt(student[i].adress);
    327. encrypt(student[i].postcode);
    328. encrypt(student[i].e_mail);
    329. fwrite(&student[i], sizeof(struct record), 1, ptw);//将数据整体写入文件
    330. }
    331. fclose(ptw);//关闭文件
    332. ptw = NULL;//将文件设置为空
    333. }
    334. int main() {
    335. printf("\t\t************************************************\n");
    336. printf("\t\t***************欢迎进入通讯录*******************\n");
    337. printf("\t\t*************************************************\n");
    338. printf("按任意键进入主菜单\n");
    339. readfile();//读取文件里的内容
    340. getch();
    341. int selectnum;
    342. while (1) {
    343. selectnum = menu_select();
    344. switch (selectnum) {
    345. case 0:
    346. {
    347. adduser();// 调用添加记录
    348. break;
    349. }
    350. case 1:
    351. {
    352. list();// 调用显示记录
    353. break;
    354. }
    355. case 2:
    356. {
    357. searchbyname();// 调用按姓名查找
    358. break;
    359. }
    360. case 3:
    361. {
    362. searchbyphone();// 调用按电话号码查找
    363. break;
    364. }
    365. case 4:
    366. {
    367. adduser();// 调用添加记录
    368. break;
    369. }
    370. case 5:
    371. {
    372. sortbyname();// 调用按姓名排序
    373. break;
    374. }
    375. case 6:
    376. {
    377. dele();// 调用删除记录
    378. break;
    379. }
    380. case 7:
    381. {
    382. printf("BYE BYE!\n");
    383. system("pause");// 程序暂停
    384. writefile();//将程序中的数据写入文件
    385. getchar();// 从缓冲区读取一个字符
    386. exit(0);// 退出程序
    387. }
    388. }
    389. }
    390. getchar();// 从缓冲区读取一个字符
    391. return 0;
    392. }

  • 相关阅读:
    Kyligence Copilot 亮相第六届进博会,增添数智新活力
    海康威视-下载的录像视频浏览器播放问题
    结构体,联合体与位段
    linux docker安装SqlServer2019
    step5 lasso 回归 实战
    reportportal 集成 robotframework 自动化执行及结果可视化
    FreeSWITCH在session上执行定时挂机与取消
    在PowerDesigner中应用达梦数据库
    java计算机毕业设计高校学生党建管理系统MyBatis+系统+LW文档+源码+调试部署
    记录--一些看起来很叼难的前端面试题
  • 原文地址:https://blog.csdn.net/2302_77527700/article/details/131289395