Newsgroup: it.comp.lang.c
Titolo: Getch

Salve ancora una volta.
Sto cercando di riscrivere una funzione e mi sono trovato davanti ad un
problema che non riesco a risolvere. La funzione getch() restituisce il
carattere digitato sulla tastiera, ma cosa succede queando non viene
digitato alcun carattere? Per esempio, questo č un esempio di quello che mi
serviva:
int direction[2] = {0, 0};
int   AllowedMoves[4] = {72, 80, 75, 77};
void main(void)
{
  //BuildAll();
  for (;;)
  {
    while (!kbhit()) /* do nothing */;
    direction[0] = getch();
    if (direction[0] != direction[1])
    {
      direction[0] = direction[1];
      for (i = 0; i <= 4; i++)
      {
        if (direction[0] == AllowedMoves[i])
        {
          gotoxy(6, 6);
          printf("Rilevata pressione consentita");
          SleepEx(1000, true);
          clrscr();
        }
      }
    }
    else
    {
      gotoxy(6, 6);
      printf("Non cambiato");
      SleepEx(500, true);
      clrscr();
    }
  }
}
Il problema sta nel fatto che qualsiasi tasto prema, entra sempre nell'else
e quindi scrive sempre Non cambiato. Probabilmente il problema sta nel come
uso il getch. Qualcuno puň aiutarmi?
Grazie a tutti.
---
Ramses
---
icq:39860665
http://knowledgeparty.cjb.net
http://evilz0ne.cjb.net


Avendo dichiarato       int direction[]   non puoi usare getch() per
immettere i dati, ma devi usare
scanf() oppure gets() seguita da atoi().
Inoltre  gli indici per AllowedMoves[4] = {72, 80, 75, 77} vanno da zero
a 3.
HTH

 a 3.
Si, qui ho sbagliato. Grazie molte.



Se vuoi rilevare gli scan codes va bene getch(), con due alternative:
dichiarare direction come tipo char  oppure
ottenere il codice in una variabile di comodo e quindi fare un cast a
int
HTH

 int
turco ottomano e pure dialetale :-)) ossia...non ho capito nulla. Non sono
in grado di fare questa roba, penso che opterň per la prima. Grazie ancora.
---


 forse posso provare a fare questo.
Aspetta. Ma dopo aver preso il carattere devo usare atoi()?

 int
Questa è la schifezza che ho fatto:
void main(void)
{
  char direction[2];
  for (;;)
  {
    direction[0] = getch();
    if (direction[0] != direction[1])
    {
      direction[0] = direction[1];
      for (i = 0; i < 4; i++)
      {
        if (direction[0] == AllowedMoves[i])
        {
          gotoxy(6, 6);
          printf("Rilevata pressione consentita");
          SleepEx(1000, true);
          clrscr();
        }
      }
    }
    else
    {
      gotoxy(6, 6);
      printf("Non cambiato");
      SleepEx(500, true);
      clrscr();
    }
  }
}
Che ne dici? Il fatto è che fa sempre come prima, ossia entre sempre nel
ramo else e scrive sempre Non cambiato!. Che posso fare?
---


Forse questo va meglio:
void main(void)
{
  int direction[2] = {0, 0};
  for (;;)
  {
    while (kbhit() != 0)
    {
      direction[0] = getch();
      direction[0] = direction[1];
      for (i = 0; i < 4; i++)
      {
        if (direction[0] == AllowedMoves[i])
        {
          gotoxy(6, 6);
          printf("Rilevata pressione consentita");
          SleepEx(1000, true);
          clrscr();
        }
      }
    }
    gotoxy(6, 6);
    printf("Non cambiato");
    SleepEx(500, true);
    clrscr();
  }
}
Facendo il debug passo-passo sembra che anche dopo la getch() il valore di
direction[0] sia sempre 0 come da inisializzazione. Qualche idea???



Completo la risposta.
Per ottenere i caratteri speciali occorre testare il valore ritornato da
getch() per zero e,
in caso affermativo, fare una seconda lettura.
Vedi se ti può servire il codice che segue.
HTH
#include <stdio.h>
#include <conio.h>
int main(void) {
int ch;
fprintf(stderr,"Premi una delle frecce direzionali\n");
fprintf(stderr,"Premi Escape per terminare\n");
while ( (ch=getch()) != 27)
   {
   if (ch == 0)   {
      ch=getch();
      switch (ch) {
         case 72: fprintf(stderr,"Inserita freccia in alto\n");  break;
         case 80: fprintf(stderr,"Inserita freccia in basso\n"); break;
         case 75: fprintf(stderr,"Inserita freccia sinistra\n"); break;
         case 77: fprintf(stderr,"Inserita freccia destra\n");   break;
         default: fprintf(stderr,"Carattere non valido %d\n",ch);
         }
      }
   else   fprintf(stderr,"Carattere non valido %c %d\n",ch,ch);
   }
return 0;
}

 codes.
Usa un trucchetto tipo questo:
int  keyread ( void )
{
  int  k;
  if( !kbhit() )  return 0;
  k = getch();
  if( !k )        return 0x100 + getch();
  return k;
}
e poi usa queste define per i caratteri non ascii (magari fatti un .h):
#define F1          0x13B
#define F2          0x13C
#define F3          0x13D
#define F4          0x13E
#define F5          0x13F
#define F6          0x140
#define F7          0x141
#define F8          0x142
#define F9          0x143
#define F10         0x144
#define F11         0x185
#define F12         0x186
#define SHIFT_F1    0x154
#define SHIFT_F2    0x155
#define SHIFT_F3    0x156
#define SHIFT_F4    0x157
#define SHIFT_F5    0x158
#define SHIFT_F6    0x159
#define SHIFT_F7    0x15A
#define SHIFT_F8    0x15B
#define SHIFT_F9    0x15C
#define SHIFT_F10   0x15D
#define SHIFT_F11   0x187
#define SHIFT_F12   0x188
#define CTRL_F1     0x15E
#define CTRL_F2     0x15F
#define CTRL_F3     0x160
#define CTRL_F4     0x161
#define CTRL_F5     0x162
#define CTRL_F6     0x163
#define CTRL_F7     0x164
#define CTRL_F8     0x165
#define CTRL_F9     0x166
#define CTRL_F10    0x167
#define CTRL_F11    0x189
#define CTRL_F12    0x18A
#define ALT_F1      0x168
#define ALT_F2      0x169
#define ALT_F3      0x16A
#define ALT_F4      0x16B
#define ALT_F5      0x16C
#define ALT_F6      0x16D
#define ALT_F7      0x16E
#define ALT_F8      0x16F
#define ALT_F9      0x170
#define ALT_F10     0x171
#define ALT_F11     0x18B
#define ALT_F12     0x18C
#define ESCAPE      0x01B
#define LF          0x00A
#define ENTER       0x00D
#define RETURN      0x00D
#define BACKSP      0x008
#define DELETE      0x153
#define INSERT      0x152
#define HOME        0x147
#define END         0x14F
#define PGUP        0x149
#define PGDN        0x151
#define UPARR       0x148
#define DNARR       0x150
#define RIGHTARR    0x14D
#define LEFTARR     0x14B
#define TAB         0x009
#define SHFT_TAB    0x10F
#define CTRL_DELETE 0x193
#define CTRL_INSERT 0x192
#define CTRL_PGUP   0x184
#define CTRL_PGDN   0x176
#define CTRL_UPARR  0x18D
#define CTRL_DNARR  0x191
#define CTRL_LEFT   0x173
#define CTRL_RIGHT  0x174
#define CTRL_HOME   0x177
#define CTRL_END    0x175
#define CTRL_PAD5   0x18F
#define CTRL_RETURN 0x00A
#define CTRL_ENTER  0x00A
#define CTRL_ESCAPE 0x01B
#define CTRL_TAB    0x194
#define ALT_TAB     0x1A5
#define ALT_ESCAPE  0x101
#define ALT_ENTER   0x11C
#define ALT_RETURN  0x11C
#define ALT_BACKSP  0x10E
#define CTRL_A      0x001
#define CTRL_B      0x002
#define CTRL_C      0x003
#define CTRL_D      0x004
#define CTRL_E      0x005
#define CTRL_F      0x006
#define CTRL_G      0x007
#define CTRL_H      0x008
#define CTRL_I      0x009
#define CTRL_J      0x00A
#define CTRL_K      0x00B
#define CTRL_L      0x00C
#define CTRL_M      0x00D
#define CTRL_N      0x00E
#define CTRL_O      0x00F
#define CTRL_P      0x010
#define CTRL_Q      0x011
#define CTRL_R      0x012
#define CTRL_S      0x013
#define CTRL_T      0x014
#define CTRL_U      0x015
#define CTRL_V      0x016
#define CTRL_W      0x017
#define CTRL_X      0x018
#define CTRL_Y      0x019
#define CTRL_Z      0x01A
#define ALT_1       0x178
#define ALT_2       0x179
#define ALT_3       0x17A
#define ALT_4       0x17B
#define ALT_5       0x17C
#define ALT_6       0x17D
#define ALT_7       0x17E
#define ALT_8       0x17F
#define ALT_9       0x180
#define ALT_0       0x181
#define ALT_A       0x11E
#define ALT_B       0x11F
#define ALT_C       0x120
#define ALT_D       0x121
#define ALT_E       0x122
#define ALT_F       0x123
#define ALT_G       0x124
#define ALT_H       0x125
#define ALT_I       0x126
#define ALT_J       0x127
#define ALT_K       0x128
#define ALT_L       0x129
#define ALT_M       0x12A
#define ALT_N       0x12B
#define ALT_O       0x12C
#define ALT_P       0x12D
#define ALT_Q       0x12E
#define ALT_R       0x12F
#define ALT_S       0x130
#define ALT_T       0x131
#define ALT_U       0x132
#define ALT_V       0x133
#define ALT_W       0x134
#define ALT_X       0x135
#define ALT_Y       0x136
#define ALT_Z       0x137
ciao
donCiccio

Aspetta. Ma dopo aver preso il carattere devo usare atoi()?
Puoi usare la getch() per leggere i tasti cursore ed i tasti funzione,
tenendo presente che a differenza dei tasti normali, i tasti speciali
tornano due codici (come se fossero premuti due tasti), il primo e'
sempre 0 ed il secondo e' il codice da considerare:
while (1) {
  if (kbhit()) {	/* tasto premuto */
    if ((k = getch()) == 0) {	/* extended key */
      k = getch();	/* richiama per leggere lo scancode */
      switch (k) {
        case 0xCB: printf("Freccia sinistra\n");
        ...
      }
    } else {	/* tasto normale */
      switch (k) {
        case 0x0D: printf("Enter\n");
        case 0x1B: printf("Esc\n");
        ...
      }
    }
  }
}
NB: buttato li', non provato, e' un virus ecc...
qualche tempo fa si e' gia' discusso questo argomento, controlla i
post precedenti
ciao, acc.   
a...@libero.it

Ecco il codice un poco sistemato:
void main(void)
{
  int k;
  while (TRUE)
  {
    if (kbhit())
    { /* tasto premuto */
      if ((k = getch()) == 0)
      { /* extended key */
        k = getch(); /* richiama per leggere lo scancode */
        switch (k)
        {
          case 72:
          {
            clrscr();
            gotoxy(6, 6);
            printf("Freccia sinistra\n");
            SleepEx(1000, true);
            /*...*/
          }
        }
      }
      else
      { /* tasto normale */
        switch (k)
        {
          case 0x0D:
          {
            clrscr();
            gotoxy(6, 6);
            printf("Enter\n");
            SleepEx(1000, true);
            /*...*/
          }
        }
      }
    }
    else
    {
      gotoxy(6 ,6);
      printf("Nessun tasto premuto");
      SleepEx(1000, true);
      clrscr();
    }
  }
}
Funziona perfettamente cosě. Perň vorrei chiderti una cosa.
Tu hai scritto che la freccia sinistra č 0xCB, ossia 203 in decimale, e cosě
non funziona, io perň so che la freccia sinistra č 75, ossia 0x4b. Come mai?
Nella tabella che tu hai postato il 12 Giugno 2001 su questo ng č segnato
0xCB, mentre su di una tabella che ho trovato su 
www.asciitable.com
 si dice
che la leftarrow č 0x4b ossia 75 in decimale. C'č qualcos'altro oppure hai
la tabella sbagliata? A dire la veritŕ sulla tabella che tu hai dato c'č
scritto che 0x4b (cioč quella giusta) č lo scancode del KAYPAD 4. Come se
non bastasse questo, donCiccio ha gentilmente postato la sua lista che
riporta la freccietta come:
#define LEFTARR     0x14B
con un 1 in piů. Non capisco piů nulla :-)). L'unico funzionante per la
freccietta sinistra č 75 ossia 0x4b, gli altri no. Ma allora perchč queste
liste sono diverse?
Scusate il lungo post.


 ciao, acc.   
a...@libero.it


Leggendo su internet ho notato che 4b è MAKE mentre CB è break. Ma cosa
significa? Che differenze ci sono tra i due tipi?


Scusate il lungo post.
Probabilmente donCiccio ha fatto il mio stesso errore, probabilmente
lui non usa la getch() o la _bios_keybrd(), bensi' una funzione che si
e' scritto da se' (prassi piuttusto diffusa questa) che utilizzando
una delle due o intercettando direttamente l'IRQ 9 (tastiera) torna un
valore diverso.
Quel 0x14B e' abbastanza eloquente, si tratta di due byte 0x01 e 0x4B,
getch() non potra' mai tornare un valore del genere, a meno che non si
tratti di una particolare implementazione.
Bisogna tenere presente che stiamo parlando di funzioni NON STANDARD,
che spesso sono implementate diversamente dalle diverse case.
ciao, acc.   
a...@libero.it

significa? Che differenze ci sono tra i due tipi?
Non capisco cosa intendi dire, MAKE sarebbe un tasto ?
ciao, acc.   
a...@libero.it

 e' scritto da se' (prassi piuttusto diffusa questa) che utilizzando
no uso getch(), ma ho anche postato come.
riposto la mia funzione di lettura tasto per cui sono valide le define che
ho dato a Ramses
int  keyread ( void )
{
  int  k;
  if( !kbhit() )  return 0;
  k = getch();
  if( !k )        return 0x100 + getch();
  return k;
}
ciao
donCiccio

 liste sono diverse?
leggilo tutto il mio post, funzione 'keyread' compresa, e capirai da dove
esce quell'uno in piu'.
ciao
donCiccio

 ciao, acc.   
a...@libero.it


 ciao, acc.   
a...@libero.it
Grazie ancora.


 ho dato a Ramses
Scusa, č tutta colpa mia, non mi ero accorto del codice ed avevo visto solo
le define. Forse mi sono confuso pensando che fosse parte del msg a cui
avevi risposto. Scusami tanto.


il link te lo posto cosě magari capisci.
Tieni per buoni i codici della colonna MAKE.
I codici della colonna MAKE vengono inviati alla PRESSIONE del tasto,
quelli della colonna BREAK vengoni inviati al RILASCIO del tasto.
Le funzioni del BIOS 16h, pero', non rilevano il rilascio del tasto, e
nemmeno la getch() dato che utilizza queste funzioni per leggere da
tastiera.
ciao, acc.   
a...@libero.it

avere lo scan code? La prima torna zero e la seconda lo scan code?
Yes
ciao, acc.   
a...@libero.it

 ciao, acc.   
a...@libero.it
Ciao


 > ... Il fatto č che mi servirebbe per


 tolgli il problema del primo controllo dello 0???
esatto.
in qualsiasi linguaggio, si usano le funzioni anche per raggruppare in un
unico punto linee di codice ripetitive.
nel caso di lettura tasti con getch() tu devi ogni volta testare se il
valore ritornato e' zero nel qual caso devi richiamare getch per eliminare
dal buffer della tastiera lo scancode del tasto non ascii.
se nel tuo codice la lettura di un tasto e' presente in 100 punti diversi,
perche' ripetere sempre le stesse linee? meglio usare una funzione che fa
questa operazione.
la funzione che ho presentato restituisce un intero in cui i valori < di
0x100 (=256) sono i caratteri ascii, mentre quelli maggiori di 0x100 sono i
tasti funzioni o particolari combinazioni di shift-key.
quindi con una unica funzione faccio tutto
switch( readkey() )
{
case 'a':
case '2': // tasti ascii
case UPARR:
case HOME: // tasti speciali
case ALT_F:
case SHIFT_F1: // idem come sopra
}
ciao
donCiccio