各位看官们,大家好,上一回中咱们说的是DIY less命令的例子,这一回咱们继续说该例子。闲话休提,言归正转。让我们一起talk C栗子吧!
看官们,我们在上一回中提到了让文件流回退的方法,不过没有详细说明使用什么方法,这一回中我们将详细介绍这种方法。
我当时想到了两种方法,它们分别是缓冲法和跳跃法。这时有看官睁大了眼睛在看我,我估计这位看官是不明白这些方法,而且连方法的名字也没有听过。我想说,这不能怪这位看官,因为这些方法的名字是我起的,正所谓不知者无罪嘛。好了,不说这些无用的了,我们抓紧时间介绍这些方法吧。
1.缓冲法
首先定义一个数组,数组中的每个元素存放文件中一整行的内容,数组的下标就是文件中的行数,如果想看文件中某一行中的内容,只需要找数组下标就可以。比如,我们想让文件的内容回退一行,那么只需要把数组的下标减一,然后查看与下标匹配的内容就可以。
该方法中使用了数组来作为缓冲,因此我给它起名为缓冲法。不过该方法有个缺点,不知道有没有看官发现呢?估计,我自创的这东西,大家可能还是不习惯,那么我来告诉大家。该方法的性能不够好,或者直接点说,它会占用很大的内存空间。因为我需要定义一个很大的数组才能存放文件中的内容,这显然是很浪费内存空间的。鉴于这个原因,我没有采用该方法。如果哪位看官感兴趣,可以使用这个思路,自己动手实现一下。我就不通过代码演示了。
2.跳跃法
我们首先跳转到文件头,跳转时使用fsetpos函数
就可以,我们在前面章回中介绍过,相信各位看官还记得,不过该函数需要一个关于文件流位置的参数,而且该位置是文件头的位置。大家还记得,我们在读取文件内容的时候留下的悬念吗?现在该是解释这个悬念的时候了:
我们当时在打开文件后,读取文件内容前使用fgetpos函数
获取了文件头的位置,现在正好派上用场了。跳转到文件头后,我们再向前移动x行,这个x行到底是多少行?我们有个计算公式x=y-1
;完了,这回是彻底的完了,x还没有计算出来,又来了个y。y是什么呢?大家还记得上一回中我们介绍如何响应j命令时提到的变量back_count吗?它是用来统计j命令运行的次数。这里的y就等于back_count的值。为什么它们的值是相等的呢?该方法的难点就在这里,大家一下子想不到是正常的,接下来我们通过画图的方法
来给大家演示其中的原理:
[窗口A]
---------------------------------------------------------------
|1.
|2.
|3.
|...
|11.
---------------------------------------------------------------
我们假设上面的图形是一个终端窗口,在该窗口中使用less命令打开文件,该窗口中显示了文件第1行到第11行的内容。这个时候back_count的值为0,我们执行j命令后文件向下滚动一行,back_count的值增加1,也就是y的值增加1。我们这里的终端窗口如下所示:
[窗口B]
---------------------------------------------------------------
|2.
|3.
|4.
|...
|12.
----------------------------------------------------------------
这个时候如果我们运行k命令时,它又会回复到窗口A的样子,那么依据公式:x=y-1
可以得到x的值为0,也就文件头。当然了,有客官会问:当y等于0,也就是在窗口A中执行k命令会是什么样子?它不会有变化的,因为已经是文件头了。不过,有一点需要注意,如果一直执行j命令到达文件末尾后,会自动结束less命令,回到DIY的shell中。
看官们,在该方法中大家要把握一个不变的东西,那就是窗口的大小。我们可以这样想,文件的行数是固定的,我们在文件上使用了一个固定大小的窗口来显示文件中的内容,执行j和k命令相当于是在滑动窗口。在这个思想的基础上,理解我自创的跳跃法会更加容易一些。思路介绍过了,图形也演示过了,接下来我们展示该方法的核心代码,在代码面前所有的一切将会显现在你眼前:
else if(cmd == 'k')
{
back_count -= 1; // reduce the count of k cmd
current_line = 0;
//go back to the beaging of file,and then go to the new location for k cmd
fsetpos(fp,&begin_pos);
while(current_line++ < back_count)
{
fgets(buf,PATH_SIZE,fp);
}
//get the right location of k cmd, and then set this location
fgetpos(fp,&pos);
fsetpos(fp,&pos);
current_line = 0; // it is used as temp, must keek to 0
}
各位看官,关于DIY less命令的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。