Newsgroup: it.comp.lang.c
Titolo: problema con getchar

Salve a tutti.
Ho un piccolo problema con getchar.
Il codice qui sotto stampa un menu e aspetta la scelta. Se metto 4 esce,
altrimenti fa qualche cosa.
Se lo compilo utilizzando la scanf funziona tutto bene.
Se invece lo compilo utilizzando la getchar, quando riscrive il menu lo
riscrive due volte!!!
Purtroppo devo usare la getchar per forza.
Dove sbaglio??
Grazie
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char ch=' ';
  while (ch != '4') {
   printf("Fai una scelta\n");
   printf("1 ...\n");
   printf("2 ...\n");
   printf("3 ...\n");
   printf("4 Exit\n");
/* ch = getchar(); */
   scanf("%s",&ch);
   switch (ch) {
    case '1': printf("Hai scelto 1\n"); break;
    case '2': printf("Hai scelto 2\n"); break;
    case '3': printf("Hai scelto 3\n"); break;
    }
 }
return (0);
}

 ha scritto nel messaggio
news:8f9ya.202525$K35.4...@news2.tin.it...


 e sei apposto :)
Sbagliato: funziona solo su alcuni sistemi dove stdin e' implementato come
un file normale. fflush(stdin) e' undefined behaviour per standard, ovvero
potrebbe fare qualsiasi cosa (anche formattarti l'HD e sarebbe ancora
ammesso da standard).
La soluzione portabile consiste nel fare un "while(getchar() != '\n');"
oppure usare una fgets che si occupa automaticamente di raccogliere
caratteri fino alla newline.
-- 
Mox
"Trust the programmer."
"Don't prevent the programmer from doing what needs to be done."
"Keep the language small and simple."
"Provide only one way to do an operation."

 caratteri fino alla newline.
azz questa mi mancava :) Buono a sapersi :P
Saluti


Allochi spazio per un carattere e poi leggi una stringa:
la scanf andra' a scrivere all'indirizzo puntato da &ch sia il carattere
letto sia il carattere di fine stringa '\0' (se non anche il return '\n').
Quindi, vai a scrivere 2 (o addirittura 3) byte in una variabile per cui e'
allocato 1 byte.
Questo puo' portare ad errori in fase di esecuzione.
Ciao,
Ema

 quindi prima della getchar() usa l'istruzione  fflush(stdin);
Ho provato, ma si comporta come prima.

 caratteri fino alla newline.
Forse non ho capito: in pratica non posso uscire dal ciclo digitando 4, ma
solo premendo Invio?
P.S.
come lo implemento il ciclo?
P.P.S.
E usando una chiamata di sistema read al posto di getchar???

 ha scritto nel messaggio
news:MKmya.205714$K35.4...@news2.tin.it...

Questa funzia:
-------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main (void) {
  char ch=' ';
  while (ch != '4') {
    if (ch != '\n') {
      printf("Fai una scelta\n");
      printf("1 ...\n");
      printf("2 ...\n");
      printf("3 ...\n");
      printf("4 Exit\n");
    }
    ch = getchar();
    switch (ch) {
    case '1': printf("Hai scelto 1\n"); break;
    case '2': printf("Hai scelto 2\n"); break;
    case '3': printf("Hai scelto 3\n"); break;
    }
  }
  return (0);
}
-------------------------------------------
Il malfunzionamento era dovuto a questo fatto:
la getchar() fa continuare l'esecuzione quando riceve il return, pero' si
ricorda tutti i caratteri digitati, return compreso
Quindi digitando qualcosa tipo
1<INVIO>
Il ciclo while veniva eseguito (e viene eseguito anche dal codice postato!)
2 volte, la prima per il carattere '1', la seconda per il carattere '\n'.
Solo che adesso, nel ciclo c'e' un if che discrimina gli altri caratteri da
'\n'.
Ciao,
Ema

 ricorda tutti i caratteri digitati, return compreso
Non avevo tenuto conto che la getchar e' buffered e con echo.
Ma in ANSI C c'e' una funzione per prendere un carattere che sia unbuffered
e senza echo?
P.S-
Provando e riprovando mi e' venuta in mente anche una variante utilizzando
gets per svuotare il buffer, in pratica ch prende solo il primo carattere
digitato. Ecco:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
char ch;
char junk[80];
while (ch!='4') {
  printf("Scegli\n1 ...\n2... \n3 ...\n4 Exit\n");
  ch=getchar();
  gets(junk);
  switch (ch) {
   case '1': printf("Hai premuto 1\n"); break;
   case '2': printf("Hai premuto 2\n"); break;
   case '3': printf("Hai premuto 3\n"); break;
   case '4': printf("Bye bye"); break;
   default : printf("Error\n"); break;
  }
}
return (0);
}
Ciao