2014-10-12 3 views
15

stdin을 차단하는 실행 파일을 실행하고 키를 누를 때 같은 문자가 즉시 인쇄되지 않으면 을 입력해야합니다.입력을 누르지 않고도 stdin에서 한 문자를 어떻게 읽을 수 있습니까?

입력하지 않고도 stdin에서 한 문자를 읽는 방법 을 입력 하시겠습니까? 내가 API를 통해 보면서 bytes()read_line()를 교체하려고

fn main() { 
    println!("Type something!"); 

    let mut line = String::new(); 
    let input = std::io::stdin().read_line(&mut line).expect("Failed to read line"); 

    println!("{}", input); 
} 

, 그러나 나는 시도 다 읽기가 발생하기 전에 를 입력 치고 저를 요구한다 :이 예제를 시작했다.

이 질문은 C/C++을 요구하지만, 그것을 할 수있는 표준 방법은없는 것 같다되었다 Capture characters from standard input without waiting for enter to be pressed

그것은 C/C++에서 간단하지 고려 녹에서 행할 수 없습니다.

+3

이것은 언어 문제가 아닌 플랫폼 문제입니다. 창문에는 문자 입력 기능이 있지만 유닉스/리눅스에서는 터미널을 라인 버퍼 모드에서 꺼내야합니다. –

+0

언급 된 SO 링크에서'getch' 함수를 사용할 수 있습니다. 이를 공유 객체로 컴파일하고 Rust에서 사용해야합니다. https://gist.github.com/ihrwein/a4558d63d9250ee0bbf6 C 컴파일러가 필요하며 Linux에서만 작동합니다 (적어도 테스트 해봤습니다). . –

답변

10

이제 이용 가능한 'ncurses'라이브러리 중 하나를 사용하십시오 (예 : this).

는 main.rs에
[dependencies] 
ncurses = "5.86.0" 

화물

에 종속성을 추가하고 다음과 같습니다

extern crate ncurses; 
use ncurses::*; // watch for globs 

는 ncurses를 초기화와 같은 단일 문자 입력을 기다리는 라이브러리의 예제를 따라

initscr(); 
/* Print to the back buffer. */ 
printw("Hello, world!"); 

/* Update the screen. */ 
refresh(); 

/* Wait for a key press. */ 
getch(); 

/* Terminate ncurses. */ 
endwin(); 
+0

이 방법이 효과적이지만, 여기에 설명 된대로 initscr()에 의해 적용되는 화면을 지우는 것을 피할 수없는 것처럼 보입니다. (http://stackoverflow.com/questions/4772061/curses-library-c-getch- 화면이 나타나지 않음) 및 [there] (http://stackoverflow.com/questions/654471/ncurses-initialization-without-clearing-the-screen). – dojuba

9

ncurses를 사용하는 @ Jon의 솔루션이 작동하는 동안 ncurses는 의도적으로 화면을 지 웁니다. 내 작은 프로젝트에 대해 Rust를 배우기 위해 termios crate을 사용하는이 솔루션을 생각해 냈습니다. 이 아이디어는 ECHOICANON 플래그를 termios 바인딩을 통해 tcsetattr에 액세스하여 수정하는 것입니다. (이들의 ncurses를 캡처 할 수 있지만) 단일 바이트를 판독

extern crate termios; 
use std::io; 
use std::io::Read; 
use std::io::Write; 
use termios::{Termios, TCSANOW, ECHO, ICANON, tcsetattr}; 

fn main() { 
    let stdin = 0; // couldn't get std::os::unix::io::FromRawFd to work 
        // on /dev/stdin or /dev/tty 
    let termios = Termios::from_fd(stdin).unwrap(); 
    let mut new_termios = termios.clone(); // make a mutable copy of termios 
              // that we will modify 
    new_termios.c_lflag &= !(ICANON | ECHO); // no echo and canonical mode 
    tcsetattr(stdin, TCSANOW, &mut new_termios).unwrap(); 
    let stdout = io::stdout(); 
    let mut reader = io::stdin(); 
    let mut buffer = [0;1]; // read exactly one byte 
    print!("Hit a key! "); 
    stdout.lock().flush().unwrap(); 
    reader.read_exact(&mut buffer).unwrap(); 
    println!("You have hit: {:?}", buffer); 
    tcsetattr(stdin, TCSANOW, & termios).unwrap(); // reset the stdin to 
                // original termios data 
} 

한가지 장점은 화살표 키를 캡처, CTRL-F 등의 확장 키를 포착하지 않는다.

이 솔루션은 UNIX와 같은 플랫폼을 대상으로합니다. 나는 Windows에 대한 경험이 없지만이 forum에 따르면 아마도 Windows에서는 SetConsoleMode을 사용하여 비슷한 결과를 얻을 수 있습니다.

관련 문제