[vox-tech] a better scanf?? (C-programming question)

Tim Riley vox-tech@lists.lugod.org
Fri, 18 Apr 2003 14:18:31 -0700


Andy Campbell wrote:

> >
> >
> >   Non-blocking with select/poll/busy-looping, reading into a
> > buffer, followed by sscanf when a return key is found will certainly
> > handle the second case... examples if that's what you want.
> >   Otherwise you will have to go with some curses or raw mode input
> > to get character by character input from a user, and opens a whole
> > can of worms...
> >
> >     TTFN,
> >       Mike
>
> Mike,
>
> I am trying to implement this but am unsuccessfull. Could you show me where
> some examples are?? Thank you!!
>
> Here is my code (it may be obviuos that I am a newbie.....I am trying to use
> file descriptors with stdin but the comiler won't let me. All in all....I
> guess I don't know enough about how you could use stdin as a file
> descriptor....any thoughts??
>
> #include <stdio.h>
> #include <sys/time.h>
> #include <sys/types.h>
> #include <sys/ioctl.h>
> #include <unistd.h>
> #include <fcntl.h>
>
> char input;
> int flag = 0;
>
> int main()
> {
>         fd_set rfds;
>         struct timeval tv;
>         int retval;
>         int n;
>         int key_press;
>
> /*
>         int key_press;
>
>         if((key_press = open(stdin, O_NONBLOCK)) < 0){
>                 fprintf(stderr, "Error opening stdin\n");
>                 exit(1);
>         }
> */    Well this didn't work...it wouldn't let me open stdin...perhaps that is
> a naive thing to try
>
>         while(flag == 0)
>         {
>
>
>
>                 FD_ZERO(&rfds);
>                 FD_SET(stdin, &rfds);       It didn't like this!!
>                 tv.tv_sec = 1;
>                 tv.tv_usec = 0;
>
>                 retval = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
>
>                 if (retval > 0) {
>                         if (FD_ISSET(stdin, &rfds)) {           ....Or this...
>                                 n = read(stdin, &input,  1);     .......or
> this........
>                                 printf("\nInput recorded as %c\n", input);
>                                 if (input == 'x')
>                                         flag = 1;
>                         }
>                 }
>
>
>
>                 printf("Waiting...\n");
>                 //sleep(5);
>         }
>
>         return 0;
> }
>
> ________

I'm trying to read your intent from the code above,
and it seems to be "run a process until
it finishes or let me press 'x' if I run out of patience." If that's the case,
then it'll be much easier to interrupt the process with <ctl>c instead.

Another possibility of intent is to prompt the user with a list of choices,
assigning each choice a single letter to press, and have that choice be
recorded without having to press <enter>. If that's the case, then Ryan's
reference to the function "set_keypress()" will work. However, the function
as posted has some bugs in it. Here is a complete program with the
function working.

#include <stdio.h>
#include <termio.h>

struct termios new_settings;
struct termios stored_settings;

void set_keypress(void) {
        tcgetattr(0,&stored_settings);
        new_settings = stored_settings;
        new_settings.c_lflag &= (~ICANON);
        new_settings.c_cc[VTIME] = 0;
        tcgetattr(0,&stored_settings);
        new_settings.c_cc[VMIN] = 1;
        tcsetattr(0,TCSANOW,&new_settings);
}

void reset_keypress(void) {
        tcsetattr(0,TCSANOW,&stored_settings);
}

int main( int argc, char *argv )
{
        char c;

        set_keypress();
        c = getchar();
        reset_keypress();
}

> _______________________________________
> vox-tech mailing list
> vox-tech@lists.lugod.org
> http://lists.lugod.org/mailman/listinfo/vox-tech