制作一个影片管理系统,要求输入定义一个结构体,表示影片信息:编号,片名,导演,片长。
同时需要将所有功能封装成单独的函数体,还需要进行文件操作,即使用fprintf和fscanf对文件进行读和写,并且可以永久保存信息在文件中,再次运行程序,自动加载上一次保存的信息,并且接着上次的写入。
咋一看,虽然功能很简单,但是对于初学者而言比如我,就很复杂。
仔细一看,真是甄姬拆围栏,甄姬拔栏!
回归正题,看看我是如何操作的吧。首先我们的有一个整体思路,既然要将所有功能都封装成函数,那么在主函数里面我们只需要写一个函数将需要的函数进行调用就行了,大体框架就是从菜单入手,先让用户做出选择,然后在选择里对不同的功能函数进行调用。
说道这里就要使用swtich函数了,有的人更喜欢用if else条件判断,但是我个人偏爱switch,我觉得这个函数很清晰明了,比较直观,会让程序有更好的可读性。
框架搭建好了,就要往里面塞函数了。先一步步来。
哦对了,在这最之前,当然要先定义我们的结构体函数了
struct mv
{
int num; //num为影片编号
char m_name[32]; //影片名
char p_name[32]; //导演名字
int time; //影片时长
};
结构体定义完后我们开始写下面的函数功能,在函数功能之前需要先定义一个结构体数组。用来保存数据,把一些准备工作都放在main函数里面。
#include<stdio.h>
#define N 5
int main()
{
struct mv s[N];
int x,y=0;
int sel; //选择
int flag=1; //控制while循环
int count=0; //影片数量
while(flag)
{
printf("请输入你的选择:\n");
printf("————————————————————————————————————————————\n");
printf(" 1 ====================>添加电影\n");
printf(" 2 ====================>删除电影\n");
printf(" 3 ====================>修改电影\n");
printf(" 4 ====================>查找电影\n");
printf(" 5 ====================>显示所有电影\n");
printf(" 6 ====================>退出 \n");
printf("————————————————————————————————————————————\n");
scanf("%d",&sel);
while(getchar()!='\n');
switch(sel)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
flag=0;
break;
default:
printf("输入有误,请重新输入\n");
break;
}
}
return 0;
}
这个就是整体框架了,我们接下来就是往里面填充函数了,每个功能对应每一个case;
不知道从何下手的话我们可以根据题目的菜单来,第一步先添加影片信息,那么我们第一个函数可以写一个影片添加函数。
void add_mv(struct mv s[],int *pcount) //*pcount 用地址传参,可以改变实参的值
{
struct mv t[N]; //设置一个临时;变量来接收输入的信息
int flag;
int i=0;
int num=1000+*pcount; //每次加载数据读取文件中的个数并追加
if(*pcount>N) //当输入的电影数量大于规定的数组最大值时,退出程序
{
printf("内存已满\n");
return ;
}
printf("请输入需要添加的电影数:\n");
scanf("%d",&flag);
while(getchar()!='\n'); //用来清空scanf输入的缓存
while(i<flag)
{
t[i].num=num;
num++; //每次添加,编号自动增加
printf("请输入电影名字:\n");
scanf("%s",t[i].m_name);
while(getchar()!='\n');
printf("请输入导演名字:\n");
scanf("%s",t[i].p_name);
while(getchar()!='\n');
printf("请输入电影时长:\n");
scanf("%d",&t[i].time);
while(getchar()!='\n');
s[*pcount]=t[i]; //将临时变量的值赋给实参数组
(*pcount)++;
i++;
}
printf("电影添加成功\n");
}
这个函数其实很好理解,首先使用地址传参,在main函数里定义的count变量为了记录影片数量,num其实是可以随便设置一个数值的,因为他是用来记录影片编号的,后面为什么加*pcount?
问的好,这是一个伏笔,在后面进行文件的读写操作时,文件会记录存入的影片信息以及个数,count本来就是记录个数的,这里*pcount指向的就是count,也就是说,每次重新加载文件,他都会从文件里的最后一个信息后面开始添加,如果文件里没有信息,那么就是从1000开始,当然你也可以设置从0开始。每次添加完后记录count的数值。这里的难点主要就是控制下标。好了,我们继续,下一个函数删除函数,在定义删除函数之前我们先定义一个显示函数,为了方便我们边做边验证。
显示函数很简单,我这里就不做过多赘述了,就是用循环遍历数组每个元素然后打印就可以了。咱直接看代码。
void show_mv(struct mv s[],int count) //按照count的数量来遍历数组并打印
{
printf("电影信息如下所示:\n");
printf("电影编号\t电影名称\t导演\t\t时长\n");
for(int i=0;i<count;i++)
{
printf("%d\t\t%s\t\t%s\t\t%d\n",s[i].num,s[i].m_name,\
s[i].p_name,s[i].time);
}
}
看吧,很简单吧。在printf函数里面有个“ \ ”是用来做换行用的,有时候代码太长屏幕显示不下就可以用这个,表示接着上面的代码。
接下来是删除,不,接下来是查找函数,为什么呢?你想啊,你怎么删除一个影片信息,首先你是不是得通过编号删除,通过比较两个编号来查询到这个影片的所有信息,然后再进行删除。所以我们得先写一个查找函数。
int find_mv_list(struct mv s[],int count ,int num)
{
for(int i=0;i<count;i++) //查找成功返回对应的下标,查找失败则返回-1
{
if(s[i].num==num)
{
return i;
}
}
return -1;
}
这个是函数其实也很简单,相信大家都看得懂。
现在可以写删除函数了,代码如下所示。
void del_mv(struct mv s[],int *pcount) //删除影片
{
int num;
int index;
printf("请输入需要删除的编号\n");
scanf("%d",&num);
while(getchar()!='\n');
index=find_mv_list(s,*pcount,num);
if(index<0)
{
printf("删除失败,编号不存在\n");
return ;
}
for(int i=index+1;i<*pcount;i++)
{
s[i-1]=s[i];
s[i-1].num-=1; //删除信息时编号也自动减1,防止编号重复
}
(*pcount)--;
return ;
}
相信聪明的小伙伴已经看到了查找函数的作用了,index用来接收查找的值,如果查找成功则返回下标,如果失败,则返回-1,然后再通过判断来确定是不是要继续执行。如果是查找成功,那么我们就要进行删除操作,删除的原理很简单,对于大多数人来说简直是张飞吃豆芽——小菜一碟。
就是通过后一位覆盖前面一位,从我们需要删除的位置开始覆盖,覆盖到什么时候结束呢,当然是最大影片数。
s[i-1].num-=1;
这个其实也是为了文件操作做的铺垫,如果不用文件操作的可以将他删除以及上面添加函数中的num=1000+*pcount中的*pcount。
每次删除结束后,我们的影片总数都会少1,所以(*pcount)自减1。
再下面就是查询影片信息了,这个就更简单了,直接看代码。
void find_mv(struct mv s[],int count)
{
int num;
int index;
printf("请输入要查找的编号:\n");
scanf("%d",&num);
while(getchar()!='\n');
index=find_mv_list(s,count,num);
if(index<0)
{
printf("编号为%d的影片不存在\n",num);
}
else
{
printf("编号%d影片信息如下:\n",num);
printf("%s\t%s\t%d\n",s[index].m_name,s[index].p_name,s[index].time);
}
return ;
}
最后一个应该就是修改影片信息了。先看代码再看解释。
void mod_mv(struct mv s[],int count)
{
int num;
int index;
int sel;
int flag=1;
printf("请输入需要修改的编号\n");
scanf("%d",&num);
while(getchar()!='\n');
index=find_mv_list(s,count,num); //读取成功则将下标传送过来
if(index<0)
{
printf("修改失败,编号不存在\n");
return ;
}
printf("请输入需要修改的信息\n");
while(flag)
{
printf("1、电影名称\n2、导演\n3、时长\n0、退出\n");
scanf("%d",&sel);
while(getchar()!='\n');
switch(sel)
{
case 1:
printf("请输入新的电影名字\n");
scanf("%s",s[index].m_name);
while(getchar()!='\n');
printf("修改成功\n");
break;
case 2:
printf("请输入新的导演名字\n");
scanf("%s",s[index].p_name);
while(getchar()!='\n');
printf("修改成功\n");
break;
case 3:
printf("请输入新的电影时长\n");
scanf("%d",&s[index].time);
while(getchar()!='\n');
printf("修改成功\n");
break;
case 0:
flag=0;
break;
default :
printf("输入错误,请重新输入\n");
break;
}
}
return ;
其实修改也简单,看着长是因为我做了一个二级菜单,可以实现根据编号只修改电影名字或者导演名字或者时长,又或者都修改。当然这里又体现了查找函数的重要性。这里你也可以直接写一个函数通过编号全部修改,那样更简单。
芜湖,手都写酸了,改结束了吧,不对,还有文件操作没写!
要实现文件的写和读其实很简单,可以用fwrite和fread函数,不过这个显示的是二进制文本,我选择fprintf和fscanf,这个可以显示文本信息还是比较好用的。
首先我们要了解如何操作读和写,开始我们得打开文件然后进行读或者写操作,最后再关闭文件。就是这么简单。但是要想实现信息永久保存那么我们就要在程序开头进行读,在结尾进行写并保存文件。而且在下次运行时还要接着文件中的内容进行操作,其实上面添加函数中我也提到了,主要就是将读到的文件赋值给添加函数中的结构指针,然后进行操作。其实说白了就是保存和读取的操作。废话不说直接献上代码;
int f_printf(struct mv s[],int count) //写入文件
{
FILE *fp=NULL;
int ret;
fp=fopen("./mv.txt","w");
if(fp==NULL) //判断文件是否打开
{
perror("fopen"); //没打开的原因
return -1;
}
for(int i=0;i<count;i++) //循环写入
{
ret=fprintf(fp,"%d\t%s\t%s\t%d\n",s[i].num,\
s[i].m_name,s[i].p_name,s[i].time);
if(ret<0)
{
perror("fprintf");
fclose(fp);
return -1;
}
}
fclose(fp); //关闭文件
return 0;
}
int f_scanf(struct mv s[],int count)
{
FILE *fp=NULL;
int ret;
struct mv *temp=s; //加载之前的文件
int i=0;
fp=fopen("./mv.txt","r");
if(fp==NULL)
{
perror("fopen");
return -1;
}
while(1)
{
ret=fscanf(fp,"%d%s%s%d",&temp[i].num,temp[i].m_name,\
temp[i].p_name,&temp[i].time);
if(ret==EOF)
{
break;
}
i++;
}
fclose(fp);
for(int j=0;j<i;j++)
{
printf("%d\t%s\t%s\t%d\n",s[j].num,s[j].m_name,\
s[j].p_name,s[j].time);
}
return i; //返回影片个数
}
这两个函数都要进行打开文件,读文件或者写文件,最后关闭文件。你要问我为什么,我只能告诉你规定的,谁规定的?那我就不知道了。
到这里基本上就结束了最后就差把函数都加入到主函数main里面了,当然还要注意,fprintf和fscanf的位置。代码如下
int main()
{
struct mv s[N];
int x,y=0;
int sel; //选择
int flag=1; //控制while循环
int count=0; //影片数量
count=f_scanf(s,count); //输入开始加载文件,并且返回影片个数
while(flag)
{
printf("请输入你的选择:\n");
printf("————————————————————————————————————————————\n");
printf(" 1 ====================>添加电影\n");
printf(" 2 ====================>删除电影\n");
printf(" 3 ====================>修改电影\n");
printf(" 4 ====================>查找电影\n");
printf(" 5 ====================>显示所有电影\n");
printf(" 6 ====================>退出 \n");
printf("————————————————————————————————————————————\n");
scanf("%d",&sel);
while(getchar()!='\n');
switch(sel)
{
case 1:
add_mv(s,&count); //添加
break;
case 2:
del_mv(s,&count); //删除
break;
case 3:
mod_mv(s,count); //修改
break;
case 4:
find_mv(s,count); //查询
break;
case 5:
show_mv(s,count); //展示所以信息
break;
case 6:
flag=0;
f_printf(s,count); //输入结束,保存文件
break;
default:
printf("输入有误,请重新输入\n");
break;
}
}
return 0;
}
代码可自取,最后是代码的运行结果。
首先是空的
然后随便添加两部电影
显示一下
接下来退出程序再进
之前添加的电影信息依旧存在,接下来我们删除试试
好了,到此结束,感谢观看!