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;
}
}
運行結果