【Unix/Linux程式設計實踐】 動手實現簡單的more
阿新 • • 發佈:2019-01-22
最近都在看一些理論方面的書,缺乏實踐真的是雲裡霧裡的,於是今天開始看《Unix/Linux程式設計實踐教程》,理論實踐相結合!
自己動手來實現linux的一些功能,確實挺有趣的,而且還能加深對系統的理解~
版本一
/*more01.c
*read and print 24 lines then pause for a few special commands
*/
#include <stdio.h>
#define PAGELEN 24
#define LINELEN 512
/*
*將資料顯示在螢幕上,滿一屏後,呼叫see_more函式接受使用者的輸入,以採取下一步動作。
*/
void do_more(FILE *);
int see_more();
int main(int argc, char * argv[])
{
FILE *fp;
//判斷是檔案還是標準輸入,開啟對應的資料來源
if ( argc == 1)
do_more(stdin);
else
{
while (argc--)
if ( (fp = fopen(* ++argv, "r")) != NULL) //第一個引數是more01,跳過
{
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; //根據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;
}
當然這個程式存在挺多問題的,比如輸入q和空格後,需要按回車,而且輸入是有回顯的。
另外,一個比較嚴重的問題是,如果我們進行重定向:
ls /bin | more01
則more01的標準輸入被重定向到ls的標準輸出中,這樣子使用者的輸入也從這個輸入流中讀取,明顯有問題。使用者的輸入應該始終從鍵盤讀取,而不應該被重定向。
所以版本二提供了直接從鍵盤裝置讀取的功能。
版本二
裝置檔案/dev/tty是鍵盤和顯示器的裝置描述檔案,往該檔案寫則顯示在使用者螢幕上,讀則從鍵盤獲取使用者輸入。
/* more02.c - version 0.2 of more
* read and print 24 lines then pause for a few special commands
* feature of version 0.2: reads from /dev/tty for commands
*/
#include <stdio.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE *);
int see_more(FILE *);
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(FILE *), reply;
FILE *fp_tty;
fp_tty = fopen( "/dev/tty", "r" ); /* NEW: cmd stream */
if ( fp_tty == NULL ) /* if open fails */
exit(1); /* no use in running */
while ( fgets( line, LINELEN, fp ) ){
if ( num_of_lines == PAGELEN ) {
reply = see_more(fp_tty); /* NEW: pass FILE * */
if ( reply == 0 )
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(FILE *cmd) /* NEW: accepts arg */
/*
* 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=getc(cmd)) != EOF ) /* NEW: reads from tty */
{
if ( c == 'q' )
return 0;
if ( c == ' ' )
return PAGELEN;
if ( c == '\n' )
return 1;
}
return 0;
}
通過一個直觀的例子感受了下Linux程式設計,雖然還有很多不完善的地方,但是完善本程式並不是我們的目的!