2009-10-03 65 views
2

c之后使用getchar()用于键盘捕获。以下代码发现何时按下了箭头键/ esc。同时,我想读取用户输入的全部单词,并且这些单词也应显示在标准输出之上。在read()

char pp = 0; 
char p = 0; 
while((i = read(0, &c, 1)) == 1) { 
if (pp == 033 && p == 0133 && (c &= 255) == 0102) /* DOWN */ break; 
if (c == 0177) /* ASCII DELETE */ break; 
printf("%o, %o, %o\t%s\n\r", pp, p, c, &c); 
pp = p; 
p = c; 
} 
... 
... 
getchar(); //I want to capture here what was entered before 
      // **return key** was pressed. 

但是,如果我删除'\ n',此代码不起作用。 我希望标准输出应该像一个普通的shell一样运行。

回答

2

printf(3)通过<stdio.h>缓冲I/O设施,其中包括fputs(3)fputc(3)。您正在观察正常线路缓冲行为。不过,如setbuf(3)所指出的那样,您可以打败这种缓冲,因为您首先不需要它,并且您已经在使用直接内核调用(read(2))进行阅读,为什么不直接调用您的逻辑来直接调用内核与write(2)以及?

char buffer[100]; 

int n; 

n = snprintf(buffer, sizeof buffer, "format string...", args...); 
write(1, buffer, n) 

如果你愿意,你可以定义自己的directPrintf使它更容易些:

#include <stdio.h> 
#include <stdarg.h> 
#include <unistd.h> 

int directPrintf(const char *format, ...) 
{ 
va_list ap; 
char buffer[200]; 

    va_start(ap, format); 
    int n = vsnprintf(buffer, sizeof buffer, format, ap); 
    va_end(ap); 
    return write(1, buffer, n); 
} 
0

getchar()很可能以read()的形式实现,其读取远远超过1个字节(通常是整个PIPE_BUF或4096个字节)。然后它保持一个私人游标到该缓冲区,根据需要提取字节。

这样做是因为read()有一个不重要的开销,与相关联,调用它。

printf()fwrite()(和其他)也出于同样的原因缓冲(write()有一个不平凡的开销)。对fflush(stdout)的调用将转换为调用任何已被缓冲但不发送到底层IO端口的write()调用。

最后,你有\n\r倒退;它几乎可以肯定应该是\r\n

0

插入

setbuf(stdout, NULL); 

某处开始和删除\ n。