Supporta il tuo Forum su Patreon!
 
  > Register  
  > Calendar  
  > Members List  
 
  > Supporta il Forum  
  > Today's Posts  
   

Go Back   netgamers.it > Tech & Tech > Developer's Zone

Reply
 
Thread Tools Rate Thread
Old 13th December 2010, 17:29   #1
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,581
[Impariamo il C] Lezione 7

Buongiorno.

Nelle puntate precedenti del corso collaborativo di programmazione:
  1. installazione dell'IDE, cenni di architettura degli elaboratori
  2. sintassi del C, programmazione strutturata
  3. ancora sulla sintassi, i tipi di dato, le variabili
  4. variabili parte seconda: gli array
  5. introduzione delle funzioni
  6. operatori aritmetici e logici
In questo capitolo:
  • costrutti di selezione

Costrutti di selezione

Nelle puntate precedenti ci è capitato spesso di dover affrontare situazioni in cui, in base ai dati che ci troviamo in mano, dobbiamo eseguire certe istruzioni piuttosto che altre. Dobbiamo, in altre parole, selezionare le istruzioni da intraprendere, sulla base di scelte logiche.

Ecco quindi motivata l'analisi degli operatori logici: saranno proprio essi a istruire il programma su come procedere in alcuni punti chiave del nostro codice.


Il tipo più semplice è il costrutto SE...ALLORA, nel quale eseguiamo un blocco di codice SOLAMENTE SE è verificata la condizione specificata. Ecco la sintassi C:

Code:
if ( condizione )  {
  // codice da eseguire..
 }
dove condizione può essere qualunque espressione valutata con un operatore logico, cioè che ritorna vero o falso.

Ricordiamoci ora come si rappresentano vero e falso in C: con 1 e 0. Ecco, quindi, perché molto spesso le funzioni ritornano un valore intero, nel quale il significato dello zero è "qualcosa non ha funzionato". Prendiamo un esempio: se io avessi una funzione trova_parola che cerca una stringa dentro una stringa più grande

Code:
trova_parola( "tapioca", "terapia tapioca come fosse antani" )
potrei dire a questa funzione di ritornare un intero che corrisponde alla posizione della parola cercata (in questo caso tapioca, posizione 9); farei corrispondere lo zero al concetto di "parola non trovata". In questo modo, potremmo scrivere codice semanticamente molto chiaro

Code:
if ( ! trova_parola( "tapioca", "terapia tapioca come fosse antani" ) ) {
   // codice da eseguire se non trova la parola 
}
che, in linguaggio naturale, si tradurrebbe con "se non trovi la parola tapioca in quella frase, esegui questo codice".


Abbiamo già visto che il costrutto SE...ALLORA in C prevede anche la possibilità di specificare una alternativa. In effetti il costrutto completo è SE...ALLORA...ALTRIMENTI secondo questo schema a blocchi:



Se la condizione di test è vera facciamo il blocco di istruzioni del then, altrimenti quello dell'else. La sintassi è come segue:

Code:
if ( condizione ) {
    // blocco THEN..
} else {
    // blocco ELSE..
}
Ma si può andare oltre come costrutti. Mettiamo che i nipotini di Paperino vogliano farsi il manuale delle Giovani Marmotte digitale, ognuno con le sue personalizzazioni. Il manuale, come prima cosa, dovrebbe riconoscere quale tra Qui, Quo e Qua lo sta utilizzando. Il programma non dovrebbe più risolvere uno schema SE...ALLORA, perché le condizioni sono 3:

Code:
if ( utente == QUI ) {
   // codice per Qui
} else {
   ..?
}
come fare? la prima soluzione, forse la più spontanea, è la cosidetta nidificazione, nella quale mettiamo blocchi dentro blocchi:

Code:
if ( utente == QUI ) {
   // codice per Qui
} else {
   if ( utente == QUO ) {
      // codice per Quo
   } else {
      // codice per Qua
   }
}
questa soluzione funziona, e corrisponde a questo diagramma di flusso:



Anche se il codice funziona, non è detto che sia la soluzione migliore. In particolare, può infastidire l'asimmetria tra i due blocchi condizionali. Non è una questione estetica, ovviamente, ma di organizzazione del codice. Ricordiamoci che potremmo doverci rimettere le mani, e richiamare alla mente tutti i sotto-flussi nidificati può essere disagevole.

Una possibile sintassi alternativa, che "appiattisce" il diagramma, è questa:

Code:
if ( condizione1 ) {
    // blocco THEN..
} else if ( condizione2 )  {
    // blocco ELSE2
} else { 
    // blocco ELSEN..
}
che, in linguaggio naturale, diventa "se si verifica la condizione1 fai questo, altrimenti se si verifica la condizione2 fai quest'altro. Se proprio non si verifica niente, fai quest'altro ancora.

Si osservi che la sintassi "else if" permette di metterne infiniti a cascata, quindi possiamo fare tutti i rami decisionali che preferiamo.


L'if..then..else si presta benissimo per condizioni semplici, ma al crescere delle condizioni può diventare caotico. Esiste un altro costrutto di selezione chiamato switch, che funziona per selezioni multiple. Guardiamo la sintassi e analizziamola:

Code:
switch ( espressione ) {

   case costante1:
      // codice se espressione == costante1
   break;

   case costante2:
      // codice se espressione == costante2
   break;

   ...

   default:
      // codice se nessuna espressione corrisponde alle costanti
   break;

}
In sostanza, noi forniamo una espressione da confrontare con un elenco di costanti (cioè di non variabili). Lo switch le confronta una per una e, se ne trova una uguale, esegue il blocco di codice corrispondente fino al break. Il break fa saltare l'esecuzione subito fuori dallo switch.

Nel caso nessuna delle costanti sia uguale all'espressione, viene eseguito il codice "default".

Giocherellando con i break, è possibile far collassare più situazioni in una sola. Ad esempio:


Code:
switch ( espressione ) {

   case costante1:
   case costante2:
   case costante3:
      // codice se espressione == costante1 o costante2 o costante3
   break;

    case costanteK:
      // codice se espressione == costanteK
   break;

   ...

     default:
      // codice se nessuna espressione corrisponde alle costanti
   break;

 }
Esiste infine un terzo costrutto di selezione, partorito dalle menti più perverse del genere umano: l'operatore ternario. Vi mostro la sintassi, e poi dimenticatela

Code:
variabile = condizione?  espressione1 : espressione2
In sostanza, se la condizione è verificata variabile diventa espressione1; espressione2 altrimenti.

L'operatore ternario è nidificabile, il che può generare codici di rarissima illeggibilità. Ecco un esempio:

Code:
int main( int argc, char* argv[] ) {

    int value = (1<2)?
                    (3>4)?
                        1 : 2 : 3;

    printf("%d", value);

   return 0;
}
Senza compilarlo (esercizio 1), che risultato darà?


Esercizio 2: scrivere un codice che, letti tre valori (interi) A, B e C stampi "diofantea!" se A*A = B*B + C*C, "non diafantea" altrimenti.

Il programma, inoltre, ritorni 0 se è diofantea, -1 se non lo è.



__________________
Lode a Bacco, in saecula saeculorum.
Emergent
Arësius is online now   Reply With Quote
Old 13th December 2010, 17:47   #2
[NiGhTmArE]
Zappel
 
[NiGhTmArE]'s Avatar
 
Join Date: Jan 2000
Location: Tivoli / Campobasso
Posts: 53,292
cacchio già la 7, devo leggermi la 6 io

a frappè
__________________
instantempo
Giochi Flash | Userbars Maker Musinvi: Video Musicali Fattori Arcani
M. ♕ Queen of Agorà ♕ G.
Frappr is dead
[NiGhTmArE] is offline   Reply With Quote
Old 13th December 2010, 18:29   #3
uizz
Registered User
 
uizz's Avatar
 
Join Date: Jan 2010
Posts: 513
la sintassi del primo esercizio non l'avevo mai vista

provo a dare la soluzione:

Spoiler:
è giusto 2? Perché la prima condizione è vera mentre la seconda è falsa, quindi scala di uno, credo
uizz is offline   Reply With Quote
Old 13th December 2010, 18:35   #4
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,581
Quote:
Originally Posted by uizz View Post
la sintassi del primo esercizio non l'avevo mai vista

provo a dare la soluzione:

Spoiler:
è giusto 2? Perché la prima condizione è vera mentre la seconda è falsa, quindi scala di uno, credo
bravo uizz fammi il secondo esercizio, che è quello veramente utile.
__________________
Lode a Bacco, in saecula saeculorum.
Emergent

Last edited by Arësius; 13th December 2010 at 18:36.
Arësius is online now   Reply With Quote
Old 13th December 2010, 19:58   #5
Cece
- - - - - - - - - - - -
 
Cece's Avatar
 
Join Date: Apr 2002
Posts: 21,292
ok ho indovinato quasi per caso la soluzione al 2 .. poi compilando e cambiando valori mi era nato un dubbio e non capivo dove sbagliavo , poi ho capito definitivamente imparando che e meglio iniziare a leggere il codice dalla condizione interna ..
Non mi piace però come è stato tabulato il codice .. secondo me esistono maniere migliori .. ora indago ..
io farei una cosa del genere
Spoiler:
Code:
    int value = (1<2)?
                    (5>4)? 1 : 2 
                    : 3;


Ora mi metto a fare l' altro esercizio..

edit: non riesco a trovare esempi di ternari annidiati , quei pochi che trovo sono scritti su una linea che trovo nettamente migliore della tabulazione del esercizio ..
edit2: niente non trovo esempi , vado a cena e dopo faccio esercizio..

Last edited by Cece; 13th December 2010 at 20:16.
Cece is offline   Reply With Quote
Old 13th December 2010, 20:55   #6
nanomad
Dietro le sbarre
 
nanomad's Avatar
 
Join Date: Apr 2005
Location: Papia (olim Ticinum)
Posts: 5,221
E secondo te era stato indentanto per aiutarti? Povero stolto

Che quel codice vi serva per capire quanto è utile indentare con criterio e quanto possa fare schifo l'operatore ternario!
Tra l'altro mettere qualche parentesi in piu' è che renda il programma piu' pesante
__________________
Rivuoi i video nel forum? Usa questa estensione (chrome)
Source & firefox version
"(...) the three great virtues of a programmer: laziness, impatience, and hubris." -- LarryWall

Last edited by nanomad; 13th December 2010 at 20:57.
nanomad is offline   Reply With Quote
Old 13th December 2010, 21:14   #7
spkbri
PiriPiri ( A molla )
 
spkbri's Avatar
 
Join Date: Feb 2010
Location: Torino - Valenza (AL)
Posts: 10,357
la mia versione dell es2:

Spoiler:

Code:
#include <stdio.h>
main(){
	int a,b,c;
	printf("Inserisci A\n");
	scanf("%d",&a);
	printf("\nInserisci B\n");
	scanf("%d",&b);
	printf("\nInserisci C\n");
	scanf("%d",&c);
	if(a*a==b*b+c*c){
		printf("\nDiofantea!\n");
		return (0);
	}
	else{
		printf("\nNon diofantea\n");
		return (-1);
	}
}
__________________
|||||||||| SoundCloud
La mia è una logica ferrea e sempre coerente, basta riuscire ad entrare nei suoi meccanismi, poi alla fine la capisci ||||||||- Licher, 2016

Last edited by spkbri; 13th December 2010 at 22:55.
spkbri is offline   Reply With Quote
Old 13th December 2010, 21:56   #8
Cece
- - - - - - - - - - - -
 
Cece's Avatar
 
Join Date: Apr 2002
Posts: 21,292
ma per curiosità e possibile mettere 2 comandi in un operatore ternario o sto provando qualcosa di impossibile ?
Cece is offline   Reply With Quote
Old 13th December 2010, 22:23   #9
Cece
- - - - - - - - - - - -
 
Cece's Avatar
 
Join Date: Apr 2002
Posts: 21,292

Spoiler:
Code:
#include <stdio.h>
#include <stdlib.h>

int main( int argc, char* argv[] ) {

    int a,b,c;
    printf("Lezione 7 corso NGI \n");
    printf("Inserisci valore A\n");
    scanf("%d",&a);
    printf("Inserisci valore B\n");
    scanf("%d",&b);
    printf("Inserisci valore C\n");
    scanf("%d",&c);
    (a*a == b*b + c*c)?printf("diofantea!\n"):printf("non diafantea\n");
    system("pause");
    return(a*a == b*b + c*c)? 0:-1;
}


come faccio a testare il return? devo rinominarla in un altra funzione e poi faccio un test tramite il main ? o c'è un altro modo ?

ok done ..
codice con la prova del return
Spoiler:
Code:
#include <stdio.h>
#include <stdlib.h>

int prova();

int main( int argc, char* argv[] ) {

    printf("\nRisultato return : %d\n\n",prova());
    system("pause");
}

int prova(  ) {

    int a,b,c;
    printf("Lezione 7 corso NGI \n");
    printf("Inserisci valore A\n");
    scanf("%d",&a);
    printf("Inserisci valore B\n");
    scanf("%d",&b);
    printf("Inserisci valore C\n");
    scanf("%d",&c);
    (a*a == b*b + c*c)?printf("diofantea!\n"):printf("non diafantea\n");
    return(a*a == b*b + c*c)?0:-1;
}

Last edited by Cece; 13th December 2010 at 22:30.
Cece is offline   Reply With Quote
Old 13th December 2010, 22:31   #10
Cece
- - - - - - - - - - - -
 
Cece's Avatar
 
Join Date: Apr 2002
Posts: 21,292
Quote:
Originally Posted by CCCComboFapper! View Post
la mia versione dell es2:

Spoiler:

Code:
#include <stdio.h>
main(){
	int a,b,c;
	printf("Inserisci A\n");
	scanf("%d",&a);
	printf("\nInserisci B\n");
	scanf("%d",&b);
	printf("\nInserisci C\n");
	scanf("%d",&c);
	if(a*a+b*b==c*c){
		printf("\nDiofantea!\n");
		return (0);
	}
	else{
		printf("\nNon diofantea\n");
		return (-1);
	}
}
hai sbagliato l' espressione .. ma fa niente ..
Cece is offline   Reply With Quote
Old 13th December 2010, 22:33   #11
[En][gma]
Registered User
 
[En][gma]'s Avatar
 
Join Date: Dec 2001
Posts: 2,968
Quote:
Originally Posted by Arësius View Post
SUPER-CUT
Ricordiamoci ora come si rappresentano vero e falso in C: con 1 e 0. Ecco, quindi, perché molto spesso le funzioni ritornano un valore intero, nel quale il significato dello zero è "qualcosa non ha funzionato".
SUPER-CUT
[/CENTER]
proprio bella sta cosa...
nelle funzioni: zero è "qualcosa non ha funzionato".
ma int main() se ritorna zero è "bella lì, tutto rego raga"
__________________
.: NoS - Nitrous Oxide System :.
[En][gma] is offline   Reply With Quote
Old 13th December 2010, 22:56   #12
spkbri
PiriPiri ( A molla )
 
spkbri's Avatar
 
Join Date: Feb 2010
Location: Torino - Valenza (AL)
Posts: 10,357
Quote:
Originally Posted by Cece View Post
hai sbagliato l' espressione .. ma fa niente ..
si vabbè, è il pensiero che conta. semplicemente l'avevo letta una volta e io ho una memoria che dopo 2 minuti devo andare a rileggere le cose.

comunque fixed....
__________________
|||||||||| SoundCloud
La mia è una logica ferrea e sempre coerente, basta riuscire ad entrare nei suoi meccanismi, poi alla fine la capisci ||||||||- Licher, 2016
spkbri is offline   Reply With Quote
Old 13th December 2010, 23:50   #13
Pier4R
Ex falso quodlibet
 
Pier4R's Avatar
 
Join Date: Jul 2004
Location: equgpbc.r2.Frisia
Posts: 18,665
io odio l'operatore ternario, intanto mi sono iscritto.
__________________
Ngi the e.FlameeXperience .Fe ! ngi.agorà@twitter (sottoscrivi per essere incluso)
You must play online: warSow EnemyTerritory + etpro quake 4 + q4max & quake 3 + cpma & quakelive Teeworlds! hoi2series

Ringrazio i grammar nazi che mi fanno comprendere gli errori ; my.IL
; lettere porno
Pier4R is offline   Reply With Quote
Old 14th December 2010, 10:22   #14
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,581
Quote:
Originally Posted by nanomad View Post
Che quel codice vi serva per capire quanto è utile indentare con criterio e quanto possa fare schifo l'operatore ternario!

bravissimo
__________________
Lode a Bacco, in saecula saeculorum.
Emergent
Arësius is online now   Reply With Quote
Old 14th December 2010, 10:25   #15
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,581
Quote:
Originally Posted by [En][gma] View Post
proprio bella sta cosa...
nelle funzioni: zero è "qualcosa non ha funzionato".
ma int main() se ritorna zero è "bella lì, tutto rego raga"
già.

cmq, non è detto che debba essere per forza così, alla fine possiamo fare come ci pare. ricordate: tramite il C, la macchina ubbidisce senza fiatare. perfino se gli comandate cose scellerate (lo vedremo coi puntatori )
__________________
Lode a Bacco, in saecula saeculorum.
Emergent
Arësius is online now   Reply With Quote
Reply

Tags
inb4 bestemmia ban

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 21:26.


Copyright 2017-2024 by netgamers.it