这是一个大一上学期期末的c语言课程实践作业,比较简单,用到的都是基础知识。
首先看题目:
题目3:通讯录程序设计
设计一个实用的小型通讯录程序,具有添加,查询和删除功能。由姓名,籍贯,电话号码1,电话号码2,电子邮箱组成,姓名可以由字符和数字混合编码。电话号码可由字符和数字组成。(用文件保存)实现功能:
(1)信息录入功能
(2)信息浏览功能
(3)信息查询功能
(4)信息修改功能
确定选题之后,我做的第一步是分析题目要求:
要求:
添加
因为要录入的信息是str和int混合的,所以我决定使用结构体数组来储存信息。
为了更人性化的设计,我想到了新建联系人列表和添加联系人(后期才想到的)
删除
因为是结构体数组,思路是先定位要删除的人,再用后面的数据直接覆盖,跟普通数组一样
查询
利用字符串的对比,遍历所有数据
其次,将录入或者修改的信息用二进制文件保存
思路:录入数据:先输入数据——>打开文件——>写入数据——>保存(关闭文件)
修改数据(增,删,查,找):打开文件——>读取数据——>关闭文件——>修改数据——>打开文件——>写入数据——>保存(关闭文件)
ok,这个程序的总体思路就是这样,多次重复使用的部分用函数封装,最后各部分代码如下:
part1:
根据题目要求储存的信息定义结构体数组
struct phonebook
{
char name[20];//用户姓名
char origin[20];//籍贯
char num1[12];//电话号码1
char num2[12];//电话号码2
char email[20];//邮箱
};
part2:
主函数如下:
int main()
{
void meanu();
int new_info(phonebook * p);
void save(phonebook * p, int num);
void readput(phonebook * p);
void del_info(phonebook * p,int num);
int doc_long(phonebook * p);
void read(phonebook * p, int n);
void output(phonebook * p, int num);
void search(phonebook * p, int num);
void modify(phonebook * p, int num);
int add_info(phonebook * p, int num);
void clear();
phonebook phone[100];
phonebook* p;
int n = 0;
int doc_num = 0;
int c, add_times = 0;
p = phone;
meanu();
scanf_s("%d", &c);
switch (c)
{
case 1:n =new_info(p); save(p,n); break;
case 2:doc_num = doc_long(p); read(p, doc_num); del_info(phone, doc_num);save(p, doc_num-1); break;
case 3:doc_num = doc_long(p); read(p, doc_num); output(p, doc_num); break;
case 4:doc_num = doc_long(p); read(p, doc_num); search(p,doc_num); break;
case 5:doc_num = doc_long(p); read(p, doc_num); modify(p, doc_num); save(p, doc_num); break;
case 6:doc_num = doc_long(p); read(p, doc_num); n = add_info(p, doc_num); save(p,n); break;
case 7:clear(); break;
case 8:break; break;
}
}
part3:
各个子函数如下:
meanu(菜单):
/*
功能:显示菜单
返回值 无
*/
void meanu()
{
printf("*******************************************************通讯录菜单*******************************************************\n");
printf(" 1:新建通讯录 ");
printf("2:删除联系人信息\n");
printf(" 3:浏览联系人信息 ");
printf("4:查询联系人信息\n");
printf(" 5:修改联系人信息 ");
printf("6:添加联系人信息\n");
printf(" 7:清空通讯录 ");
printf("8:退出系统\n");
}
new_info
/*
功能:输入联系人信息
参数 p:结构体数组指针
返回值 输入信息条数
*/
int new_info(phonebook *p)
{
int n;
char name[20];
n = 0;
printf("新建通讯录:\n");
printf("请输入姓名:");
getchar();#吸收换行符号(否则换行符会被gets_s吸收)
gets_s(p->name);
strcpy(name, p->name);
if (strcmp(name, "stop") != 0)//控制程序的结束
{
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
n++;
p++;
}
while (strcmp(name, "stop") != 0)//首次输入姓名时不为stop,第二次输入执行这行
{
printf("请输入姓名:");
gets_s(p->name);
strcpy(name, p->name);
if (strcmp(name, "stop") == 0)
break;
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
n++;
p++;//指针自增,指向下一条数据
}
return n;//记录输入数据的条数,并且返回,后续配合
}
save函数:保存数据
/*
功能 :保存数据
参数:p:结构体数组指针
num:要保存的数据的条数
*/
void save(phonebook* p,int num)
{
FILE* fp;
fp = fopen("phonebook_data", "wb");//生成新文件
fwrite(p, sizeof(phonebook), num, fp);//写文件
fclose(fp);//关闭文件
}
接收new_info返回的数据条数,并且保存数据,
new_info和save配合使用即可输入并且保存数据(实现菜单中的第一个功能)
case 1:n =new_info(p); save(p,n); break;
doc_long(获取文件中数据的条数)
/*
功能 :获取文件中数据条数
参数:p:结构体数组指针
返回值 文件中数据条数
*/
int doc_long(phonebook* p)
{
FILE* fp;
int doc_num = 0;
fp = fopen("phonebook_data", "rb");
while (1)
{
fread(p, sizeof(phonebook), 1, fp);
if (feof(fp))
break;
doc_num++;
}
fclose(fp);
return doc_num;
}
由于本人才疏学浅,学识有限,只能做到执行一次程序只使用一个功能,所以我要读取之前保存的数据的时候会遇到一个尴尬的问题:无法知道文件中数据的条数,所以doc_long这个函数应运而生。
在获得了数据的条数之后,便可以读取数据:
read
/*
功能 :读取文件
参数:p:结构体数组指针
num:要读取数据的条数
*/
void read(phonebook* p, int num)
{
FILE* fp;
fp = fopen("phonebook_data", "rb");
fread(p, sizeof(phonebook), num, fp);
fclose(fp);
}
由此第二个功能,删除联系人即可实现
del_info
/*
功能 :删除指定联系人数据
参数:p:结构体数组指针
num:数据条数
*/
void del_info(phonebook* p,int num)
{
int success = 0;//判断是否删除成功
phonebook phone[100];
char del_name[20];
int n = 0;//用来遍历数组
int c = 0;//获取索引值
printf("删除联系人信息\n");
printf("请输入你要删除的名字:");
getchar();
gets_s(del_name);
for (n; n < num; n++)//遍历结构体数组
{
if (strcmp(del_name, p->name) == 0)
{
c = n;
for (c; c < num+2; c++)
{
*(p) = *(p+1);//覆盖要删除的信息
p++;
}
printf("删除%s的信息成功\n", del_name);
success = 1;
}
p++;
}
if (success != 1)
{
printf("抱歉,没有找到%s\n", del_name);
}
}
output:输出联系人信息
/*
功能 :输出联系人信息
参数:p:结构体数组指针
num:要输出的数据的条数
*/
void output(phonebook* p, int num)
{
if (num == 0)
{
printf("通讯录为空,请先新建通讯录");
}
for (int a = 0; a < num; a++)
{
printf("姓名:%s\n", p->name);
printf("籍贯:%s\n", p->origin);
printf("号码1:%s\n", p->num1);
printf("号码2:%s\n", p->num2);
printf("邮箱:%s\n", p->email);
printf("\n");
p++;
}
}
写这个功能的时候我遇到一个问题,就是无论我文件里面有几条数据,我只能输出第一位联系人的信息,后来我发现是因为我的指针没有自增,因此,指针的自增是非常重要的
doc_num = doc_long(p); read(p, doc_num); output(p, doc_num); break;
配合doc_long read两个函数,可以轻松实现输出联系人的功能
search:查找某一人的信息
void search(phonebook* p, int num)
{
printf("查询联系人信息\n");
printf("请输入姓名以搜索:");
char name[20];
int success = 0;
getchar();
gets_s(name);
for (int i = 0; i < num; i++)
{
if (strcmp(name, p->name) == 0)
{
printf("查询到的联系人信息如下:\n");
printf("姓名:%s\n", p->name);
printf("籍贯:%s\n", p->origin);
printf("号码1:%s\n", p->num1);
printf("号码2:%s\n", p->num2);
printf("邮箱:%s\n", p->email);
printf("\n");
success = 1;
}
p++;
}
if (success != 1)
{
printf("抱歉,没有找到该联系人\n");
}
}
方法跟删除联系人的时候是一样的,我直接照搬上面的代码,再稍微修改一下
modify:修改联系人信息
/*
功能 :修改联系人信息
参数:p:结构体数组指针
num:联系人数目
*/
void modify(phonebook* p, int num)
{
printf("修改联系人信息\n");
printf("请输入要修改的名字:");
char name[20];
int success = 0;//判断是否修改成功
getchar();
gets_s(name);
for (int i = 0; i < num; i++)
{
if (strcmp(name, p->name) == 0)
{
printf("请输入姓名:");
gets_s(p->name);
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
printf("\n");
success = 1;
printf("修改成功\n");
}
p++;
}
if (success != 1)
{
printf("抱歉,没有找到该联系人\n");
}
}
add_info:增加联系人信息
/*
功能 :添加联系人信息
参数:p:结构体数组指针
num:原有的联系人数量
返回值:添加完后总共的联系人数量
*/
int add_info(phonebook* p, int num)
{
int c = 0;
int n;
char name[20];
n = 0;
while (c < num)
{
c++;
p++;
}
printf("请输入姓名:");
getchar();
gets_s(p->name);
strcpy(name, p->name);
if (strcmp(name, "stop") != 0)
{
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
n++;
p++;
}
while (strcmp(name, "stop") != 0)
{
printf("请输入姓名:");
gets_s(p->name);//
strcpy(name, p->name);
if (strcmp(name, "stop") == 0)
break;
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
n++;
p++;
}
n = n + num;
return n;//返回添加完成后的联系人数目
}
此功能一开始写的时候是比较棘手的,没啥头绪,卡了我比较久的一个功能。后来一想,也没有那么难
思路:先把指针移动到当前数组的最后,再在数组的末尾添加数据就好了
clear:清空通讯录
/*
功能 :清空通讯录
*/
void clear()
{
int sure;
printf("你确定要清空通讯录吗?\n");
printf("确认请输入1\n取消请输入0\n");
scanf_s("%d", &sure);
if (sure == 1)
{
FILE* fp;
fp = fopen("phonebook_data", "w");
fclose(fp);
printf("清空成功");
}
if (sure== 0)
printf("已取消");
}
最后附上我的完整程序:
#include
struct phonebook
{
char name[20];
char origin[20];
char num1[12];
char num2[12];
char email[20];
};
int main()
{
void meanu();
int new_info(phonebook * p);
void save(phonebook * p, int num);
void readput(phonebook * p);
void del_info(phonebook * p,int num);
int doc_long(phonebook * p);
void read(phonebook * p, int n);
void output(phonebook * p, int num);
void search(phonebook * p, int num);
void modify(phonebook * p, int num);
int add_info(phonebook * p, int num);
void clear();
phonebook phone[100];
phonebook* p;
int n = 0;
int doc_num = 0;
int c, add_times = 0;
p = phone;
meanu();
scanf_s("%d", &c);
switch (c)
{
case 1:n =new_info(p); save(p,n); break;
case 2:doc_num = doc_long(p); read(p, doc_num); del_info(phone, doc_num);save(p, doc_num-1); break;
case 3:doc_num = doc_long(p); read(p, doc_num); output(p, doc_num); break;
case 4:doc_num = doc_long(p); read(p, doc_num); search(p,doc_num); break;
case 5:doc_num = doc_long(p); read(p, doc_num); modify(p, doc_num); save(p, doc_num); break;
case 6:doc_num = doc_long(p); read(p, doc_num); n = add_info(p, doc_num); save(p,n); break;
case 7:clear(); break;
case 8:break; break;
}
}
/*
功能:显示菜单
返回值 无
*/
void meanu()
{
printf("*******************************************************通讯录菜单*******************************************************\n");
printf(" 1:新建通讯录 ");
printf("2:删除联系人信息\n");
printf(" 3:浏览联系人信息 ");
printf("4:查询联系人信息\n");
printf(" 5:修改联系人信息 ");
printf("6:添加联系人信息\n");
printf(" 7:清空通讯录 ");
printf("8:退出系统\n");
}
/*
功能:输入联系人信息
参数 p:结构体数组指针
返回值 输入信息条数
*/
int new_info(phonebook *p)
{
int n;
char name[20];
n = 0;
printf("新建通讯录:\n");
printf("请输入姓名:");
getchar();
gets_s(p->name);
strcpy(name, p->name);
if (strcmp(name, "stop") != 0)
{
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
n++;
p++;
}
while (strcmp(name, "stop") != 0)
{
printf("请输入姓名:");
gets_s(p->name);//
strcpy(name, p->name);
if (strcmp(name, "stop") == 0)
break;
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
n++;
p++;
}
return n;
}
/*
功能 :保存数据
参数:p:结构体数组指针
num:要保存的数据的条数
*/
void save(phonebook* p,int num)
{
FILE* fp;
fp = fopen("phonebook_data", "wb");//生成新文件
fwrite(p, sizeof(phonebook), num, fp);//写文件
fclose(fp);//关闭文件
}
/*
功能 :删除指定联系人数据
参数:p:结构体数组指针
num:数据条数
*/
void del_info(phonebook* p,int num)
{
int success = 0;
phonebook phone[100];
char del_name[20];
int n = 0;
int c = 0;
printf("删除联系人信息\n");
printf("请输入你要删除的名字:");
getchar();
gets_s(del_name);
for (n; n < num; n++)//遍历结构体数组
{
if (strcmp(del_name, p->name) == 0)
{
c = n;
for (c; c < num+2; c++)
{
*(p) = *(p+1);
p++;
}
printf("删除%s的信息成功\n", del_name);
success = 1;
}
p++;
}
if (success != 1)
{
printf("抱歉,没有找到%s\n", del_name);
}
}
/*
功能 :获取文件中数据条数
参数:p:结构体数组指针
返回值 文件中数据条数
*/
int doc_long(phonebook* p)
{
FILE* fp;
int doc_num = 0;
fp = fopen("phonebook_data", "rb");
while (1)
{
fread(p, sizeof(phonebook), 1, fp);
if (feof(fp))
break;
doc_num++;
}
fclose(fp);
return doc_num;
}
/*
功能 :读取文件
参数:p:结构体数组指针
num:要读取数据的条数
*/
void read(phonebook* p, int num)
{
FILE* fp;
fp = fopen("phonebook_data", "rb");
fread(p, sizeof(phonebook), num, fp);
fclose(fp);
}
/*
功能 :输出联系人信息
参数:p:结构体数组指针
num:要输出的数据的条数
*/
void output(phonebook* p, int num)
{
if (num == 0)
{
printf("通讯录为空,请先新建通讯录");
}
for (int a = 0; a < num; a++)
{
printf("姓名:%s\n", p->name);
printf("籍贯:%s\n", p->origin);
printf("号码1:%s\n", p->num1);
printf("号码2:%s\n", p->num2);
printf("邮箱:%s\n", p->email);
printf("\n");
p++;
}
}
/*
功能 :搜索联系人信息
参数:p:结构体数组指针
num:联系人数目
*/
void search(phonebook* p, int num)
{
printf("查询联系人信息\n");
printf("请输入姓名以搜索:");
char name[20];
int success = 0;
getchar();
gets_s(name);
for (int i = 0; i < num; i++)
{
if (strcmp(name, p->name) == 0)
{
printf("查询到的联系人信息如下:\n");
printf("姓名:%s\n", p->name);
printf("籍贯:%s\n", p->origin);
printf("号码1:%s\n", p->num1);
printf("号码2:%s\n", p->num2);
printf("邮箱:%s\n", p->email);
printf("\n");
success = 1;
}
p++;
}
if (success != 1)
{
printf("抱歉,没有找到该联系人\n");
}
}
/*
功能 :修改联系人信息
参数:p:结构体数组指针
num:联系人数目
*/
void modify(phonebook* p, int num)
{
printf("修改联系人信息\n");
printf("请输入要修改的名字:");
char name[20];
int success = 0;//判断是否修改成功
getchar();
gets_s(name);
for (int i = 0; i < num; i++)
{
if (strcmp(name, p->name) == 0)
{
printf("请输入姓名:");
gets_s(p->name);
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
printf("\n");
success = 1;
printf("修改成功\n");
}
p++;
}
if (success != 1)
{
printf("抱歉,没有找到该联系人\n");
}
}
/*
功能 :添加联系人信息
参数:p:结构体数组指针
num:原有的联系人数量
返回值:添加完后总共的联系人数量
*/
int add_info(phonebook* p, int num)
{
int c = 0;
int n;
char name[20];
n = 0;
while (c < num)
{
c++;
p++;
}
printf("请输入姓名:");
getchar();
gets_s(p->name);
strcpy(name, p->name);
if (strcmp(name, "stop") != 0)
{
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
n++;
p++;
}
while (strcmp(name, "stop") != 0)
{
printf("请输入姓名:");
gets_s(p->name);//
strcpy(name, p->name);
if (strcmp(name, "stop") == 0)
break;
printf("请输入籍贯:");
gets_s(p->origin);
printf("请输入电话号码1:");
gets_s(p->num1);
printf("请输入电话号码2:");
gets_s(p->num2);
printf("请输入电子邮箱:");
gets_s(p->email);
n++;
p++;
}
n = n + num;
return n;//返回添加完成后的联系人数目
}
/*
功能 :清空通讯录
*/
void clear()
{
int sure;
printf("你确定要清空通讯录吗?\n");
printf("确认请输入1\n取消请输入0\n");
scanf_s("%d", &sure);
if (sure == 1)
{
FILE* fp;
fp = fopen("phonebook_data", "w");
fclose(fp);
printf("清空成功");
}
if (sure== 0)
printf("已取消");
}
总结:整个作业写下来,并不是一帆风顺的,文章开头提到的那些思路也不是从一开始就想到的,是在不断写程序的过程中总结出来的,怎样写方便,怎样写简单,都是慢慢摸索的,有一种船到桥头自然直的感觉,使我这次实践受益匪浅。
以上就是一位c语言初学者的一份期末作业,希望分享给和我一样的初学者一起交流,如果有什么改进方案或者错误的地方·,请务必私信我,谢谢