PDA

View Full Version : [C] Funzione getch(); su linux...


Starise
21-10-2006, 14:25
Salve ragazzi. Sto programmando su ambiente GNU/Linux, e sto avendo problemi sull'utilizzo della funzione getch(); (quella che su windows ferma l'esecuzione in attesa della pressione di un tasto da parte dell'utente!)

Cercando sulla rete ho scoperto che la stessa funzione non è presente (c'è un altra getch() inclusa in ncurses.h credo, ma non fa la stessa cosa!) - ma ho bisogno assolutamente di quella funzionalità!

Spero possiate darmi una soluzione (possibilmente funzionante anche su win, per la portabilità)!

ilsensine
21-10-2006, 14:52
fgetc?

Starise
21-10-2006, 15:07
ho già provato a fare:getc();
getc(stdin);
getchar(); ma non vanno! scusa ma fgetc non è per i file?

void Pausa(void)
{
int invio;
printf(" - Premi INVIO per continuare - \n");
invio = getchar();
}

ilsensine
21-10-2006, 15:17
scusa ma fgetc non è per i file?
File, stdin, socket, pipe...sono la stessa cosa ;)


void Pausa(void)
{
int invio;
printf(" - Premi INVIO per continuare - \n");
invio = getchar();
}
A me questo codice funziona...

Starise
21-10-2006, 15:34
Scusate, non capisco cosa sbaglio. Il codice di prima non funziona. Adesso l'ho modificato cosi:
void Pausa(void)
{
int invio;
printf(" - Premi INVIO per continuare - \n");
invio = fgetc(stdin);
} Continua a non andare!

PS: Sto su Gentoo Linux, compilo con gcc 4.1.1

ilsensine
21-10-2006, 15:37
Non saprei, qui va.
Provala come main() singola, ci deve essere un problema da qualche altra parte. In che senso non ti funziona? Non si blocca sulla fgets? Non risponde a <invio>?

Starise
21-10-2006, 15:45
Non si blocca sul fgetc. Però provata come main singola... funziona!
però è strano.... chiamata da questa main invece, non va:
main()
{
/* contiene la scelta dell'utente */
char scelta;

do
{
MenuPrincipale();
scanf("%c", &scelta);

if( scelta == '1' )
{
printf("scelta 1\n");
Pausa();
}
else if( scelta == '2' )
{
printf("scelta 2\n");
Pausa();
}
}while( scelta != '0' );

return (0);
}

Starise
21-10-2006, 15:52
if( scelta == '1' )
{
int invio;
printf(" - Premi INVIO per continuare - \n");
invio = fgetc(stdin);
}
non funziona! Allora il problema è in quel do-while? però io non lo vedo....

ilsensine
21-10-2006, 16:05
Non si blocca sul fgetc
Allora hai alcuni dati non ancora letti su stdin.

Starise
21-10-2006, 16:38
ho provato a riavviare la macchina, far partire il programma...
ma continua non funzionare... (anche togliendo il do-while)

cosa posso fare?

ilsensine
21-10-2006, 16:41
ho provato a riavviare la macchina, far partire il programma...
ma continua non funzionare... (anche togliendo il do-while)

cosa posso fare?
No, niente di così drammatico.
C'è un punto precedente del programma dove leggi dell'input dato dall'utente?

Starise
21-10-2006, 17:03
l'unica istruzione di lettura è
scanf("%c", &scelta); che vedi nella main postata sopra!

ilsensine
21-10-2006, 17:24
l'unica istruzione di lettura è
scanf("%c", &scelta); che vedi nella main postata sopra!
...e qui casca l'asino.
La scanf legge da stdin, che è line-buffered. Quindi nessun carattere viene passato alla scanf finché stdin con contiene una riga intera, <invio> incluso.
La scanf si ciuccia il suo bel %c, le la getchar legge \n.
Prova a sostituire la scanf con
scanf("%c\n", &scelta);

Starise
21-10-2006, 18:19
Ho provato cosi, ma alla scanf devo inserire 2 volte il valore prima che lo accetti. Dopodichè entrato in Pausa(), continua a non funzionare (ho controllato con printf il valore di "invio", in pratica prende il valore che sta in scanf.

Ti do un esempio dell'output:
::MENU PRINCIPALE::
1) Visualizza Contatto
0) Esci dal Programma
1
1
scelta = 1
(entro nella function Pausa)
- Premi INVIO per continuare -
invio = 1

::MENU PRINCIPALE::
1) Visualizza Contatto
0) Esci dal Programma

ilsensine
21-10-2006, 18:24
Allora rimetti la scanf come era prima; subito dopo la scanf metti questo:
while(getchar()!='\n');

E' un pò una ciofeca; per risolvere bene il problema dovresti usare le funzioni di i/o di linux.

Starise
21-10-2006, 18:37
while(getchar()!='\n');Facendo cosi, (finalmente) funziona! Ti ringrazio tantissimo per l'aiuto!
E' un pò una ciofeca; per risolvere bene il problema dovresti usare le funzioni di i/o di linux.
mi sapresti dire le librerie che posseggono queste funzioni? Cosi mi guardo i man.

Grazie ancora. :)

-fidel-
22-10-2006, 12:31
Facendo cosi, (finalmente) funziona! Ti ringrazio tantissimo per l'aiuto!

mi sapresti dire le librerie che posseggono queste funzioni? Cosi mi guardo i man.

Grazie ancora. :)

<unistd.h> (penso che ilsensine si riferisse a quelle).
Io inizierei con read e write: apri Konqueror e digita come indirizzo:
man:/read
o
man:/write

(la pagina di man che ti interessa è la prima, se ce n'è più d'una).
Oppure usa il "man" da console, ma ti consiglio Konqueror per 2 motivi:
1) dopo che hai digitato man:/ ti escono tutte le pagine di man disponibili come lista.
2) Puoi navigare nelle pagine di man come fossero ipertesto (utile soprattutto nella parte "See also", dove vengono citate le altre funzioni correlate: ti basta cliccare sulla funzione correlata di interesse e viene aperta in automatico la pagina di man associata).

71104
22-10-2006, 13:39
scusa ma perché una getchar semplice non va? io la uso sempre su Windows; l'unica cosa è che non ferma l'esecuzione alla pressione di un tasto qualsiasi, ma di Invio.

beppegrillo
22-10-2006, 14:11
fpurge x svuotare i buffer?

-fidel-
22-10-2006, 15:15
scusa ma perché una getchar semplice non va? io la uso sempre su Windows; l'unica cosa è che non ferma l'esecuzione alla pressione di un tasto qualsiasi, ma di Invio.

prova a fare:


#include <stdio.h>

int main(void)
{
int x;
scanf ("%d", &x);
printf("Premi INVIO per continuare...");
getchar();
}

-fidel-
22-10-2006, 15:22
fpurge x svuotare i buffer?

Ok, ma non bisogna chiamarla come
fpurge(stdin);
dal momento che non la fpurge (BSD 4.4) non è compatibile con linux. Bisogna fare:
__fpurge(stdin);
ma non è né standard né portabile.
meglio a questo punto fare
while (getchar() != '\n');
oppure usare una read (o altro) invece della scanf...

ilsensine
23-10-2006, 09:32
<unistd.h> (penso che ilsensine si riferisse a quelle).
Io inizierei con read e write: apri Konqueror e digita come indirizzo:
man:/read
o
man:/write

Oltre a read/write (che usano direttamente il file descriptor, senza passare per FILE * che può utilizzare una sua bufferizzazione interna), è possibile anche utilizzare le funzioni di termios.h per impostare diversi parametri per stdin (ad es. line/non line buffered, bloccante/non bloccante, con o senza echo ecc.)

trallallero
23-10-2006, 11:56
Salve ragazzi. Sto programmando su ambiente GNU/Linux, e sto avendo problemi sull'utilizzo della funzione getch(); (quella che su windows ferma l'esecuzione in attesa della pressione di un tasto da parte dell'utente!)

Cercando sulla rete ho scoperto che la stessa funzione non è presente (c'è un altra getch() inclusa in ncurses.h credo, ma non fa la stessa cosa!) - ma ho bisogno assolutamente di quella funzionalità!

Spero possiate darmi una soluzione (possibilmente funzionante anche su win, per la portabilità)!
da quello che scrivi quí e come lo risolvi dopo con l'aiuto degli utenti c'é qualche differenza :what:
la getch() che dici tu non aspetta l'invio ma un tasto qualsiasi mentre se ho capito bene hai risolto con la getchar() che aspetta un invio.
Se ti serve mi son fatto io una funzione che scimmiotta (:D) la getch() (lo anche giá postata in questo forum) e te la posso mandare. Usa i curses ... EDIT: errato, uso i termios :doh:
Ciao :)

trallallero
23-10-2006, 12:01
fpurge x svuotare i buffer?
fpurge é nonstandard e non portabile, inoltre, dal man:
was introduced in BSD 4.4 and is not available under Linux.
Meglio fflush ;)

ilsensine
23-10-2006, 12:02
Meglio fflush ;)
...che funziona solo sugli OUTPUT stream :)

trallallero
23-10-2006, 14:05
...che funziona solo sugli OUTPUT stream :)
la cosa mi perplime :D
veramente l'ho sempre usata anche per stdin ... probabilmente mi son sempre illuso che facesse qualcosa :what:

EDIT:

#include <stdio.h>

int main(void)
{
int x;
scanf ("%d", &x);
printf("Premi INVIO per continuare...");
/*fflush(stdin);*/
getchar();
}

invece funziona (su Sun almeno)
prova a mettere o togliere fflush() e vedi che cambia ;)

-fidel-
23-10-2006, 14:13
EDIT:

#include <stdio.h>

int main(void)
{
int x;
scanf ("%d", &x);
printf("Premi INVIO per continuare...");
/*fflush(stdin);*/
getchar();
}

invece funziona (su Sun almeno)
prova a mettere o togliere fflush() e vedi che cambia ;)

Su solaris va bene, su Linux no (come diceva ilsensine, funziona solo sugli stream di output).

trallallero
23-10-2006, 14:25
Su solaris va bene, su Linux no (come diceva ilsensine, funziona solo sugli stream di output).
strano! mi ricordo col Turbo C su MS andava anche con stdin ...

-fidel-
23-10-2006, 15:45
strano! mi ricordo col Turbo C su MS andava anche con stdin ...

Infatti su Win va bene, è su linux il "problema" :)

ilsensine
23-10-2006, 16:30
Infatti su Win va bene, è su linux il "problema" :)
http://www.iso-9899.info/wiki/Implementation

-fidel-
23-10-2006, 16:36
http://www.iso-9899.info/wiki/Implementation
Appunto, non a caso avevo virgolettato :)

trallallero
23-10-2006, 16:40
http://www.iso-9899.info/wiki/Implementation
fortuna che certi siti chiusi li riesco a leggere con un barbatrucco (google translate) :asd:

Comunque lo immaginavo, di solito chi impone restrizioni non lo fa per fare un dispetto :)
E per fortuna qui in banca non facciamo programmi con input da linea di comando :D

ilsensine
23-10-2006, 17:24
E per fortuna qui in banca non facciamo programmi con input da linea di comando :D
Bè non ci sarebbe nulla di male, basta evitare FILE * & co.

Il "problema" su fflush è solo uno dei tanti di questo standard. Va bene per i/o (semplice) da file, assolutamente inadeguato per gestire i/o interattivo (o operazioni di i/o avanzate da file).