Newsgroup: it.comp.lang.c
Titolo: Un equivalente Ansi C per la la getch() di CONIO:H

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)
-- 
Gargamella from Nonsense Delivering Service
remove *dinkyisland* from address to mail me

.
-- 
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;
}

(Uso compilatori GNU sotto Liunx e sotto DOS)
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