# Soluzioni: Strutture di Controllo 2 ## Esercizio Switch 1: Calcolatrice Si scriva un programma che replichi il funzionamento di una calcolatrice. Implementare solamente le 4 operazioni: '+', '-', '\*', '/'. Usare il costrutto switch. ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili float op1, op2, res; char operazione; // Acquisizione da tastiera del primo operando printf("Inserire il PRIMO operando: "); scanf("%f", &op1); scanf("%*c"); // consumo \n in quanto dovrò leggere un char // Acquisizione da tastiera dell'operazione printf("Inserire l'operazione da eseguire: "); scanf("%c", &operazione); // Acquisizione da tastiera del secondo operando printf("Inserire il SECONDO operando: "); scanf("%f", &op2); // Svolgo l'operazione switch(operazione){ case '+': res = op1 + op2; break; case '-': res = op1 - op2; break; case '*': res = op1 * op2; break; case '/': if(op2 != 0) res = op1 / op2; else{ printf("Errore!\n"); return 1; } break; default: printf("Operazione non consentita!\n"); return 1; } printf("%.2f %c %.2f = %.2f.\n", op1, operazione, op2, res); return 0; } ``` --- ## Esercizio 1a: Inserimento Sequenziale di Caratteri con Criterio di Stop Si scriva un programma che permetta di inserire all'utente un carattere alla volta. Ogni volta che l'utente inserisce un carattere il programma deve stampare: 1. il numero di caratteri inseriti finora; 2. l'ultimo carattere inserito. Il programma termina quando l'utente inserisce il carattere '*'. ### Versione 1: Controllo direttamente sull'ultimo carattere inserito ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili char carattere = 0; int contatore = 0; // Ciclo while per l'inserimento sequenziale di caratteri // La condizione di uscita è proprio quella per cui il carattere inserito è '*' while(carattere != '*'){ // Inserimento del carattere printf("Inserisci un carattere: "); scanf("%c", &carattere); // consumare il carattere '\n' rimanente scanf("%*c"); // Incremento del contatore contatore++; // Stampa delle informazioni printf("Il carattere inserito è: %c.\n", carattere); printf("Numero di caratteri inseriti finora: %d.\n\n", contatore); } return 0; } ``` ### Versione 2: Controllo su una variabile di flag ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili char carattere = 0; int contatore = 0, flag = 0; // Ciclo while per l'inserimento sequenziale di caratteri // La condizione di uscita è regolata dal flag // La variabile flag è pensata per essere True quando l'utente inserisce il carattere '*' while(!flag){ // Inserimento del carattere printf("Inserisci un carattere: "); scanf("%c", &carattere); // consumare il carattere '\n' rimanente scanf("%*c"); // Incremento del contatore contatore++; // Stampa delle informazioni printf("Il carattere inserito è: %c.\n", carattere); printf("Numero di caratteri inseriti finora: %d.\n\n", contatore); // Se l'ultimo carattere inserito è '*' // allora si assegna alla variabile flag il valore 1 if(carattere == '*') flag = 1; } return 0; } ``` **Bonus**: come fare se non si vuole stampare l'ultimo carattere '*' senza modificare la struttura generale del codice fornito? (Suggerimento: usare break). --- ## Esercizio 1b: Inserimento Sequenziale di Numeri in Ordine Ascendente Scrivere un programma che consenta all'utente di inserire una sequenza (potenzialmente infinita) di numeri da tastiera. I numeri inseriti dall'utente devono rispettare un ordinamento strettamente crescente. Il programma termina non appena l'utente inserisce un numero che non rispetta la condizione di crescita. ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili int current, last, flag = 0; // Acquisizione del primo numero printf("Inserisci un numero: "); scanf("%d", &last); // Acquisizione dei numeri while(!flag){ // Inserimento printf("Inserisci un numero: "); scanf("%d", &current); // Verifica che sia > del numero precedente if(current > last) last = current; else flag = 1; } return 0; } ``` **Bonus**: stampare a schermo la sequenza solamente dopo che si è usciti dal ciclo (implementare solo il caso in cui l'utente inserisce valori compresi tra 0 e 9). *Suggerimento: usare il meccansimo della versione ottimizzata dell'inversione delle cifre di un numero.* --- ## Esercizio 2: Somma dei Primi N Numeri Naturali Si scriva un programma che permetta all'utente di inserire un numero intero positivo $N$. Il programma deve calcolare e stampare a schermo la somma dei primi $N$ numeri naturali (senza usare la formula di Gauss). ### Versione 1: For ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili int N, i, res = 0; // Inserimento del numero da parte dell'utente printf("Inserisci un numero intero positivo: "); scanf("%d", &N); // Controllo se il numero inserito è positivo if(N < 0){ printf("Il numero inserito è negativo!\n"); return 1; } // Calcolo della somma dei numeri for(i=1; i<=N; i++) res += i; // Stampa del risultato printf("La somma dei primi %d numeri naturali è %d.\n", N, res); return 0; } ``` ### Versione 2: While ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili int N, i, res = 0; // Inserimento del numero da parte dell'utente printf("Inserisci un numero intero positivo: "); scanf("%d", &N); // Controllo se il numero inserito è positivo if(N < 0){ printf("Il numero inserito è negativo!\n"); return 1; } // Calcolo della somma dei numeri i = 1; while(i<=N){ res += i; i++; } // Stampa del risultato printf("La somma dei primi %d numeri naturali è %d.\n", N, res); return 0; } ``` --- ## Esercizio 3: Numero di Cifre di un Numero Si scriva un programma che permetta all'utente di inserire un numero intero $N$ in input (positivo o negativo). Il programma calcola il numero di cifre di $N$ e lo stampa a schermo. ```c #include <stdio.h> int main(int argc, const char * argv[]){ // Variabili int N, tmp, n_cifre; // Inserimento del numero da parte dell'utente printf("Inserisci un numero intero: "); scanf("%d", &N); // Calcolo del numero di cifre tmp = N; n_cifre = 0; while(tmp != 0){ tmp /= 10; n_cifre++; } // Sistemo il caso in cui il numero inserito è 0 if(N == 0) n_cifre = 1; // Stampa del risultato printf("Il numero %d ha %d cifre.\n", N, n_cifre); return 0; } ``` --- ## Esercizio 4: Inversione delle Cifre Si scriva un programma che permetta all'utente di inserire un numero intero positivo $N$ in input. Il programma deve stampare a schermo il numero inserito dall'utente con tutte le cifre invertite. Ad esempio se l'utente inserisce $N=1234$ il programma deve stampare $4321$. ### Versione Intuitiva ```c #include <stdio.h> #include <math.h> int main(int argc, const char * argv[]){ // Dichiarazione delle variabili int N, n_cifre, res, tmp, i; // Acquisizione numero da parte dell'utente printf("Inserisci un numero intero positivo: "); scanf("%d", &N); // Verifica che il numero sia postivo if(N < 0){ printf("Il numero è negativo!.\n"); return 1; } // Capisci il numero di cifre del numero tmp = N; n_cifre = 0; while(tmp != 0){ tmp /= 10; n_cifre++; } if(N == 0) n_cifre = 1; // Inversione cifre res = 0; tmp = N; for(i=1; i <= n_cifre; i++){ res += (tmp % 10) * (int)pow(10, n_cifre - i); tmp = tmp / 10; } // Stampa printf("Numero inserito: %d\n", N); printf("Numero invertito: %d\n", res); return 0; } ``` ### Versione Ottimizzata ```c #include <stdio.h> #include <math.h> int main(int argc, const char * argv[]){ // Dichiarazione delle variabili int N, res, tmp, i; // Acquisizione numero da parte dell'utente printf("Inserisci un numero intero positivo: "); scanf("%d", &N); // Verifica che il numero sia postivo if(N < 0){ printf("Il numero è negativo!.\n"); return 1; } // Inversione cifre res = N % 10; tmp = N / 10; while(tmp != 0){ res *= 10; res += tmp % 10; tmp /= 10; } // Stampa printf("Numero inserito: %d\n", N); printf("Numero invertito: %d\n", res); return 0; } ``` **Bonus**: si faccia anche con la possibilità di avere numeri negativi. --- ## Esercizio 5: La Tabella ASCII Scrivere un programma in grado di stampare tutta la tabella ASCII (id e carattere corrispondente). ```c #include <stdio.h> int main(int argc, char* argv[]){ for(int i = 0; i <= 255; i++) printf("%d \t %c\n", i, i); return 0; } ``` --- ## Esercizio 6: Numeri Triangolari Si scriva un programma che verifichi se un numero intero positivo inserito dall'utente è triangolare. Il programma deve stampare a schermo se il numero è effettivamente triangolare o no. ==**NOTA**: $N$ si dice traingolare se $\exists T \in \mathbb{N}$ tale che $N = \sum_{i=1}^{T}i$.== ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili int N, tmp, i; // Acquisizione di N dall'input printf("Inserire un numero intero positivo: "); scanf("%d", &N); // Verifica che il numero sia corretto if(N < 0){ printf("Il numero inserito è negativo!\n"); return 1; } // Calcolo della somma dei numeri naturali fino al valore di N i = 0; tmp = i; while(tmp < N){ i++; tmp += i; } // Controllo se il numero è trinagolare if(tmp == N) printf("Il numero %d è trinagolare.\n", N); else printf("Il numero %d NON è trinagolare.\n", N); return 0; } ``` --- ## Esercizio 7: Stampa delle Tabelline Si scriva un programma in grado di stampare le tabelline (da 1 a 10) usando solo cicli while. ```c #include <stdin.h> int main(int argc, char* argv[]){ // Variabili int n = 1, i = 0; // Primo ciclo while(n <= 10){ i = n; // Secondo ciclo per stampare while(i <= 10*n){ printf("%d ", i); i += n; } printf("\n"); n++; } return 0; } ``` **Bonus**: implementare il programma usando solo cicli `for` invece che i cicli `while`. --- ## Esercizio 8: Caratteri Compresi tra due Estremi Si scriva un programma in grado di ricevere in input due caratteri da parte dell'utente. Il programma, una volta stabilito quale carattere precede l'altro, stampa tutti i caratteri compresi tra i due inseriti dall'utente. ### Versione 1: Controlli di coerenza lazy ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili char max, min, tmp; // Acquisizione del primo carattere da parte dell'utente printf("Inserire il primo carattere: "); scanf("%c", &max); scanf("%*c"); // dopo bisogna acquisire un nuovo carattere quindi devo consumare lo \n che rimane // controllo che il primo carattere sia una lettera if(!(max >= 'a' && max <= 'z') && !(max >= 'A' && max <= 'Z')){ printf("Il primo carattere non è una lettera!\n"); return 1; } // Acquisizione dei caratteri da parte dell'utente printf("Inserire il secondo carattere: "); scanf("%c", &tmp); // controllo che il secondo carattere sia una lettera if(!(tmp >= 'a' && tmp <= 'z') && !(tmp >= 'A' && tmp <= 'Z')){ printf("Il secondo carattere non è una lettera!\n"); return 1; } // Controllo che i caratteri siano entrambi lettere minuscole o entrambi lettere maiuscole if(!(max >= 'a' && max <= 'z' && tmp >= 'a' && tmp <= 'z') && !(max >= 'A' && max <= 'Z' && tmp >= 'A' && tmp <= 'Z')){ printf("Le lettere inserite non sono in un intervallo coerente.\n"); return 1; } // Capisco chi è il massimo if(max >= tmp) min = tmp; else{ min = max; max = tmp; } // Stampo tutti i caratteri tra il minimo e il massimo for(tmp = min; tmp <= max; tmp++) printf("%c", tmp); printf("\n"); return 0; } ``` ### Versione 2: Controlli di coerenza ottimizzati ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili char max, min, tmp; int flag; /* La variabile flag è pensata per assumere i valori: * 0: la prima lettera inserita è minuscola * 1: la prima lettera inserita è MAIUSCOLA */ // Acquisizione del primo carattere da parte dell'utente printf("Inserire il primo carattere: "); scanf("%c", &max); scanf("%*c"); // dopo bisogna acquisire un nuovo carattere quindi devo consumare lo \n che rimane // controllo che il primo carattere sia una lettera // contestualmente al controllo modifico la variabile di flag per // mantere l'informazione sul fatto che la prima lettera è minuscola o MAIUSCOLA if(max >= 'a' && max <= 'z') flag = 0; else if(max >= 'A' && max <= 'Z') flag = 1; else{ printf("Il primo carattere non è una lettera!\n"); return 1; } // Acquisizione dei caratteri da parte dell'utente printf("Inserire il secondo carattere: "); scanf("%c", &tmp); // controllo che il secondo carattere sia una lettera if(tmp >= 'a' && tmp <= 'z'){ if(flag){ printf("Le lettere inserite non sono in un intervallo coerente.\n"); return 1; } } else if(tmp >= 'A' && tmp <= 'Z'){ if(!flag){ printf("Le lettere inserite non sono in un intervallo coerente.\n"); return 1; } } else{ printf("Il secondo carattere non è una lettera!\n"); return 1; } // Capisco chi è il massimo if(max >= tmp) min = tmp; else{ min = max; max = tmp; } // Stampo tutti i caratteri tra il minimo e il massimo for(tmp = min; tmp <= max; tmp++) printf("%c", tmp); printf("\n"); return 0; } ``` **Bonus**: si implementi il programma usando un ciclo`while` anziché il `for`.