zoukankan      html  css  js  c++  java
  • APUE fig 1.10示例代码的完善对提示符及输入回车的优化

     APUE 第3版第15页的shell2.c示例程序,运行效果如下:

     1 gcc ol.shell.c -o origin_shell
     2 
     3 ./origin_shell
     4 % date
     5 2015年12月13日 星期日 22时04分48秒 CST
     6 % ^Cinterrupt
     7 ls
     8 Makefile    getcputc.c    mycat.c        myls_info.c    note.md        origin_shell    shell2.c    uidgid.c
     9 a.out        hello.c        myls.c        myls_sort.c    ol.shell.c    shell1.c    testerror.c
    10 % %
    11 couldn't execute: : No such file or directory
    12 % ls
    13 Makefile    getcputc.c    mycat.c        myls_info.c    note.md        origin_shell    shell2.c    uidgid.c
    14 a.out        hello.c        myls.c        myls_sort.c    ol.shell.c    shell1.c    testerror.c
    15 %

    从上述示例中可以看出,存在2个小问题:

    1. 当通过ctrl+C输入中断信号时,中断捕获程序的输出语句的“%”并没有立即输出来,等到下一次回车时才输出,导致第10行有两个%%号。

    2. 当出现%提示符时,直接回车,会提示如11行所示的错误。因为此时传递给execlp函数的buf内容是空的。其中问题1是出现在程序中的如下一句:

    while (fgets(buf, MAXLINE, stdin) != NULL) {
    }
    // 即中断信号中断的是fgets函数,此时系统正在请求输入中,而中断处理程序的输出:
    
    printf("interrupt\n%% ");
    
    // 在换行之后,%并没有立即出来。如果将其修改如下,

    printf("interrupt\n%%\n"); // 则显示效果变成这样:
    1 % ^Cinterrupt
    2 %
    3 ls
    4 Makefile    mycat.c        note.md        shell2.c
    5 a.out        myls.c        ol.shell.c    testerror.c
    6 getcputc.c    myls_info.c    origin_shell    uidgid.c
    7 hello.c        myls_sort.c    shell1.c

    如上可见,上述增加一个'\n'后,虽然立即输出了%,但如第3行所见,光标移到%下一行了。

    一个解决办法是使用fflush()函数。完整代码,新增为21-24行,以及46行:

     1 #include "../apue.h"
     2 #include <sys/wait.h>
     3 
     4 static void    sig_int(int);        /* our signal-catching function */
     5 
     6 int
     7 main(void)
     8 {
     9     char buf[MAXLINE];    /* from apue.h */
    10     pid_t  pid;
    11     int  status;
    12 
    13     if (signal(SIGINT, sig_int) == SIG_ERR)
    14         err_sys("signal error");
    15 
    16     printf("%% ");    /* print prompt (printf requires %% to print %) */
    17     while (fgets(buf, MAXLINE, stdin) != NULL) {
    18         if (buf[strlen(buf) - 1] == '\n')
    19             buf[strlen(buf) - 1] = 0; /* replace newline with null */
    20 
    21         if (strlen(buf) == 0) { // 此if语句用于处理直接回车
    22             printf("%% ");  
    23             continue;
    24         }
    25 
    26         if ((pid = fork()) < 0) {
    27             err_sys("fork error");
    28         } else if (pid == 0) {        /* child */
    29             execlp(buf, buf, (char *)0);
    30             err_ret("couldn't execute: %s", buf);
    31             exit(127);
    32         }
    33 
    34         /* parent */
    35         if ((pid = waitpid(pid, &status, 0)) < 0)
    36             err_sys("waitpid error");
    37         printf("%% ");
    38     }
    39     exit(0);
    40 }
    41 
    42 void
    43 sig_int(int signo)
    44 {
    45       printf(" interrupt!\n%%");
    46       fflush(stdout);   //强制输出所有stdout中的字符流
    47 }

     完善后效果如下:

    1 % date
    2 2015年12月13日 星期日 22时31分53秒 CST
    3 % ^C interrupt!
    4 % date
    5 2015年12月13日 星期日 22时32分15秒 CST
    6 %
    7 %
  • 相关阅读:
    常见的单链表题目
    一个string类的几个函数
    strcpy和memcpy的区别
    字符串及 strcpy几种写法
    什么函数不能声明为虚函数
    STL中Vector和List的底层数据结构
    C/C++堆、栈及静态数据区详解
    tcp四次握手
    几个知识点
    内存对齐的规则与作用
  • 原文地址:https://www.cnblogs.com/qinqiao/p/opt_apue_fig1_10_shell2.html
Copyright © 2011-2022 走看看