[질문] 한글자씩 입력받기

aham의 이미지

보통 stdin으로부터 한 글자씩 입력을 받으려면
fgetc나 getchar 같은 것을 쓰는데
이들 함수는 엔터를 쳐야지만 글자가 입력이 되더군요.

엔터를 안 치고 입력을 받을 수 있는 방법이 없을까요?
keyboard에서 a를 누르면 바로 a를 입력받을 수 있는 방법이요..

현재로는 입력 버퍼의 크기를 1이나 0으로 만들어서 해보려고 하는데
setsockopt 같은 것을 쓰니까 소켓아니라 파일디스크립터라고 하더군요.
(참고로 socket으로는 그냥 1을 사용합니다.)

어떤 좋은 방법이 있을까요??
ncurses 같은 것은 어떻게 구현되어 있는건가요??

valor의 이미지

예전에 이런 일을 한 적이 있었는데요...

일단 NCURSES를 사용해도 됩니다만 그 기능 하나를 쓰기 위해 NCURSES를 쓰는 건 좀 아니라는 생각이 들었습니다.

그러다 보니 터미널에 canonical 속성을 끄면 키 입력 하나하나 받을때마다 처리한다는 사실을 찾았습니다.

근데 제가 그 속성 설정하는 방법을 잊어버렸군요...

http://arcane.4wish.net/mirror/kordoc/kldp/kldp/Serial-Programming-HOWTO

여기 문서에 예제가 있네요... 위 문서의 예제는 시리얼 터미널의 경우인데 여기서 파일 디스크립터인 fd를 새로 여는 디바이스가 아닌 STDIN 즉 0번을 사용하면 되겠지요...

yeppiguy의 이미지

#include <termios.h>
static struct termios   tsaved;
bool                    bsaved=false;
void cmd_prepare()
{
    struct termios  tnew;

    if(isatty(0) && tcgetattr(0,&tsaved) >= 0)
    {
        bsaved=true;
        memcpy(&tnew,&tsaved,sizeof(tsaved));
        tnew.c_lflag &= ~(ICANON|ECHO|ISIG);
        tcsetattr(0,TCSANOW,&tnew);
    }
    else
        bsaved=false;
}
void cmd_restore()
{
    if(bsaved)
    {
        tcsetattr(0,TCSANOW,&tsaved);
        bsaved=false;
    }
}
int main()
{
     ...........
     while(1)
     {
         if(select(stdin,NULL,NULL,NULL,NULL))
             cmd_handler(fgetc(stdin));
     }     
     ...........
}

예전에 사용했던 테스트 프로그램인데, 참고하세요.
참, 위의 예제는 한문자 들어올때마다 처리하긴 하지만, ECHO를 꺼놓아서, 사용자가 ECHO처리를 하셔야 합니다.

myreas의 이미지

int Get (char *s, int size,int keymode) {
struct termio tdes,tdes_old; /* Ioctl 버퍼 */
int old_ttymode; /* tty 모드 */
int old_sockmode; /* 소켓 스트림 모드 */
int i;
int rlen; /* Read 된 사이즈 */
int lineflag; /* 라인이 구성되면 ON (1),OFF(0) */
int msgflag;
int count; /* 문자열 입력 스트링 카운터 */
char ch; /* 1 문자 */
char *cs; /* 문자 버퍼위치 */
struct timeval fddelay;
fd_set in_stdset; /* 키스트림 플래그 */
fd_set out_stdset; /* 키스트림 플래그 */
fd_set exc_stdset; /* 키스트림 플래그 */
int sockfd;
char keybuf [256 + 1];
long maxwaittime;
long stime, etime; /* 시간 */
count = 0;
cs = s;
count = strlen (s);
cs = s+count;
ioctl (0, TCGETA, &tdes_old);
ioctl (0, TCGETA, &tdes);
old_ttymode = fcntl(0,F_GETFL); /* 기존의 스트림 내용 기억 */
/* 키스트림(규준모드 입력 설정) */
if (keymode == 0)
{
signal(SIGINT,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
ioctl(0,TCSETA,&tdes);
}

/* 키스트림(RAW 입력 설정) */
if ( keymode == 1 || keymode == 2|| keymode == 3 || keymode == 4 )
{
tdes.c_lflag &= ~(ICANON | ECHO);
tdes.c_lflag &= (ECHO);
tdes.c_oflag |= (OPOST);
tdes.c_iflag |= IXON;
tdes.c_cc[VMIN ]=1;
tdes.c_cc[VTIME]=0;

ioctl(0,TCSETA,&tdes);
}

time(&stime);

memset(keybuf,0,sizeof(keybuf));
fflush(stdout);

while(1)
{
rlen = read(0,keybuf,MAX_STRING_LENGTH); /* 현재 스트림에 있는 모든 버퍼를 읽음 */
for (i=0;i<rlen;i++)
{
ch = *(keybuf+i);
if (ch ==26||ch ==13||ch ==10)
{
*(cs) = 0;
if (keymode != 0) fflush(stdout);

ioctl(0, TCSETA, &tdes_old);
fcntl(0, F_SETFL, old_ttymode);
if (ch==26) return(EXIT); /* Ctrl + Z */
return(OK);
}

if ( ch == 8 && count == 0)
{
goto roop;
}

if ( ch == 8 && count != 0)
{
*cs--='\0';
count--;
if (keymode == 1||keymode == 2 || keymode==3 )
{
putchar(ch);
putchar (' ');
putchar (ch);
if (keymode != 0) fflush(stdout);
}
goto roop;
}

count++;
if ( count == size )
{
/* 버퍼가 가득찼음 */
*(cs) = 0;
if (keymode != 0) fflush(stdout);

ioctl(0, TCSETA, &tdes_old);
fcntl(0, F_SETFL, old_ttymode);
if (ch==26) return(EXIT); /* Ctrl + Z */
return(OK);
}

*cs++ = ch;
if (keymode == 1 || keymode==3 ) putchar(ch);
if (keymode == 2) putchar('*');
if (keymode != 0) fflush(stdout);
roop:;
}
memset(keybuf,0,sizeof(keybuf));
}
/* Get() End */
}

Rock will never die

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.