【C语言进阶】进来抄作业,完善你的通讯录(软工期末大作业可用)
目录
🥰前言🥰:
一、输入合法性检测🤠:
①.对“ 联系方式 ”的合法性检测:
②.对“年龄”进行合法性检测:
二、字典排序🤑:
三、反馈优化🤯:
四、优化版通讯录全部源码🤩:
①.Contact.h:
②.Contact.c:
③.test.c:
🥳总结🥳:
🛰️博客主页:✈️銮同学的干货分享基地
🛰️欢迎关注:👍点赞🙌收藏✍️留言
🛰️系列专栏:💐【进阶】C语言学习
🛰️代码仓库:🎉VS2022_C语言仓库
家人们更新不易,你们的👍点赞👍和👉关注👈真的对我真重要,各位路过的友友麻烦多多点赞关注,欢迎你们的私信提问,感谢你们的转发!
关注我,关注我,关注我,你们将会看到更多的优质内容!!
🏡🏡 本文重点 🏡🏡:
🚅 优化完善静态通讯录(源码在结尾) 🚏🚏
🥰前言🥰:
在上篇文章中我们已经使用我们所学过的结构体相关知识,写出了一个基础版本的通讯录工具,但是我们也知道这个基础版本的通讯录工具仍然存在着许多的缺陷。
我们注意到,在我们的基础版通讯录中,我们对输入的值没有合法性检测,这将会导致,无论用户输入什么样的值都将会被我们的通讯录存储,并且由于输入与反馈的数据类型及格式差异,很有可能会导致输出错误。并且我们可以回想一下,我们手机里的通讯录在保存好联系人信息后,在我们进行查看时,会按照类似字典内的排序方式(即字典排序)将所有联系人进行排序后反馈给用户,而在我们基础版的通讯录中,保存的联系人信息还没有经过排序。最后还有对输出反馈的优化,相信各位小伙伴们在使用通讯录的时侯,屏幕上的打印反馈信息也应该都不是凌乱的吧。
而关于上面所说的这些问题,我们今天就将逐一进行处理。
一、输入合法性检测🤠:
关于合法性检测,我们的要求是对需要进行输入合法性检测的信息进行合法性检测。例如输入联系方式时若用户输入非数字字符,则提示用户输入非法;以及在用户输入年龄时应当对年龄范围进行限制,超出限制范围则应提示用户输入非法。
①.对“ 联系方式 ”的合法性检测:
对联系方式的合法性检测我们认为应当分为两步,首先我们应当对输入的联系方式内容进行检测,这里所采用的方式是,对数组内字符串进行遍历,在前11个位置(联系方式为 11 位)每个位置上的字符均为数字字符 0~9 时,则继续向后遍历,全部遍历完成且没有错误后则判断为合法,否则为不合法,提醒用户输入非法并要求用户重新进行输入:
scanf("%s", p->data[p->sz].tele);
char check1[MAX_TELE] = { 0 };
strcpy(check1, p->data[p->sz].tele);
int i = 0;
int cmp = 0;
//比较变量cmp用于标记各位置上的判断结果
for (i = 0; i < 11; i++)
{
if ('0' <= check1[i] && check1[i] <= '9')
{
cmp = 0;
}
else
{
cmp = 1;
break;
}
}
if (cmp)
{
printf("您输入的联系方式有误,请重新输入!\n");
}
接下来我们还要进行联系方式长度检测,我们当前所使用的联系方式通常为 11 位,于是我们就将位数暂且定为11位,并且我们前面的合法位判断中已经确定了每一位上均为合法,于是在这里我们只需要对位数加以判断即可,我们选择的判断方法是若第十二位为初始化时的 0(即第十二位没有输入值),则合法,否则不合法:
if (check1[11] == 0)
//下标从零开始,第十二位下标为11
{
;
//若合法则不进行操作,不合法则提示不合法并重新输入
}
else
{
cmp = 1;
}
最后我们再对整个循环条件进行判断即可。我们使用了 do ... while 循环,保证了合法性判断至少进行一次,并在判断循环一开始便让判断条件 input 变为 0(假),若在判断结束时仍没有不合法现象,则判断为假跳出循环,合法性判断结束;若在过程中判断存在不合法输入,则将其值重新赋为 1,提示不合法后继续进入下一循环:
int input = 1;
do
{
input = 0;
//直接让input为0,若出现不合法则改其值为1继续循环
//不符合不合法则跳出循环
printf("请输入联系人联系方式:>");
scanf("%s", p->data[p->sz].tele);
char check1[MAX_TELE] = { 0 };
strcpy(check1, p->data[p->sz].tele);
int i = 0;
int cmp = 0;
//比较变量cmp用于标记各位置上的判断结果
for (i = 0; i < 11; i++)
{
if ('0' <= check1[i] && check1[i] <= '9')
{
cmp = 0;
}
else
{
cmp = 1;
break;
}
}
if (check1[11] == 0)
//下标从零开始,第十二位下标为11
{
;
//若合法则不进行操作,不合法则提示不合法并重新输入
}
else
{
cmp = 1;
}
if (cmp)
{
input = 1;
//不合法继续循环
printf("您输入的联系方式有误,请重新输入!\n");
}
} while (input);
同时我们对“修改联系人信息”功能中的相关输入也需要采用这样的方式进行合法性判断:
case 4:
do
{
input_cmp = 0;
//直接让input_cmp为0,若出现不合法则改其值为1继续循环
//不符合不合法则跳出循环
printf("请输入联系人联系方式:>");
scanf("%s", p->data[x - 1].tele);
char check1[MAX_TELE] = { 0 };
strcpy(check1, p->data[x - 1].tele);
int i = 0;
int cmp = 0;
//比较变量cmp用于标记各位置上的判断结果
for (i = 0; i < 11; i++)
{
if ('0' <= check1[i] && check1[i] <= '9')
{
cmp = 0;
}
else
{
cmp = 1;
break;
}
}
if (check1[11] == 0)
//下标从零开始,第十二位下标为11
{
;
//若合法则不进行操作,不合法则提示不合法并重新输入
}
else
{
cmp = 1;
}
if (cmp)
{
input_cmp = 1;
//不合法继续循环
printf("您输入的联系方式有误,请重新输入!\n");
}
else
{
printf("修改成功!\n");
}
} while (input_cmp);
PrintContact(p, x - 1);
input = 0;
break;
②.对“年龄”进行合法性检测:
对年龄的合法性检测最为简单,我们只需要判断用户输入的年龄位于区间 0~100 之间即可,合法则跳出,否则继续循环:
int input = 1;
do
{
printf("请输入联系人年龄:>");
scanf("%d", &(p->data[p->sz].age));
if (0 <= p->data[p->sz].age && p->data[p->sz].age <= 100)
{
input = 0;
}
else
{
printf("您输入的年龄信息有误,请重新输入!\n");
}
} while (input);
同样的,将“修改联系人信息”功能中的输入以同样的方式进行合法性检测:
case 3:
do
{
printf("请输入联系人年龄:>");
scanf("%d", &(p->data[x - 1].age));
if (0 <= p->data[x - 1].age && p->data[x - 1].age <= 100)
{
input_cmp = 0;
printf("修改成功!\n");
}
else
{
printf("您输入的年龄信息有误,请重新输入!\n");
}
} while (input_cmp);
PrintContact(p, x - 1);
input = 0;
break;
二、字典排序🤑:
字典排序相对简单,简单来说,就是按照像字典里那样,根据姓名的排序,将通讯录中联系人信息进行排序。
而我们要想进行实现,其实也很简单,我们只需要像冒泡排序那样进行遍历,将每一个联系人的姓名均与下一个联系人进行比较,如果后一个联系人的姓名更靠前,则将二者的信息进行交换,否则继续向后一个进行比较:
//字典排序:
void sort(contact* p)
{
int i = 0;
PeoInfo temp;
for (i = 0; i < p->sz; i++)
{
if (strcmp(p->data[i].name, p->data[i + 1].name) > 0)
{
temp = p->data[i + 1];
p->data[i + 1] = p->data[i];
p->data[i] = temp;
}
}
}
在这里,我们只需要再定义一个中间结构体,并通过中间结构体直接交换两个联系人的信息即可,而不用逐一交换两个联系人的各项信息。
三、反馈优化🤯:
而关于反馈优化则很简单了。在优化前,我们的通讯录小工具运行起来是这个样子的:
优化前的程序运行结果肉眼可见的繁杂、凌乱,一团乱麻地堆在一起。于是我们就需要对小工具的打印反馈过程进行优化。
我们使用的方法仍然是,使用 Sleep 命令与 system 命令,共同协作完成优化工作。
而关于 Sleep 与 system 命令,我们前面在对三子棋游戏与扫雷游戏(点击跳转)进行优化时,就已经为大家讲解过了,这里就不再做过多的赘述,各位小伙伴们可以通过点击游戏名跳转至我们之前关于这两个命令的讲解部分进行学习。
四、优化版通讯录全部源码🤩:
废话不多说,直接给大家上源码!
①.Contact.h:
#pragma once
//定义宏常量:
#define MAX 1000
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
//引用头文件:
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<Windows.h>
//选项枚举:
enum Option
{
Exit,//值为0
Add,//值为1
Del,//值为2
Search,//值为3
Modify,//值为4
Print//值为5
};
//联系人信息:
typedef struct PeoInfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
//通讯录调用封装:
typedef struct contact
{
PeoInfo data[MAX];
int sz;
}contact;
//函数声明:
void InitContact(contact* p);
void sort(contact* p);
void PrintContact(const contact* p, int x);
void PrintAllContact(const contact* p);
void AddContact(contact* p);
void DelContact(contact* p);
void SearchContact(const contact* p);
void ModifyContact(const contact* p);
②.Contact.c:
#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
//初始化通讯录:
void InitContact(contact* p)
{
assert(p);
p->sz = 0;
memset(p->data, 0, sizeof(p->data));
//使用memeset函数将p->data所指向的空间中的数据初始化为0
//操作的空间大小为sizeof函数所计算出的p->data所指向空间的大小,即整个无联系人数据的结构体数组data所占的空间的大小
}
//字典排序:
void sort(contact* p)
{
int i = 0;
PeoInfo temp;
for (i = 0; i < p->sz; i++)
{
if (strcmp(p->data[i].name, p->data[i + 1].name) > 0)
{
temp = p->data[i + 1];
p->data[i + 1] = p->data[i];
p->data[i] = temp;
}
}
}
//打印联系人信息:
void PrintContact(const contact* p, int x)
{
assert(p);
printf(" 联系人 :%04d\n", x + 1);
printf(" 姓 名 :%s\n", p->data[x].name);
printf(" 性 别 :%s\n", p->data[x].sex);
printf(" 年 龄 :%d\n", p->data[x].age);
printf("联系方式:%s\n", p->data[x].tele);
printf("当前住址:%s\n", p->data[x].addr);
}
//打印全部联系人信息:
void PrintAllContact(const contact* p)
{
assert(p);
printf("联系人 姓名 性别 年龄 联系方式 住址\n");
int i = 0;
for (i = 0; i < p->sz; i++)
{
printf(" %04d %-20s %-5s %-4d %-12s %-30s\n", i + 1, p->data[i].name, p->data[i].sex, p->data[i].age, p->data[i].tele, p->data[i].addr);
}
}
//添加联系人:
void AddContact(contact* p)
{
assert(p);
if (p->sz == MAX)
{
system("cls");
printf("通讯录空间不足,无法添加新成员!\n");
Sleep(1500);
system("cls");
}
else
{
printf("请输入联系人姓名:>");
scanf("%s", p->data[p->sz].name);
printf("请输入联系人性别:>");
scanf("%s", p->data[p->sz].sex);
//对年龄进行合法性检测:
int input = 1;
do
{
printf("请输入联系人年龄:>");
scanf("%d", &(p->data[p->sz].age));
if (0 <= p->data[p->sz].age && p->data[p->sz].age <= 100)
{
input = 0;
}
else
{
Sleep(1000);
system("cls");
printf("您输入的年龄信息有误,请重新输入!\n");
Sleep(1500);
system("cls");
printf("请输入联系人姓名:>%s\n", p->data[p->sz].name);
printf("请输入联系人性别:>%s\n", p->data[p->sz].sex);
}
} while (input);
//对联系方式进行合法性检测:
input = 1;
do
{
input = 0;
//直接让input为0,若出现不合法则改其值为1继续循环
//不符合不合法则跳出循环
printf("请输入联系人联系方式:>");
scanf("%s", p->data[p->sz].tele);
char check1[MAX_TELE] = { 0 };
strcpy(check1, p->data[p->sz].tele);
int i = 0;
int cmp = 0;
//比较变量cmp用于标记各位置上的判断结果
for (i = 0; i < 11; i++)
{
if ('0' <= check1[i] && check1[i] <= '9')
{
cmp = 0;
}
else
{
cmp = 1;
break;
}
}
if (check1[11] == 0)
//下标从零开始,第十二位下标为11
{
;
//若合法则不进行操作,不合法则提示不合法并重新输入
}
else
{
cmp = 1;
}
if (cmp)
{
input = 1;
//不合法继续循环
Sleep(1000);
system("cls");
printf("您输入的联系方式有误,请重新输入!\n");
Sleep(1500);
system("cls");
printf("请输入联系人姓名:>%s\n", p->data[p->sz].name);
printf("请输入联系人性别:>%s\n", p->data[p->sz].sex);
printf("请输入联系人年龄:>%d\n", p->data[p->sz].age);
}
} while (input);
printf("请输入联系人住址:>");
scanf("%s", p->data[p->sz].addr);
Sleep(1000);
system("cls");
printf("****************************\n");
printf("****************************\n");
printf("**** 联系人信息添加成功!***\n");
printf("****************************\n");
printf("****************************\n");
PrintContact(p, p->sz);
sort(p);
p->sz++;
}
}
//删除联系人:
void DelContact(contact* p)
{
assert(p);
int num = 0;
if (p->sz == 0)
{
printf("对不起,当前通讯录中没有联系人信息!\n");
Sleep(1500);
}
else
{
PrintAllContact(p);
printf("请输入您想删除的联系人编号:>");
scanf("%d", &num);
int x = num - 1;
if (0 <= x && x <= p->sz)
{
int j = 0;
for (j = x; j < p->sz; j++)
{
p->data[j] = p->data[j + 1];
p->sz--;
}
Sleep(1000);
system("cls");
printf("**************************\n");
printf("**************************\n");
printf("**** 联系人信息已删除!***\n");
printf("**************************\n");
printf("**************************\n");
PrintAllContact(p);
Sleep(3000);
}
}
}
//查询联系人:
void SearchContact(const contact* p)
{
assert(p);
char name[MAX_NAME] = { 0 };
printf("请输入您想要查询的联系人姓名:>");
scanf("%s", &name);
Sleep(1000);
system("cls");
int i = 0;
int ret = 1;
for (i = 0; i < p->data; i++)
{
if (0 == strcmp(name, p->data[i].name))
{
printf("************************\n");
printf("************************\n");
printf("**** 成功找到联系人!***\n");
printf("************************\n");
printf("************************\n");
PrintContact(p, i);
Sleep(3000);
ret = 0;
break;
}
}
if (ret)
{
printf("************************\n");
printf("************************\n");
printf("**** 未找到该联系人!***\n");
printf("************************\n");
printf("************************\n");
Sleep(1500);
}
}
//修改联系人信息:
void ModifyContact(contact* p)
{
assert(p);
int x = 0;
int input = 0;
int input_cmp = 1;
if (p->sz == 0)
{
printf("对不起,当前通讯录中没有联系人信息!\n");
Sleep(1500);
system("cls");
}
else
{
PrintAllContact(p);
printf("请输入您想要修改的联系人编号:>");
scanf("%d", &x);
Sleep(1000);
system("cls");
do
{
printf("***************************\n");
printf("***************************\n");
PrintContact(p, x - 1);
printf("***************************\n");
printf("当前支持修改的信息:\n");
printf("1.Name\n");
printf("2.Sex\n");
printf("3.Age\n");
printf("4.Tele\n");
printf("5.Addr\n");
printf("请选择您想要修改的信息:>");
scanf("%d", &input);
Sleep(1000);
system("cls");
switch (input)
{
case 1:
printf("***************************\n");
printf("***************************\n");
PrintContact(p, x - 1);
printf("***************************\n");
printf("请更新联系人姓名:");
scanf("%s", p->data[x - 1].name);
Sleep(1000);
system("cls");
printf("**************************\n");
printf("**************************\n");
printf("**** 联系人姓名已修改!***\n");
printf("**************************\n");
printf("**************************\n");
PrintContact(p, x - 1);
Sleep(3000);
system("cls");
input = 0;
break;
case 2:
printf("***************************\n");
printf("***************************\n");
PrintContact(p, x - 1);
printf("***************************\n");
printf("请更新联系人性别:");
scanf("%s", p->data[x - 1].sex);
Sleep(1000);
system("cls");
printf("**************************\n");
printf("**************************\n");
printf("**** 联系人性别已修改!***\n");
printf("**************************\n");
printf("**************************\n");
PrintContact(p, x - 1);
Sleep(3000);
system("cls");
input = 0;
break;
case 3:
do
{
printf("***************************\n");
printf("***************************\n");
PrintContact(p, x - 1);
printf("***************************\n");
printf("请更新联系人年龄:>");
scanf("%d", &(p->data[x - 1].age));
Sleep(1000);
system("cls");
if (0 <= p->data[x - 1].age && p->data[x - 1].age <= 100)
{
input_cmp = 0;
printf("**************************\n");
printf("**************************\n");
printf("**** 联系人年龄已修改!***\n");
printf("**************************\n");
printf("**************************\n");
}
else
{
printf("您输入的年龄信息有误,请重新输入!\n");
Sleep(1500);
system("cls");
}
} while (input_cmp);
PrintContact(p, x - 1);
Sleep(3000);
system("cls");
input = 0;
break;
case 4:
do
{
input_cmp = 0;
//直接让input_cmp为0,若出现不合法则改其值为1继续循环
//不符合不合法则跳出循环
printf("***************************\n");
printf("***************************\n");
PrintContact(p, x - 1);
printf("***************************\n");
printf("请更新联系人联系方式:>");
scanf("%s", p->data[x - 1].tele);
Sleep(1000);
system("cls");
char check1[MAX_TELE] = { 0 };
strcpy(check1, p->data[x - 1].tele);
int i = 0;
int cmp = 0;
//比较变量cmp用于标记各位置上的判断结果
for (i = 0; i < 11; i++)
{
if ('0' <= check1[i] && check1[i] <= '9')
{
cmp = 0;
}
else
{
cmp = 1;
break;
}
}
if (check1[11] == 0)
//下标从零开始,第十二位下标为11
{
;
//若合法则不进行操作,不合法则提示不合法并重新输入
}
else
{
cmp = 1;
}
if (cmp)
{
input_cmp = 1;
//不合法继续循环
printf("您输入的联系方式有误,请重新输入!\n");
Sleep(1500);
system("cls");
}
else
{
printf("******************************\n");
printf("******************************\n");
printf("**** 联系人联系方式已修改!***\n");
printf("******************************\n");
printf("******************************\n");
}
} while (input_cmp);
PrintContact(p, x - 1);
Sleep(3000);
system("cls");
input = 0;
break;
case 5:
printf("***************************\n");
printf("***************************\n");
PrintContact(p, x - 1);
printf("***************************\n");
printf("请更新联系人住址:");
scanf("%s", p->data[x - 1].addr);
Sleep(1000);
system("cls");
printf("**************************\n");
printf("**************************\n");
printf("**** 联系人住址已修改!***\n");
printf("**************************\n");
printf("**************************\n");
PrintContact(p, x - 1);
Sleep(3000);
system("cls");
input = 0;
break;
default:
printf("您的选择有误,请重新选择!\n");
Sleep(1500);
system("cls");
break;
}
}while (input);
}
}
③.test.c:
#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
void menu()
{
printf("**********************************\n");
printf("**********************************\n");
printf("******** 欢迎使用本通讯录 ********\n");
printf("**********************************\n");
printf("***** 本通讯录现提供以下功能 *****\n");
printf("************ 1.Add ***************\n");
printf("************ 2.Del ***************\n");
printf("************ 3.Search ************\n");
printf("************ 4.Modify ************\n");
printf("************ 5.Print *************\n");
printf("************ 0.Exit **************\n");
printf("**********************************\n");
printf("**********************************\n");
}
void Contact()
{
int input = 0;
contact con;
InitContact(&con);
do
{
menu();
printf("请您进行选择:> ");
scanf("%d", &input);
switch (input)
{
case Add:
Sleep(1000);
system("cls");
AddContact(&con);
Sleep(3000);
system("cls");
break;
case Del:
Sleep(1000);
system("cls");
DelContact(&con);
system("cls");
break;
case Search:
Sleep(1000);
system("cls");
SearchContact(&con);
system("cls");
break;
case Modify:
Sleep(1000);
system("cls");
ModifyContact(&con);
Sleep(1000);
system("cls");
break;
case Print:
Sleep(1000);
system("cls");
PrintAllContact(&con);
Sleep(1000);
system("cls");
break;
case Exit:
Sleep(1000);
system("cls");
printf("正在退出!\n");
Sleep(1000);
system("cls");
break;
default:
Sleep(1000);
system("cls");
printf("您的选择有误,请重新选择!\n");
Sleep(1500);
system("cls");
break;
}
} while (input);
}
int main()
{
Contact();
return 0;
}
🥳总结🥳:
至此,我们关于通讯录的优化就全部完成了。不过我们看到我们目前写出来的通讯录仍旧功能简单,各位小伙伴们下去以后可以自行研究,再给它添加上我们需要的各种功能!
🔥🔥坚强并不只是在大是大非中不屈服,而也是在挫折前不改变自己🔥🔥
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!