Newsgroup: it.comp.lang.c
Titolo: do...while

Nel codice seguente
int interfaccia2 (void)
{
    int a;
    do
                     {
     printf("\n\n\n1) Calcolare l'area del quadrato");
     printf("\n2) Calcolare l'area del triangolo");
     printf("\n3) Calcolare l'area del cubo");
     printf("\n4) Calcolare il volume del cubo\n\n\n");
     printf("Scegli la opzione di tuo interesse: ");
         scanf("%d",&a);
                    }  while (a < 1 || a > 4);
  return 0;
}
se introduco anzichč un numero una lettera o altro, č evidente come la "a"
rimanga indefinita!
Ora, una "a" indefinita non dovrebbe soddisfare la condizione a < 1 || a > ,
tuttavia questa condizione risulta verificata, visto che il ciclo si ripete.
Come mai?
Grazie

 rimanga indefinita!
Diciamo che le possibilita' sono 2, a seconda del compilatore o
dello standard che non mi ricordo. (Quindi probabilmente
e' vera solo una di queste 2), ma non importa...
1) a vale 0 (0vvero viene inizializzata dal compilatore)
2) a ha un valore praticamente casuale (dipende da quello
che c'e' nella memoria)
In ogni caso non ha un valore "indefinito" nel senso di "non numerico".
Se fallisce la scanf quindi e' probabile che a sia uguale o a 0
o a un numero tipo 66343453.
In ogni caso e' estremamente probabile che sia minore di 1 o maggiore di
  4...
Se vuoi premurarti puoi agire in diversi modi
1) assegnare preliminarmente un valore speciale ad a, tipo a=666;
2) controllare che la scanf abbia effettivamente letto qualcosa.
Tieni presente che la scanf in caso di successo dovrebbe ritornare, come
  valore, il numero di variabili effettivamente letto.
Quindi se 1!=scanf(...) c'e' stato qualche problema.
Non so se e' fatto apposta, ma nel codice sopra il valore di a viene
letto e poi dimenticato. Forse e' meglio definire la funzione
come int interfaccia(...) e poi alla fine invece di return 0;
mettere un return a;
ciao,
g.

 Come mai?
Come hai giustamente detto la conversione fallisce e quindi /a/ rimane
non inizializzata. Supponendo che sizeof(int) = 4, la variabile /a/ puo`
assumere 2^32 valori diversi. I valori della variabile che fanno
terminare il ciclo sono solo 4. La probabilita` che il ciclo termini
quando /a/ non e` inizializzata sono:
         4      1
P(T) =  ---- = ----
        2^32   2^30
La parte su cui sei in errore e` "una "a" indefinita non dovrebbe
soddisfare la condizione". Questo non e` assolutamente vero, anzi e`
molto piu` probabile che /a/ soddisfi quella condizione.
La soluzione consiste nel controllare il valore di ritorno di scanf, che
rappresenta il numero di conversioni effettuate con successo:
do {
        ....
        if (scanf("%d", &a) < 1)
                /* Conversione fallita */
                continue;
} while(a < 1 || a > 4);
Fai attenzione che con questo codice, nel caso di input non valido,
avrai un loop infinito. Supponi di digitare "x\n" (x + invio): scanf
fallisce la conversione, nel buffer dello stdin rimangono i caratteri
'x', '\n'; ricomincia il ciclo, la scanf cerca di rifare la conversione
su quegli stessi caratteri e fallisce...
Devi quindi mettere una cosa di questo tipo, per svuotare il buffer:
while(getchar() != '\n')
        /* Nothing */;
Nota che un problema simile lo avresti anche con un input valido. Se, ad
esempio, inserisci il numero '1', la scanf lascera` nel buffer il
carattere '\n' e la successiva conversione potrebbe fallire in modo
inaspettato (ad esempio se deve leggere una stringa).
Nel tuo caso, si riesce a cavarsela con getchar(), ma con input piu`
complessi e` consigliabile usare fgets() per leggere tutta la linea di
input e fare il parsing della stringa letta. Cosi`, anche in caso di
fallimenti di conversione, lo stdin rimane sempre in uno stato noto
(inizio della riga successiva).
Luca
-- 
Home: 
http://kronoz.cjb.net
K.R.O.N.O.S
Kinetic Replicant Optimized for Nocturnal Observation and Sabotage

                     }  while (a < 1 || a > 4);
      printf("Scegli la opzione di tuo interesse: ");
      do { 
        int test=scanf("%d",&a);
        scanf("*[^\n]");
      } while (test==0);
 
            }  while (a < 1 || a > 4);
-- 
Horst

 } while(a < 1 || a > 4);
Non ho ben capito: che nesso c'č tra il valore ritornato da scanf, che ho
capito bene essere il valore di conversioni fatte con successo, con il
nostro problema?
Cioč: qualunque numero venga assegnato ad "a" da scanf, sempre rimane 1 il
valore ritornato da scanf, no?
Grazie

 valore ritornato da scanf, no?
Se la scanf non restituisce 1 (conversione fallita) il valore di /a/ non
e` definito, quindi non deve essere fatto il test (a < 1 || a > 4),
infatti viene forzata un'altra iterazione (continue). La condizione sul
valore di ritorno di scanf serve per discriminare tra input valido ed
input non valido.
Se invece la conversione ha successo viene valuta la condizione del
while, che e` quella che discrimina tra opzioni numeriche accettabili e
non.
Luca
-- 
Home: 
http://kronoz.cjb.net
"Ricorda sempre che sei unico, esattamente come tutti gli altri".

 non.
Benissimo. Grazie

 infatti viene forzata un'altra iterazione (continue).
Una sola cosa..anzi due.
1) continue, è una istruzione che serve per forzare una iterazione
prescindendo dalla condizione while??
2)
int interfaccia2 (void)
{
    int a = 1;
    do
                     {
     printf("\n\n\n1) Calcolare l'area del quadrato");
     printf("\n2) Calcolare l'area del triangolo");
     printf("\n3) Calcolare l'area del cubo");
     printf("\n4) Calcolare il volume del cubo\n\n\n");
     printf("Scegli la opzione di tuo interesse: ");
         scanf("%d",&a);
                    }  while (a < 1 || a > 4);
  return 0;
}
questo codice, pensavo, avrebbe dovuto comportarsi così: se la conversione
avviene, allora a prende il nuovo valore numerico e passa alla while la
verifica della condizione. Se viene introdotta una lettera o altro carattere
sbagliato, alla a rimane il valore di 1 e così parte automaticamente
l'opzione 1. IN realtà ciò non avviene. Penso perchè la scanf, se non fa una
conversione, cmq sovrascrive a con un valore "indefinito" ed
"imprevedibile". Giusto?
Grazie

 infatti viene forzata un'altra iterazione (continue).
Una sola cosa..anzi due.
1) continue, è una istruzione che serve per forzare una iterazione
prescindendo dalla condizione while??
2)
int interfaccia2 (void)
{
    int a = 1;
    do
                     {
     printf("\n\n\n1) Calcolare l'area del quadrato");
     printf("\n2) Calcolare l'area del triangolo");
     printf("\n3) Calcolare l'area del cubo");
     printf("\n4) Calcolare il volume del cubo\n\n\n");
     printf("Scegli la opzione di tuo interesse: ");
         scanf("%d",&a);
                    }  while (a < 1 || a > 4);
  return 0;
}
questo codice, pensavo, avrebbe dovuto comportarsi così: se la conversione


 "imprevedibile". Giusto?
Sbagliato! Ho verificvato che a conserva l'ultimo valore numerico valido.
Usando questa
int main(void)
{
    int a = 2;
    do
                     {
     printf("\n\n\n1) Calcolare l'area %d del quadrato",a);
     printf("Scegli la opzione di tuo interesse: ");
         scanf("%d",&a);
                    }  while (a < 1 || a > 4);
  return 0;
}
ho potuto "spiare" il valore di a ad ogni ciclo ed ho visto che se scanf
ritorna 0, a rimane al numerico valido precedente....
E' tutto giusto?

 Sbagliato! Ho verificvato che a conserva l'ultimo valore numerico valido.
Ho dato un'occhiata veloce allo standard e mi pare un po' vago. Nelle
*scanf pare che la scrittura sull'oggetto passato avvenga dopo che il
match con lo specificatore di conversione e` stato fatto con successo.
Quindi se la conversione non e` avvenuta la variabile passata
dall'utente dovrebbe essere immodificata, ma non ne sono sicuro 100%.
Luca
-- 
Home: 
http://kronoz.cjb.net
Not an editor command: Wq

Kronos ha scritto:

In ogni caso, una cosa è chiara: il valore di quella variabile, quale esso
sia, non ha NESSUN significato, quindi non dovrebbe MAI essere utilizzato in
alcun modo.
Per sapere se una scanf è andata bene o male, si deve controllare il valore
ritornato dalla funzione.
--
Cingar
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 dall'utente dovrebbe essere immodificata, ma non ne sono sicuro 100%.
Dove hai controllato? Hai un link allo standard?
GHrazie

 Dove hai controllato? Hai un link allo standard?
Ho comprato lo standard sul sito dell'ISO (la versione PDF). In rete si
trovano le copie dell'ultimo draft prima della ratifica (usa google).
Luca
-- 
Home: 
http://kronoz.cjb.net
La mia opinione puo` essere cambiata, ma non il fatto che ho ragione.