[comp.lang.c] getchar

storm@cs.mcgill.ca (Marc WANDSCHNEIDER) (03/05/91)

The following file:

#include "stdio.h"
main()
{
   int c;
   c = getchar();
   while (c != 65) {     /* 65 is capital A on the PC*/
       putchar(c);
       c = getchar();
     }
}

   Echos every character that you put on the screen.  However, it does not 
stop (even after a Capital A) until you hit return.

   I changed the program to this:

#include ....
main()
{
    long nc;
    nc = 0;
    while(getchar() !=65)
                ++nc;
    printf("%ld\n", nc);
}

   This program STILL echos the characters I type in (even without the 
putchar()), and will only abort after I've hit the RETURN AFTER a "A".

    Can somebody offer some insight into what the hell is going on...?

    Also, is there and EOF character on the PC.  The origional program for
both the above cases was !=EOF, but I changed it to !=65....

    Any help would be great.

    Thanks.

./*-

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
storm@cs.mcgill.ca         McGill University           It's 11pm, do YOU
Marc Wandschneider         Montreal, CANADA            know what time it is?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

harry@matilda.UK.Sun.COM (Harry Protoolis - Sun EHQ) (03/06/91)

Marc,

Your problem is that your system is line buffering input. (yes, even getchar()
does this).

Assuming that your are on a Unix system you can turn this off using
ioctl to turn off cbreak mode (read tty(4)) to your input device. If
you are running DOS I don't know, but there is certainly an equivalent.

Cheers
Harry Protoolis

Harry.Protoolis@UK.Sun.COM

dave@cs.arizona.edu (Dave P. Schaumann) (03/06/91)

In article <1991Mar5.063644.8459@cs.mcgill.ca> storm@cs.mcgill.ca (Marc WANDSCHNEIDER) writes:
>[program that reads input using getchar() deleted]
>
>   Echos every character that you put on the screen.  However, it does not 
>stop (even after a Capital A) until you hit return.

The problem with your program is that stdin (and stdout) is buffered.  This
means for input, that when you request a character, the system actually gets
a whole line, and then feeds you the result one character at a time.  This
is efficient for when the overhead on a read is high, and doesn't depend much
on the size of the input read.

That is why your program doesn't quit until you hit return; the call to
getchar() doesn't return until you  hit (carriage) return.

Your next question, no doubt is "how do I do unbuffered reads?".
Unfortunately, there is no portable way to do this, although many (most?)
systems have some way to do it.  I would suggest you RTFM to find out more.

-- 
		Dave Schaumann		dave@cs.arizona.edu
'Dog Gang'!  Where do they get off calling us the 'Dog Gang'?  I'm beginning to
think the party's over.  I'm beginning to think maybe we don't need a dog.  Or
maybe we need a *new* dog.  Or maybe we need a *cat*! - Amazing Stories

gordon@osiris.cso.uiuc.edu (John Gordon) (03/06/91)

	Your problem is that getchar() does not recognize ANY input until
you hit Enter.

storm@cs.mcgill.ca (Marc WANDSCHNEIDER) (03/07/91)

In article <1991Mar5.220902.19196@ux1.cso.uiuc.edu> gordon@osiris.cso.uiuc.edu (John Gordon) writes:
>
>	Your problem is that getchar() does not recognize ANY input until
>you hit Enter.


    Then is there ANY way that I can have sort of "HOT KEYS" ie the user
just hits a  key, and then the computer recognizes that a key has been hit
and the key is sent to some variable...?  (Using MSDOS...)

    Thanks for the help.

./*-

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
storm@cs.mcgill.ca         McGill University           It's 11pm, do YOU
Marc Wandschneider         Montreal, CANADA            know what time it is?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

tlglenn@cs.arizona.edu (Ted L. Glenn) (03/07/91)

In article <1991Mar6.165835.10237@cs.mcgill.ca>, storm@cs.mcgill.ca (Marc WANDSCHNEIDER) writes:
>     Then is there ANY way that I can have sort of "HOT KEYS" ie the user
> just hits a  key, and then the computer recognizes that a key has been hit
> and the key is sent to some variable...?  (Using MSDOS...)
> 
>     Thanks for the help.

     I remember seeing a book in the university library about how one
could use Turbo Pascal to write programs that could set a BIOS or some
other interupt to be called when certain keys were pressed. I should
think that there are C books that deal with this topic.


-- 
        -Ted L. Glenn             "Don't worry, be happy!" <--Ack! Pffffhhht!
         tlglenn@cs.arizona.edu
         G19382105@ccit.arizona.edu    G19382105@ARIZRVAX.BITNET

kirste@methan.chemie.fu-berlin.de (Burkhard Kirste) (03/07/91)

storm@cs.mcgill.ca (Marc WANDSCHNEIDER) writes:

>>	Your problem is that getchar() does not recognize ANY input until
>>you hit Enter.
>
>    Then is there ANY way that I can have sort of "HOT KEYS" ie the user
>just hits a  key, and then the computer recognizes that a key has been hit
>and the key is sent to some variable...?  (Using MSDOS...)
>
That's trivial in Turbo C (MSDOS):  i = getch();
It is much more complicated under UNIX, but possible.
-- 
  |~|   Freie Universitaet Berlin, Institut fuer Organische Chemie
  / \   Burkhard Kirste    kirste@kristall.chemie.fu-berlin.dbp.de
 /FUB\  Takustrasse 3, D-1000 Berlin 33      UUCP: kirste@fub.uucp
 `---'  Telefon: (030)838-6484              Telefax: (030)838-5163

tchrist@convex.COM (Tom Christiansen) (03/08/91)

From the keyboard of daniel@island.COM (Daniel Smith):
:	I'd rewrite it in perl, but one of the things grabchars lets you do
:is assign defaults and time out after a given number of seconds, and I
:don't see how to set a timer in perl (Larry?).

You can use the alarm() function and catch SIGALRM.  

(Funny thing to find lurking in comp.lang.perl^H^H^H^Hc.)

--tom
--
	I get so tired of utilities with arbitrary, undocumented,
	compiled-in limits.  Don't you?

Tom Christiansen		tchrist@convex.com	convex!tchrist

dsebbo@dahlia.uwaterloo.ca (David Ebbo) (03/09/91)

In article <1991Mar6.165835.10237@cs.mcgill.ca> storm@cs.mcgill.ca (Marc WANDSCHNEIDER) writes:
>    Then is there ANY way that I can have sort of "HOT KEYS" ie the user
>just hits a  key, and then the computer recognizes that a key has been hit
>and the key is sent to some variable...?  (Using MSDOS...)
>
>    Thanks for the help.

Surely there is a way, but it's not portable.
On Turbo C++ and MS C (and quick C I guess), you can use either getch() or
getche().  The difference is that getche() echos the characters you type, 
while getch() doesn't.
You should include conio.h if you're going to use those functions.

Hope this helped,
David Ebbo.

browns@iccgcc.decnet.ab.com (Stan Brown) (03/10/91)

In article <1991Mar6.165835.10237@cs.mcgill.ca>, storm@cs.mcgill.ca (Marc WANDSCHNEIDER) writes:
> In article <1991Mar5.220902.19196@ux1.cso.uiuc.edu> gordon@osiris.cso.uiuc.edu (John Gordon) writes:
>>
>>	Your problem is that getchar() does not recognize ANY input until
>>you hit Enter.
> 
>     Then is there ANY way that I can have sort of "HOT KEYS" ie the user
> just hits a  key, and then the computer recognizes that a key has been hit
> and the key is sent to some variable...?  (Using MSDOS...)

As several people have said, there's no portable way to do this.

You don't say which compiler you're using.  In Microsoft C, use _bios_keybrd
or getch.  I would imagine there's something similar in Turbo C.  

Is it appropriate to remind you to RTFM?  

My opinions are mine:  I don't speak for any other person or company.
                   email (until 91/4/30): browns@iccgcc.decnet.ab.com
Stan Brown, Oak Road Systems, Cleveland, Ohio, USA    +1 216 371 0043

edrury@3cpu.UUCP (Ed Drury) (03/10/91)

In article <5CTOV6E@methan.chemie.fu-berlin.de> kirste@methan.chemie.fu-berlin.de (Burkhard Kirste) writes:
>storm@cs.mcgill.ca (Marc WANDSCHNEIDER) writes:
>
>>>	Your problem is that getchar() does not recognize ANY input until
>>>you hit Enter.
>>

	[ "yes, but..." stuff deleted ]

 oh yes, much more complicated, you have to use #include <curses.h>
rather than #include <conio.h> -- but the question as I understand
it was how to impliment "hot" keys under DOS using C which is not
portably done under DOS by reading scan codes -- but is portably
done by using pccurses or a series of #define KEY_UP etc ...

 union k {
	char ch[2];
	unsigned i;
	} key;
 ...
 if(!key.ch[0]) { /* it's a 'hot' one */
	switch(key.ch[1]){
		...
	
	}


		      Ed

kirste@methan.chemie.fu-berlin.de (Burkhard Kirste) (03/12/91)

edrury@3cpu.UUCP (Ed Drury) writes:

>In article <5CTOV6E@methan.chemie.fu-berlin.de> kirste@methan.chemie.fu-berlin.de (Burkhard Kirste) writes:
>>storm@cs.mcgill.ca (Marc WANDSCHNEIDER) writes:
>>
>>>>	Your problem is that getchar() does not recognize ANY input until
>>>>you hit Enter.
>
> oh yes, much more complicated, you have to use #include <curses.h>
                                                 ^^^^^^^^^^^^^^^^^^^
>rather than #include <conio.h> -- but the question as I understand
[stuff deleted]
Well yes, but you forgot to mention that this is in no way all you
would have to do under Unix. You would have to call initscr() in the
beginning, endwin() in the end, and you have to replace your printf's
by printw's. And you have to link the curses library, which gives
you a lot of overhead if getch() is really all you need.

Alternatively, you can avoid the whole curses stuff and change the
terminal settings via ioctl(...) etc.
-- 
  |~|   Freie Universitaet Berlin, Institut fuer Organische Chemie
  / \   Burkhard Kirste    kirste@kristall.chemie.fu-berlin.dbp.de
 /FUB\  Takustrasse 3, D-1000 Berlin 33      UUCP: kirste@fub.uucp
 `---'  Telefon: (030)838-6484              Telefax: (030)838-5163