# 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", ¤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 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`.