more命令的基本实现

#include <stdio.h>
#include <stdlib.h>
#define PAGELEN 24
#define LINELEN 512

void do_more(FILE*);
int see_more();

int main(int ac, char* av[]) {
	FILE* fp;
	if (ac == 1) do_more(stdin);
	else {
                /*若有多个参数,则可以打印对应文件的内容*/
		while (--ac) {
			if ((fp = fopen(*++av, "r")) != NULL) {
				do_more(fp);
				fclose(fp);
			} else {
				exit(1);
			}	
		}
	}
	return 0;
}

void do_more(FILE* fp) {
	char line[LINELEN];
	int num_of_lines = 0;
	int see_more(), reply;
	
	while (fgets(line, LINELEN, fp)) {
		if (num_of_lines == PAGELEN) {
			reply = see_more();
			if (reply == 0) break;
			num_of_lines -= reply;
		}
		if (fputs(line, stdout) == EOF) exit(1);
		num_of_lines++;
	}
}

int see_more() {
	int c;
	printf("\033[7m more?\033[m");
	while ((c=getchar()) != EOF) {
		if (c == 'q') return 0;
		if (c == ' ') return PAGELEN;
		if (c == '\n') return 1;
	}
	return 0;
}

分析上述代码的不足:

从上述第11行代码可以知道,若只有一个命令行参数,则会从标准输入读取数据。

若使用如下的管道重定向和输入重定向的话,more01这个程序就只有一个命令行参数,就不是从标准输入读入数据,而是分别从ls /bin这个命令输出、more01.c这个文件,来读取数据:




从上述代码的第45行我们可以知道,当程序运行到第45行代码时会请求我们输入,但若我们使用的是管道重定向或输入重定向的话,就不会请求我们输入了,因为getchar()这个函数是读取标准输入的数据,现在我们用管道重定向或输入重定向将标准输入重定向了,所以getchar()函数会直接读取ls /bin这个命令输出或more01.c这个文件中的数据。因此,当使用

ls /bin | ./more01

./more01 < more01.c

这两个命令的时候,会直接输出全部的内容,而不会像下面这幅图一样进行询问:


(这幅图是使用命令./more01 more01.c后得到的结果)

解决方案:

从标准输入中读入要分页的数据,从键盘读入用户的输入。

上图中/dev/tty这个文件是键盘和显示器的设备描述文件,即当你向这个文件写入数据的时候,这些数据会直接在显示器上打印出来;当你向这个文件读入数据的时候,就相当于从键盘获取用户的输入(即向用户请求输入,用户输入后的数据会直接被读走)。这个就可以保证,即使程序的输入/输出被重定向,程序还可以通过这个文件和终端交换数据。

修改后的源程序可以在more02.c文件中看到。

其它不足之处:

用户输入空格键或字符'q'后,还得按回车键程序才会动作,并且输入的空格键或字符'q'还会显示出来,而实际的more命令是不需要额外的回车,并且输入的字符也不会回显。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值