Newsgroup: it.comp.lang.c
Titolo: scanf maledetta

Ciao a tutti sono uno studente di ing edile alle prese con l'esame di
informatica è superfluo dunque dirvi che sono più che dilettante, mi trovo
alle prese con un esercizio in cui si devono fornire, i lati di un
triangolo, e il programma deve stabilire se tali dati sono effettivamante i
lati di un triang inoltre stabilire il tipo di triang  calcolare area e
perimetro; sembrava che fossi riuscito a farcela, invece, dopo aver
compilato il programma, in fase di esecuzione, mi si presenta un problema
incredibile, di cui non so spiegarmi il motivo (il problema è descritto
all'interno del prog).
Se qualcuno volesse aiutarmi lo ringrazio anticipatamente.
#include<Stdio.h>
#include<math.h>
double ipotenusa(double cat, double bas);
main()
{
double i,c,perim,a,b;
int stato=1;
char car;
while(stato==1)
{                                                                    //
inizio ciclo
printf("digita il valore del primo lato ");
scanf("%f", &a);
printf("\ndigita il valore del secondo lato ");
scanf("%f", &b);
printf("\nse il triangolo e' rettangolo i dati digitati sono sufficienti,
altrimenti devi digitare un'altro lato\nil triangolo e' rettangolo? Y/N :
");
scanf("%c", &car);
if (car=='n')
{   //iniz b1 che viene eseguito solo se non e' rettangolo
}   //fine b1
else           //opzione che esegue solo se è un triangolo rettangolo
{
i=ipotenusa(a,b);
perim=a+b+i;
printf("I dati del triangolo rettangolo sono:\n\n-LATI = %f %f
%f\n-PERIMETRO = %f", a,b,i, perim);
}
car='p';
stato=2;
printf ("\nVuoi eseguire un'altra operazione? Y/N: ");
/*se si giunge a questo punto provenendo dal blocco1 dell'istruzione if, il
tutto si svolge regolarmente,
mentre se si giunge dal ramo else, "l'istruzione incriminata" seguente non
viene presa in considerazione
cioè non mi si chiede di immettere nessun valore e si entra direttamante
nello switch,
conseguentemente sul output appare la seguente scritta:
Vuoi eseguire un'altra operazione? Y/N:
il carattere digitato non e' valido
Vuoi eseguire un'altra operazione? Y/N:   e solo ora mi chiede di digitare
un carattere,
dopodicchè il ciclo si ripete o termina regolarmente a seconda del carattere
digitato.
A me sembra una cosa incredibile e non sono riuscito a spiegarmi il
perchè.*/
/*istruzione icriminata*/scanf("%c", &car);
while (stato==2)
{
switch(car)
      {
      case 'n' : stato=0;
      break;
      case 'y' : stato=1;
      break;
      default: {printf("\nil carattere digitato non e' valido");
                stato=2;
                printf ("\nVuoi eseguire un'altra operazione? Y/N: ");
                scanf("%c", &car);}
       }
}
}//fine ciclo
printf("Fine della sessione");
}//fine main
double ipotenusa(double cat, double bas) // definizione funzione ipotenusa

 ha scritto nel messaggio
news:2fQt6.79930$lj4.2...@news6.giganews.com...


 ha scritto nel messaggio
news:2fQt6.79930$lj4.2...@news6.giganews.com...

Puoi provare a mettere dopo ogni scanf la seguente riga:
while(getchar!='\n');
Per maggiori ragguagli puoi guardare la FAQ che trovi su
www.programmazione.it

Vediamo se riesco a non dire troppe fesserie sul funzionamento di scanf:
scanf divide il set di caratteri in 2 categorie, white space e non white
space.
i white space sono i caratteri tipo lo spazio, il return, il line feed, il
form feed, la tabulazione, etc,
i non white space tutti gli altri.
i white space sono usati per determinare inizio e fine dei campi da
convertire, per tutti i tipi eccetto "%c", che legge un qualsiasi carattere.
Il primo carattere white space dopo un campo convertito rimane dispoibile
nello stream in uso per il prossimo campo o per la prossima funzione di
lettura.
quindi supponiamo un input tipo "  123 \n\n ciao a tutti ":
una prima scanf fatta con format string "%d" cerca nello stream in uso il
primo carattere che non sia un white space (il carattere 1), e scarta quindi
i primi due spazi iniziali, essendo il campo numerico "%d" scanf considera
facenti parte del primo campo tutti i caratteri numerici consecutivi, fino
al primo non numerico (spazio),
una seconda scanf fatta con format string "%s" si trova ad analizzare lo
stream dallo spazio dopo il (3) cioe' dove si era fermata la prima scanf,
non essendo un %c", fa come la precedente, prima si cerca il primo carattere
non white space,e poi prende per buono qualsiasi carattere fino al primo
white space, il campo letto varra' "ciao" tutto il resto prima e' stato
scartato da scanf,
a questo punto una terza scanf con format string "%c", parte ad analizzare
lo stream dal primo spazio dopo "ciao", ma e' una "%c" per la quale tutto
vanno bene anche i white space, quindi il valore letto sara' proprio lo
spazio, restano nello stream, non letti e disponbilii per la prossima scanf,
tutti i caratteri a partire da "a tutti ".
se la seconda scanf fosse stata "%d" sarebbe fallita dopo la ricerca del
primo carattere non white space, cioe' la (c), perche non e' un carattere
numerico, lasciando questo carattere disponibile alla terza scanf, ma
eliminando i white space precedenti.
mi sa che piu' che dare un aiuto, ho incasinato le idee :-)
ciao
donCiccio

Anch'io ho avuto questo problema con scanf, che bufferizza l'Enter e a
volte crea problemi.
Mi hanno passato un trucchetto:
se metti un tabulatore \t all'inizio dello scanf il problema si risolve
Es: scanf("\t%d", &valore);
Non so perche' ma funziona ;-)
ciao
Christian

 ha scritto nel messaggio
news:3ABDE585...@yahoo.com...

Se é per questo va bene anche
scanf("%d%d",&num)
scanf("  %d",&num)

 scanf("%d%d",&num)
mmhhh...
spiega un po cosa vorresti fare con questa istruzione? crashare il sistema
presumo...
ciao
donCiccio

 ha scritto nel messaggio
news:99nu2v$ekk$1...@nreadA.inwind.it...

opppsss scanf("%d%c",&num);
cos' crasha?


certo che si! il numero di parametri passati alla scanf deve corrispondere
ai campi immessi nel format string.
Qui hai comunque 2 campi da leggere "%d%c", ma un solo indirizzo in cui
scrivere il primo valore, il secondo indirizzo verra' preso a caso da scanf,
con risultati imprevedibili.
ciao
donCiccio

con risultati imprevedibili.
Volevo solo aggiungere che se si vuole leggere qualcosa e ignorarne il
valore basta usare "*" subito dopo il segno di "%" ... ad esempio con
"%d%*c". In questo caso non si devono passare due puntatori perche'
scanf e' informata del fatto che il valore letto deve essere buttato.
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 ha scritto nel messaggio
news:pnmw6.35609$lT1.5...@news2.tin.it...

scanf("%d%*c",&num);
e cosě?

 e così?
SEI TROPPO FORTE! :-)
peccato che ha risposto prima Griffini....
ciao
donCiccio

...


 formattare l'hard disk, ma io non ci credo.
Il comportamento di fflush() su stream di input _non_e'_definito_, il che
vuol dire che potrebbe *in teoria* accadere qualsiasi cosa; ma da qui a
dire che potrebbe formattarti l'hd ce ne passa...
-- 
 Ciao, Bianco.
 Reply to luca.bianco (at) 
tiscalinet.it

formattare l'hard disk, ma io non ci credo.
qui mettiamo tutti i condizionali possibili, perchè non sono
sicurissimo di quello che dico. Cmq se ricordo bene non è possibile
effettuare fflush() su stdin, pena un undefined behaviour: questo
significa che il compilatore potrebbe inserire qualunque cosa in quel
codice e non è detto che funzioni: quindi potrebbe inserire anche il
codice per formattare l'HD, anche se era evidentemente una battuta.
Anto
--
Antonio Cuni, 18 anni, studente
Brainbench Certification: 
Master C++: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
http://www.brainbench.com/transcript.jsp?pid=1301688


La soluzione ideale é sempre la:
while(getchar()!='\n');
dopo la scanf.....é portabile, sicura ed é approvata dalla associazione
programmatori C di cotale newsgroup!!!!!