非缓冲标准输入读 [英] non-buffering stdin reading

查看:139
本文介绍了非缓冲标准输入读的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的测试应用程序

 的#include< SYS / types.h中>
#包括LT&; SYS / wait.h>
#包括LT&;&signal.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&fcntl.h GT;INT主(INT ARGC,CHAR *的argv []的char * envp []){
  INT FD [2];  如果(管道(FD)℃,){
    的printf(可以\\'吨创建管道\\ n);
    出口(-1);
  }  将为pid_t FPID = fork()的;
  如果(FPID == 0){
    关闭(0);
    关闭(FD [1]);
    字符* S =(字符*)malloc的(的sizeof(字符));
    而(1)如果(读(FD [0],S,1))的printf(%I \\ N,* S);
  }
  关闭(FD [0]);
  字符* C =(字符*)malloc的(的sizeof(字符));
  而(1){
    如果(读(0,C 1)大于0)写(FD [1],C,1);
  }
  返回0;
}

我想看到煤焦code分别输入字符后。但事实上,* S仅之后在控制台中的'\\ n'打印。所以看起来像标准输入(文件,说明0)进行缓冲。但读功能缓冲少,是不是?我在哪里错了。

UPD:我用linux

所以,解决的办法是

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&termios.h GT;INT主(INT ARGC,CHAR *的argv []的char * envp []){
  INT FD [2];  如果(管道(FD)℃,){
    的printf(可以\\'吨创建管道\\ n);
    出口(-1);
  }  结构termios的期限,term_orig;  如果(tcgetattr(0,&放大器; term_orig)){
    的printf(tcgetattr失败\\ n);
    出口(-1);
  }  长期= term_orig;  term.c_lflag&安培; =〜ICANON;
  term.c_lflag | = ECHO;
  term.c_cc [VMIN] = 0;
  term.c_cc [VTIME] = 0;  如果(tcsetattr(0,TCSANOW,&安培术语)){
    的printf(tcsetattr失败\\ n);
    出口(-1);
  }  将为pid_t FPID = fork()的;
  如果(FPID == 0){
    关闭(0);
    关闭(FD [1]);
    字符* S =(字符*)malloc的(的sizeof(字符));
    而(1)如果(读(FD [0],S,1))的printf(%I \\ N,* S);
  }
  关闭(FD [0]);
  字符* C =(字符*)malloc的(的sizeof(字符));
  而(1){
    如果(读(0,C 1)大于0)写(FD [1],C,1);
  }
  返回0;
}


解决方案

不幸的是,你要寻找的行为是不可能的标准ANSI C,以及UNIX终端我的默认模式/ O是面向行的,这意味着你将永远需要输入 \\ n 字符检索输入。你需要使用终端I / O的设施,让你在 <程序href=\"http://stackoverflow.com/questions/358342/canonical-vs-non-canonical-terminal-input\">non-canonical模式,使每个键盘preSS触发一个事件。在Linux / UNIX,你可以看看到&LT; termios.h&GT; 头,或者的 ncurses的库。

My test application is

#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

int main(int argc, char *argv[], char *envp[]) {
  int fd[2];

  if(pipe(fd) < 0) { 
    printf("Can\'t create pipe\n");
    exit(-1); 
  }

  pid_t fpid = fork();
  if (fpid == 0) {
    close(0);
    close(fd[1]);
    char *s = (char *) malloc(sizeof(char));
    while(1) if (read(fd[0], s, 1)) printf("%i\n", *s);
  }
  close(fd[0]);
  char *c = (char *) malloc(sizeof(char));
  while (1) {
    if (read(0, c, 1) > 0) write(fd[1], c, 1);
  }
  return 0;
}

I want to see char-code after each entered char. But in fact *s is printed only after '\n' in the console. So seems like stdin (file with desc 0) is buffered. But the read function is buffer-less, isn't it? Where am I wrong.

UPD: I use linux.

So the solution is

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>

int main(int argc, char *argv[], char *envp[]) {
  int fd[2];

  if(pipe(fd) < 0) { 
    printf("Can\'t create pipe\n");
    exit(-1); 
  }

  struct termios term, term_orig;

  if(tcgetattr(0, &term_orig)) {
    printf("tcgetattr failed\n");
    exit(-1); 
  }

  term = term_orig;

  term.c_lflag &= ~ICANON;
  term.c_lflag |= ECHO;
  term.c_cc[VMIN] = 0;
  term.c_cc[VTIME] = 0;

  if (tcsetattr(0, TCSANOW, &term)) {
    printf("tcsetattr failed\n");
    exit(-1);
  }

  pid_t fpid = fork();
  if (fpid == 0) {
    close(0);
    close(fd[1]);
    char *s = (char *) malloc(sizeof(char));
    while(1) if (read(fd[0], s, 1)) printf("%i\n", *s);
  }
  close(fd[0]);
  char *c = (char *) malloc(sizeof(char));
  while (1) {
    if (read(0, c, 1) > 0) write(fd[1], c, 1);
  }
  return 0;
} 

解决方案

Unfortunately, the behavior you're looking for is not possible with standard ANSI C, and the default mode for UNIX terminal I/O is line-oriented, which means you will always need an inputted \n character to retrieve the input. You'll need to use terminal I/O facilities that let you program in non-canonical mode, so that each key-press triggers an event. On Linux/UNIX, you can look into the <termios.h> header, or the ncurses library.

这篇关于非缓冲标准输入读的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆