remove *dinkyisland* from address to mail me
> Qualcuno conosce una funzione equivalente alla getch() di conio.h che
> sia contenuta in ANSI C?
> Oppure potrebbe scrivermi un piccolo sorgente sostitutivo ANSI C
> compatibile?
> (Uso compilatori GNU sotto Liunx e sotto DOS)
Ahime' non c'e' maniera PORTABILE di farlo (domanda e risposta 19.2
della FAQ di comp.lang.c per i particolari). Sotto DOS puoi usare
direttamente getch e conio; sotto Unix/Linux puoi usare o curses o
qualcosa sul tipo del codice che accludo (assieme alla risposta alla
tua prossima domanda, cioe' kbhit :-), e dovuto a Floyd Davidson
<fl...@ptialaska.net>.
--
Maurizio Loreti http://wwwcdf.pd.infn.it/~loreti/mlo.html
Un. of Padova, Dept. of Physics - Padova, Italy lor...@padova.infn.it
/*
* getch() -- a blocking single character input from stdin
*
* This function has been tested on several SysV machines, SunOS4.1,
* BSDI UNIX, and Linux.
*
* BSD or POSIX systems may require a struct termios, older systems
* may require a struct termio, and some (Linux) may be able to use
* either.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
int getch(void);
int kbhit(void);
#define CMIN 1
#ifdef CTIME
#undef CTIME
#endif
#define CTIME 1
/*
* get a single character from stdin.
*
* First stdout is flushed, stdin is then switched to
* raw mode and input is waited for. When a single
* character is received from stdin the tty is restored
* to its original state and the character is returned.
* If the read from stdin fails, a -1 is returned.
*
* A conditional allows compiling with or without echo.
*/
int
getch(void)
{
char ch;
int error;
static struct termios Otty, Ntty;
fflush(stdout);
tcgetattr( 0, &Otty);
Ntty = Otty;
Ntty.c_iflag = 0; /* input mode */
Ntty.c_oflag = 0; /* output mode */
/* Change this conditional to enable echo of input character */
#if 1
Ntty.c_lflag = 0; /* line settings (no echo) */
#else
Ntty.c_lflag = ECHO; /* line settings (echo) */
#endif
Ntty.c_cc[VMIN] = CMIN; /* minimum time to wait */
Ntty.c_cc[VTIME] = CTIME;/* minimum characters to wait for */
#if 0
/*
* use this to flush the input buffer before blocking for new input
*/
#define FLAG TCSAFLUSH
#else
/*
* use this to return a char from the current input buffer, or block if
* no input is waiting.
*/
#define FLAG TCSANOW
#endif
if ( 0 == (error = tcsetattr( 0, FLAG, &Ntty))) {
error = read( 0, &ch, 1 ); /* get char from stdin */
error += tcsetattr(0, FLAG, &Otty); /* restore old settings */
}
return ( error == 1 ? (int) ch : -1 );
}
/*
* kbhit() -- a keyboard lookahead monitor
*
* returns the number of characters available to read, or -1 on error.
*
*/
int
kbhit(void)
{
int cnt = 0;
int error;
static struct termios Otty, Ntty;
tcgetattr( 0, &Otty);
Ntty = Otty;
Ntty.c_iflag = 0; /* input mode */
Ntty.c_oflag = 0; /* output mode */
Ntty.c_lflag &= ~ICANON; /* raw mode */
Ntty.c_cc[VMIN] = CMIN; /* minimum time to wait */
Ntty.c_cc[VTIME] = CTIME; /* minimum characters to wait for */
if (0 == (error = tcsetattr(0, TCSANOW, &Ntty))) {
error += ioctl(0, FIONREAD, &cnt);
error += tcsetattr(0, TCSANOW, &Otty);
}
return ( error == 0 ? cnt : -1 );
}
int
main(void)
{
int ch;
int cnt;
printf("*** Demonstrate kbhit() function ***\n\n");
printf("You must enter 10 characters: ");
fflush(stdout);
/* collect 10 characters plus allow for a newline */
while (1) {
if (10 <= (cnt = kbhit())) {
break;
}
}
printf("\n");
/* delete any 11th char, regardless of what it is */
if (cnt > 9) {
cnt = 10;
}
/* fetch the ten characters, and print them */
printf("The characters entered were: ");
while (cnt--) {
ch = getch();
printf("%c", ch);
}
while (1) {
printf("\n\n");
printf("*** Demonstrate getch() function ***\n\n");
printf(" Select Action\n");
printf(" 1 Run this program again.\n");
printf(" 2 Print this menu again.\n");
printf(" 3 Exit this program.\n\n");
printf(" Enter a selection: ");
fflush(stdout);
while (1) {
switch (ch = getch()) {
case '1': printf("\n\n"); main();
case '3': printf("\n\n"); exit(EXIT_SUCCESS);
case '2': break;
default: continue;
}
break;
}
}
/* flush stdin before returning to the shell command line. */
while (cnt--) {
ch = getch();
if ('\n' == ch || '\r' == ch) {
break;
}
}
return EXIT_SUCCESS;
}
No, non esiste il modo, in C Standard (non con l'attuale
standard ISO, non con il precedente standard ANSI), di
realizzare questa funzionalita` (input di un carattere da
console, senza attesa e senza eco); bisogna realizzarla,
sistema per sistema, in modo dipendente, appunto, da
ciascun sistema operativo usato.
Su entrambi i sistemi che nomini, questa funzionalita`
e` realizzabile; in Dos (se non vi e` migliore supporto
nella libreria del tuo compilatore), ad esempio, con
una delle funzioni dell'interrupt 21h; in Linux, settando
il driver del terminale (o pseudo-terminale) di input a
"crudo" ("raw"). Va verificata, se interessa, l'eventuale
interazione di questo "settaggio" con altre letture da
questo terminale, o pseudo-terminale; se quello che
si vuole e` leggere in questa modalita` una certa
sequenza di caratteri, ad esempio una password,
potrebbe essere piu` consigliabile operare in una
sequenza leggermente diversa:
-- setta l'input "tty" a "raw"
-- leggi gli N caratteri
-- resetta l'input "tty" a "cooked" (canonico)
piuttosto che non:
-- leggi N caratteri, per ciascuno:
-- setta a raw
-- leggi 1 carattere
-- resetta
che ha decisamente piu` overhead.
Su questo gruppo, o su it.comp.lang.c++, sono state
postate di recente routine di esempio per questo tipo
di compito; lo specifico argomento discusso era la
lettura di una password. Puoi consultare messaggi
passati su qualsiasi newsgroup con www.dejanews.com,
funzione "power search".
Alex