有任何不懂的问题可以评论区留言,能力范围内都会一一回答
通过学习文件操作,我们可以通过c去打开硬盘上的文件,那么设想,我们能不能去做点好玩的呢,我们是不是可以去做一个电子书模拟器呢?可以显示页数点一下就翻页的哪种呢?听起来还不错,那么我们先做一个简易的再一点一点去优化它。
首先我们要打开读取一个文件,这里我以道德经为例,先做一个简陋的,首先打开文件通过
FILE* pf = fopen("道德经全文.txt", "r");
就可以了,但是一篇文章这么多我们这里取一页为1800字符(终端,也就是屏幕显示大小是可以调节的,这个地方先做一个简单的后面再优化)
但是这里要注意的是我们要确定这个文件是否被打开,因此我们需要一个if语句去判断,并且同时通过perror去把错误的原因打印出来
if (pf == NULL)
{
perror("fopen");
return 1;
}
那么接下来就是将内容打印了,那我们先得把内容取出来,这里我选择的是fgetc这个函数去取,但是这个地方我们就面两个问题,第一个就是我们要确定这个文件是否读到末尾了,因为如果读到末尾了,哪怕屏幕上没有到1800大小你也不能再读了,因此我们的所有打印都要满足
ch = fgetc(pf)) != EOF
也就是没有读到文件末尾,
那么读取到了怎么打印呢,最简单的当然是
printf("%c",ch);
这里由于文章通篇是字符我们也可以用字符和字符串相关函数
putchar(ch);
这个地方两种都可以,接踵而至的是我们怎么确定我有没有读到1800个字符呢,那这个地方最简单的就是用一个变量去计数,同时由于无论是从文件中读内容的函数和打印内容的函数每次都只能处理一个字符,这个地方最简单的就是用while循环了,
while ((ch = fgetc(pf)) != EOF){
putchar( ch);
count++;
if (count == 1800)
......
那么我们思考,当打印了1800字符后就要停下来了,那怎么停下来呢,我们所学过的最简单的就是通过输入也就是
char ah="a";
scanf("c",&ah);
同样
char ah=getchar();
也可以
那么这个地方我们做一个简易版的(只做往后翻页的,往前翻页的后面会再慢慢优化的)
如果读者输入换行键就代表翻页
因此这个地方可以
if (char ah = getchar() == '\n')
进行一个判断
如果输入的是换行我们就要翻页,但是我们要翻页,我们首先要去清空屏幕这一页内容,再输入下一页的内容,首先清空屏幕,我们就要用到一个库函数,也就是
system("cls");
头文件是
#include <stdlib.h>
那再打印下一页内容
这个地方根据我们所学的内容同样有两种方式
第一种就是我们把打印一页作为一个函数,当我们输入换行符也就是翻页的时候,这个函数再调用函数自己,也就是函数递归,将读到函数文件末尾也就是(ch = fgetc(pf)) == EOF)为递归停止条件
当然为了大多数人都可以实现,这个地方我先做一个简单的goto语句去模拟递归,但是要注意,goto语句记得要少用,一旦出错会相当麻烦,
back:
int count = 0;//新的一页从0开始计算字符数
while ((ch = fgetc(pf)) != EOF)//读取文章内容
{
putchar( ch);//打印文章内容
count++;//记录当前屏幕字符数
if (count == 1800)//当前页面内容是否输入完成
{
if (char ah = getchar() == '\n')//判断是否翻页
{
system("cls")//清空屏幕
goto back;
}
}
}
这个方法和函数递归类似,但是一定要记住每次goto语句过去的时候都是打印新的一页,都要将计算字符数量的变量重置成0;
再最后读到文件末尾循环停止,但是不要忘了最后要关闭文件,同时要将指针置为空指针,不然这个时候指针虽然指向文件,但是文件已经关闭,我们无法通过指针找到原来文件所在位置,它就变成了一个野指针,
fclose(pf);
pf == NULL;
野指针很危险,切记一定要将指针至于空指针
当然这个地方有个小技巧,如果程序运行的时候有屏闪,可以用getchar()具体原理本章不做介绍,综上我们做出了一个非常非常简陋的电子书模拟器了。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int count;
int main(void) {
char ch = 0;
FILE* pf = fopen("道德经全文.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
back:
int count = 0;
while ((ch = fgetc(pf)) != EOF){
putchar( ch);
count++;
if (count == 1800) {
if (char ah = getchar() == '\n') {
system("cls");
goto back;
}
}
}
fclose(pf);
pf == NULL;
getchar();
return 0;
}
该程序运行效果在博主主页有,麻烦大家自行观看,那个视频放到文章里面播放效果太差了
以上就是本章所有内容,
那么思考一下如果我要设置一个可以往前翻页的电子书该怎么办呢,这个地方同样提供给大家两种思路,有兴趣的可以试试看能否实现,当然同样再后面的优化中我也会再单独出几期
第一个思路就是既然翻页,我为什么不能每一页的起始位置放一个指针,做成一个指针数组(比如char*arr[100]),将每一页的地址记录到里面,往前或者往后翻一页就通过arr[i],通过i的递增或者 递减调节fgetc()的开始的位置(也就是读取内容的位置)
当然这个地方肯会遇到i是局部变量这个地方循环判断多容易被清0也可以static int i;
给i添加内部链接属性会让我们编写起来会简单很多
第二个思路就很有以上了,就是通过fseek函数去改变读取文件光标的位置(也就是偏移量)
比如fseek(pf, 1800, SEEK_CUR);光标像后移动1800字符从下一页的相同的位置开始读取打印,
或者fseek(pf, -1800, SEEK_CUR);光标像前移动1800字符从上一页的相同的位置开始读取打印
但是不要忘了这种偏移是否会超出文章范围,这个地方可以用库函数assert去判断,,它的头文件是 #include<assert.h>
欢迎大家在评论区指正或分享讨论 下期见喽!!!