unix/linux more命令的實現

Understanding Unix/Linux Programming(Unix/Linux編程實踐教程)

學習模式:

(1)它能做什麼?

(2)它是如何實現的?

(3)能不能自己編寫一個?

(實驗環境:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 


/* more01.c  - version 0.1 of more
 *	read and print 24 lines then pause for a few special commands
 */

#include	<stdio.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 )
/*
 *  read PAGELEN lines, then call see_more() for further instructions
 */
{
	char	line[LINELEN];
	int	num_of_lines = 0;
	int	see_more(), reply;

	while ( fgets( line, LINELEN, fp ) ){		/* more input	*/
		if ( num_of_lines == PAGELEN ) {	/* full screen?	*/
			reply = see_more();		/* y: ask user  */
			if ( reply == 0 )		/*    n: done   */
				break;
			num_of_lines -= reply;		/* reset count	*/
		}
		if ( fputs( line, stdout )  == EOF )	/* show line	*/
			exit(1);			/* or die	*/
		num_of_lines++;				/* count it	*/
	}
}

int see_more()
/*
 *	print message, wait for response, return # of lines to advance
 *	q means no, space means yes, CR means one line
 */
{
	int	c;

	printf("\033[7m more? \033[m");		/* reverse on a vt100	*/
	while( (c=getchar()) != EOF )			/* get response	*/
	{
		if ( c == 'q' )			/* q -> N		*/
			return 0;
		if ( c == ' ' )			/* ' ' => next page	*/
			return PAGELEN;		/* how many to show	*/
		if ( c == '\n' )		/* Enter key => 1 line	*/
			return 1;		
	}
	return 0;
}




相比上面的程序,下面這個程序多了幾個擴展功能。

(1)當程序按空格或者輸入“q”後,不需要按回車鍵直接處理。

(2)打印文件中已經顯示的百分比。

相比課本,未完成功能如下,在網上找不到合適的資料,待續。

(1)確定終端打印的行數列數(終端類)

//more command
#include<stdio.h>
#include<stdlib.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE* );
int see_more(FILE*,int );
int sum_size  = 0;

int main(int ac,char *av[])
{
	FILE* fp;
	if(ac == 1)
		do_more(stdin);
	else
		while(--ac)
		{
			if((fp = fopen(*++av,"r")) != NULL)
			{
				fseek(fp,0L,SEEK_END);  /*利用fseek函數將指針定位在文件結尾的位置*/
				sum_size=ftell(fp);     /*利用ftell函數返回指針相對於文件開頭的位置,以字節計算*/
				printf("\n the type of file is : %d\n",sum_size);   /*進行輸出文件總大小*/
				fseek(fp,0L,SEEK_SET);   /*將fp設置文件開始的位置*/
				do_more(fp);
				fclose(fp);
			}
			else
				exit(1);
		}
	return 0;
}

void do_more(FILE* fp)
{
	/*
		read PAGELEN lines, then call see_more() for further instructions
	*/
	char line[LINELEN];
	int num_of_lines = 0;
	int see_more(FILE*,int),reply;
	FILE* fp_tty;
	fp_tty = fopen("/dev/tty","r");
	if(fp_tty == NULL)
		exit(1);
	while(fgets(line, LINELEN,fp))
	{
		if(num_of_lines == PAGELEN)
		{
			int cur_size=ftell(fp);   /*利用ftell函數返回指針相對於文件開頭的位置,以字節計算*/
			int per= (int)100* cur_size/sum_size; //計算當前佔用比例。
			reply =see_more(fp_tty,per);
			if(reply == 0 )
				break;
			num_of_lines -= reply;
		}
		if(fputs(line,stdout) == EOF)
			exit(1);
		num_of_lines++;
	}
}
int see_more(FILE* cmd,int per)
{
	/*
	print message, wait for response, return # of lines to advance
	q means no, space means yes CRmeans one line
	*/
	int c;
	system("stty -icanon");//關閉緩衝區,輸入字符無需回車直接接受
	printf("\033[7m more?--%d%--\033[m",per);  //實現反白
	while((c=getc(cmd))!=EOF)
	{
		if(c == 'q')
			return 0;
		if(c == ' ')
			return PAGELEN;
		if(c == '\n')
			return 1;
	}
}



運行結果




發佈了146 篇原創文章 · 獲贊 240 · 訪問量 46萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章