# Soluzioni: Strutture di Controllo 3 + Array ## Strutture di controllo 3 ### Esercizio 1: Sasso Carta Forbice Implementare una partita di sasso carta e forbice per due giocatori: - Non giocatore vs computer - Le giocate sono sequenziali, immaginate il programma come un “verificatore” per capire, date le giocate di una partita fisica, chi abbia vinto ```c #include <stdio.h> int main() { int p1, p2; int vittoria=0; do { printf("\n0 per sasso, 1 per carta, 2 per forbice\n"); printf("player 1: "); scanf("%d", &p1); printf("player 2: "); scanf("%d", &p2); if (p1 < 0 || p1 > 2 || p2 < 0 || p2 > 2) { printf("Mossa non valida!\n"); } else if (p1 == p2) { printf("Pareggio!\n"); } else if ((p1 == 0 && p2 == 2) || (p1 == 1 && p2 == 0) || (p1 == 2 && p2 == 1)) { printf("Vince player 1!\n"); vittoria = 1; } else { printf("Vince player 2!\n"); vittoria = 1; } } while (!vittoria); return 0; } ``` **Bonus**: Si provi ad implementare una versione di questo programma in grado di supportare più partite (si continua a giocare fintanto che la risposta alla domanda "vuoi continuare a giocare?" dopo la terminazione della partita è "1") --- ### Esercizio 2: 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 3: 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--> #### Versione 1: 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; } ``` #### Versione 2: 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; } ``` --- ### Esercizio 4: La Tabella ASCII Scrivere un programma in grado di stampare tutta la tabella ASCII (id e carattere corrispondente). #### Versione 1: while ```c #include <stdio.h> int main(){ int i = 0; while(i <= 255) { printf("%d \t %c\n", i, i); i++; } return 0; } ``` #### Versione 2: for ```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 5: 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 6: 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 tmp = min; while(tmp <= max) { printf("%c", tmp); tmp++; } printf("\n"); return 0; } ``` #### Versione 2: Controlli di coerenza ottimizzati - while ```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 tmp = min; while(tmp <= max) { printf("%c", tmp); tmp++; } printf("\n"); return 0; } ``` #### Versione 3: Controlli di coerenza ottimizzati - for ```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; } ``` --- ### Esercizio 7: Tabelline - Parte triangolare superiore Si scriva un programma in grado di stampare solo la parte triangolare superiore dei valori delle tabelline (da 1 a 10 incluse). Si usino SOLO cicli for. ```c #include <stdio.h> int main(int argc, char* argv[]){ // Variabili int n=1, i=1; // Non ci interessa che siano allineati correttamente, ma solo che siano tutti presenti for(n=1; n<=10; n++){ for(i=n; i<=10; i++) printf("%d\t", i*n); printf("\n"); } return 0; } ``` **Bonus**: Si implementi una versione del programma in grado di allineare effettivamente le tabelline in maniera corretta, stampando: ``` 1 2 3 4 5 6 7 8 9 10 4 6 8 10 12 14 16 18 20 9 ... ``` --- ## Array ### Esercizio 8: Inversione di un Array Scrivere un programma che permetta all’utente di inserire un array di numeri **v1**. Il programma copia l’array **v1** al contrario nell’array **v2**. Il programma stampa **v2**. #### Versione base con tre for ```c #include <stdio.h> #define N 100 int main(int argc, char* argv[]){ // Variabili int real_N = N, v1[N] = {0}, v2[N] = {0}, i = 0; // Acquisizione array do { printf("Quanti numeri vuoi inserire? "); scanf("%d", &real_N); } while(real_N < 0 || real_N > N); for(i=0; i<real_N; i++){ printf("Inserire l'elemento in psozione %d: ", i); scanf("%d", &v1[i]); } // Copio l'array al contrario E lo stampo for(i=real_N-1; i>=0; i--){ v2[real_N - i - 1] = v1[i]; } // Stampo l'array copiato al contrario printf("["); for(i=0; i< real_N; i++){ printf(" %d", v2[i]); } printf("]"); return 0; } ``` #### Versione con due for ```c #include <stdio.h> #define N 100 int main(int argc, char* argv[]){ // Variabili int real_N = N, v1[N] = {0}, v2[N] = {0}, i = 0; // Acquisizione array do { printf("Quanti numeri vuoi inserire? "); scanf("%d", &real_N); } while(real_N < 0 || real_N > N); for(i=0; i<real_N; i++){ printf("Inserire l'elemento in psozione %d: ", i); scanf("%d", &v1[i]); } // Copio l'array al contrario E lo stampo printf("["); for(i=real_N-1; i>=0; i--){ v2[real_N - i - 1] = v1[i]; printf(" %d", v1[i]); } printf("]\n"); return 0; } ``` **Bonus:** si può usare un solo `for`? **Bonus:** invece di usare **v1** e **v2**, è possibile usare un solo array? ---