# 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", ¤t);
// 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?
---