实现more命令

来源:互联网 发布:软件项目评分表 编辑:程序博客网 时间:2024/06/14 13:09

在看了《Linux/UNIX系统编程手册》和APUE前几章之后发现缺少相应的实践,如果只是单纯的了解API并没有太大意义,因此决定跟随《UNIX/Linux编程实践教程》将书中的例子调通与理解透。然后再去啃APUE,效果应该会好很多。
书中第一章给出了more实现的第一版,由于书写与2004年,代码看上去有些“另类”,修改后如下:
编译方法是直接使用gcc more01.c,然后./a.out more.01.c /etc/passwd
或从标准输入中获取信息直接输入./a.out
下面代码有几点需要注意:

 if ( (fp = fopen(* ++argv, "r")) != NULL) //第一个参数是./a.out,跳过 ``` 关于main函数中argc argv参考[main函数arc argv介绍](https://www.52coder.net/post/main)这行代码其实换成如下形式更好理解``` C    while (argc--)    {        argv++;        if ( (fp = fopen(*argv, "r")) != NULL) //第一个参数是more01,跳过        {            do_more(fp);            fclose(fp);        }        else            exit(1);    }<div class="se-preview-section-delimiter"></div>

再有就是关于 printf(“\033[7m more? \033[m”);中的形式之前没有见过,解释如下:
\033是8进制,它就是unix下终端转义符ESC(16进制1A,10进制27)
ESC[xm 是unix下改变终端输出颜色的命令
printf(“\033[7m more?\033[m”);
会显示一个白底黒字的more
输出特效格式控制:
“`
\033[0m 关闭所有属性
\033[1m 设置高亮度
\03[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m – \033[37m 设置前景色
\033[40m – \033[47m 设置背景色

<div class="se-preview-section-delimiter"></div>#### 版本一<div class="se-preview-section-delimiter"></div>``` C/*more01.c *read and print 24 lines then pause for a few special commands */#include <stdio.h>#include <stdlib.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 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和空格后,需要按回车,而且输入是有回显,more会跟着屏幕滚动。

另外,一个比较严重的问题是,如果我们进行重定向:
gcc -o more01 more01.c
然后将生成的可执行文件放到以下任意一个目录就可以执行了:/bin /usr/bin /usr/local/bin.
ls /bin | more01
如果没有将可执行文件放在上面三个目录中任意一个的话只能用如下方式
ls /bin | ./more01
文件名后有*表示可执行文件。
期望的结果是将/bin目录下的文件分页,显示24行后暂停,实际结果并非如此,24行以后并没有暂停而是继续输出。
more01中的getchar()从标准输入读数据,ls /bin | ./more已经将more01的标准输入重定向到ls的标准输出。
解决的方法是从标准输入中读入要分页的数据,直接从键盘读用户的输入。

版本二

#include    <stdio.h>#include    <stdlib.h>#define PAGELEN 24#define LINELEN 512void 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   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;}

目前more命令与Linux中的more命令存在着两点主要区别:
1.输入回车换行之后,more跟着屏幕滚动
2.没有显示进度
随着学习的深入,这些问题将在后面解决。

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小卧室装修设计 小男孩的房间 小男孩房间 手工迷你小房间 小房间布置 爷爷骗小孙子在房间 装修小房间的效果图 15个房间的小旅馆装修 小房间装修多少钱 小户型房间布置 榻榻米小房间 小房间装修风格 小房间如何装修 小房间儿童房设计 小女孩房间设计图卧室图片 小房间 小房间装修效果图 女孩小房间装修 小房间怎么布置 室内装修小房间 小房间上下铺设计图 小房间衣柜设计图 小房间怎么设计 女生小房间装饰 超小房间装修 10平米小房间布置 小房间怎样装修 小房间图片 小房间创意装修 小房间的装饰 小房间书房设计 10平米小房间装修 小房间的设计 小房间榻榻米床装修效果图 女生小房间设计 7平米小房间设计 卧室小房间布置 小房间的装修设计 女孩小房间装修效果图 女生小房间装修图 小房间的装饰图