[질문] 한글자씩 입력받기
글쓴이: aham / 작성시간: 월, 2004/03/15 - 11:23오전
보통 stdin으로부터 한 글자씩 입력을 받으려면
fgetc나 getchar 같은 것을 쓰는데
이들 함수는 엔터를 쳐야지만 글자가 입력이 되더군요.
엔터를 안 치고 입력을 받을 수 있는 방법이 없을까요?
keyboard에서 a를 누르면 바로 a를 입력받을 수 있는 방법이요..
현재로는 입력 버퍼의 크기를 1이나 0으로 만들어서 해보려고 하는데
setsockopt 같은 것을 쓰니까 소켓아니라 파일디스크립터라고 하더군요.
(참고로 socket으로는 그냥 1을 사용합니다.)
어떤 좋은 방법이 있을까요??
ncurses 같은 것은 어떻게 구현되어 있는건가요??
Forums:
non-canonical로 터미널 속성을 변경하면 될겁니다...
예전에 이런 일을 한 적이 있었는데요...
일단 NCURSES를 사용해도 됩니다만 그 기능 하나를 쓰기 위해 NCURSES를 쓰는 건 좀 아니라는 생각이 들었습니다.
그러다 보니 터미널에 canonical 속성을 끄면 키 입력 하나하나 받을때마다 처리한다는 사실을 찾았습니다.
근데 제가 그 속성 설정하는 방법을 잊어버렸군요...
http://arcane.4wish.net/mirror/kordoc/kldp/kldp/Serial-Programming-HOWTO
여기 문서에 예제가 있네요... 위 문서의 예제는 시리얼 터미널의 경우인데 여기서 파일 디스크립터인 fd를 새로 여는 디바이스가 아닌 STDIN 즉 0번을 사용하면 되겠지요...
[code:1]#include <termios.h>stat
예전에 사용했던 테스트 프로그램인데, 참고하세요.
참, 위의 예제는 한문자 들어올때마다 처리하긴 하지만, ECHO를 꺼놓아서, 사용자가 ECHO처리를 하셔야 합니다.
음 참고가 되었으면 좋겠습니다.
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
댓글 달기