PROGRAMMAZIONE IN C E C++
Prof. Enrico TerroneA. S: 2011/12
Definizioni
Programmare significa risolvere problemi col computer, cioè far risolvere problemi al computer attraverso un insieme di informazioni e una sequenza di istruzioni.
La programmazione si compone di tre fasi: analisi / algoritmo / programma
L’analisi consiste nell’individuare i dati e i risultati del problema che bisogna risolvere.
Definizioni
L’algoritmo è la serie di passaggi che permette di risolvere il problema trasformando i dati nei risultati.
L’algoritmo può essere espresso in una qualunque lingua naturale oppure in un formalismo apposito (p. es. i flow-chart). L’algoritmo è una “ricetta” che spiega all’esecutore come produrre i risultati a partire dai dati. L’algoritmo ha sempre carattere generale: non risolve un singolo problema (p. es. quanto fa 1/3 + 2/5), ma una famiglia di problemi (p. es. come si sommano due frazioni).
Definizioni
Il programma è la traduzione dell’algoritmo in un linguaggio comprensibile dal computer. I linguaggi comprensibili dal computer si chiamano linguaggi di programmazione. Il linguaggio di programmazione che useremo in questo corso si chiama C/C++.
Il programma è scritto da un programmatore per un utente. In laboratorio lo studente interpreterà di solito entrambi i ruoli, ma bisogna sempre tener presente che si tratta di due figure ben distinte.
La forma del programma
Lo schema generale di un programma è il seguente:
1) DEFINIZIONE DELLE INFORMAZIONI(impostazione del problema)
2) CARICAMENTO DEI DATI
3) ELABORAZIONE (risoluzione del problema, calcolo dei risultati)
4) COMUNICAZIONE DEI RISULTATI
Il programma più semplice
Il più semplice programma si riduce alla comunicazione di una frase, ed ha la forma:
// Enrico Terrone, 12/9/2008, Programma “Frase”
#include <iostream.h>
using namespace std;
int main ()
{
cout << “Hello World \n”;
system(“PAUSE”);
//istruzione finale di ogni programma
}
Il programma più semplice
Il programma non ha variabili e l’unica vera istruzione è “cout << “Hello World \n”;”, che stampa sullo schermo la scritta “Hello World” seguita da un a capo. Il resto è una “cornice” che si ripeterà in ogni programma.
Il testo che segue i caratteri // è un commento che serve solo a descrivere le istruzioni ma non ha effetti sull’esecuzione del programma. È consigliato di usare sempre un commento a inizio programma in cui si scrive autore, data e titolo del programma.
In generale le istruzioni di un programma C/C++ devono stare su una riga che termina con il punto e virgola; il programma è composto da una serie di istruzioni che vengono eseguite una dopo l’altra, nell’ordine che va dall’alto verso il basso.
Definizione delle informazioni
La definizione delle informazioni richiede la creazione delle variabili, che sono gli spazi di memoria centrale dove le informazioni sono contenute. Possiamo pensare a una variabile come a una casella dentro la quale possiamo leggere e scrivere. Una variabile è caratterizzata dal suo nome (che èassociato alla casella), dal suo tipo (quali dati possiamo scrivere nella casella; inizialmente useremo soltanto i tipi semplici: numeri e caratteri) e dal suo valore (quale dato è effettivamente scritto dentro la casella in un certo istante).
14int numero
Definizione delle informazioni
Per creare una variabile in C si usa un’istruzione della forma: <tipo> nome;
int x; // crea una variabile di nome x// e di tipo “numero intero”double num; // crea una variabile di nome num
// e di tipo “numero decimale”char caratt; // crea una variabile di nome caratt
// e di tipo “carattere”
Il nome è a scelta dell’utente, purché inizi con una lettera e contenga solo lettere, numeri e underscore
(trattini bassi). I tipi invece sono predefiniti dal linguaggio.
Il caricamento dei dati
Per caricare i dati di un programma occorre innanzitutto definire le variabili che li possono contenere. Dopo di che ci sono tre possibilità:
Lettura da tastiera;Estrazione casuale;Lettura da file.
Consideriamo per adesso soltanto la modalità piùsemplice, che è la lettura da tastiera: per prima cosa occorre stampare sullo schermo (con l’istruzione cout) una scritta che invita l’utente a inserire il dato; a questa, fa seguito una seconda istruzione (cin) che legge il valore inserito da tastiera e lo salva nella variabile indicata sulla stessa riga.
Il caricamento dei dati // Enrico Terrone, 12/9/2008, Programma “Quadrato”
#include <iostream.h>
using namespace std;
int main ()
{
int l;
cout << “PROGRAMMA: QUADRATO”;
cout << “Inserisci il lato del quadrato: ”;
cin >> l;
…
}
Nota-1: come prima istruzione del programma, subito dopo la creazione delle variabili, è consigliato di scrivere sempre sullo schermo il titolo del programma in modo che l’utente sappia che cosa sta usando.
Nota-2: le frecce che seguono cin sono girate al contrario rispetto a quelle dopo cout: esse indicano infatti un movimento dei dati dalla tastiera (cin) alla variabile.
L’elaborazione
L’elaborazione è l’insieme delle operazioni che permettono di passare dai dati ai risultati.
L’istruzione fondamentale per l’elaborazione èl’assegnazione che consiste nel calcolo di un’espressione e nella scrittura del risultato dentro una variabile. La sua forma è questa:
<variabile> = <espressione>
Per espressione si intende una combinazione di valori, variabili, operatori (+, -, *, /, %) ed eventuali parentesi (solo le tonde!) conforme alle regole di calcolo.
L’elaborazione
// Enrico Terrone, 13/9/2008, Programma “Rettangolo”
#include <iostream.h>
using namespace std;
int main ()
{
int b, h, perim, area;
cout << “PROGRAMMA: RETTANGOLO”;
cout << “Inserisci la base del rettangolo: ”;
cin >> b;
cout << “Inserisci l’altezza del rettangolo: ”;
cin >> h;
area = b*h;
perim = 2*b + 2*h; // la moltiplicazione in
// informatica va sempre esplicitata
}
La comunicazione dei risultati
Dopo che l’elaborazione ha concluso il calcolo dei risultati, occorre che questi vengano comunicati all’utente. I risultati possono essere comunicati su video o su file.
Per ora noi vediamo solo la comunicazione dei risultati tramite video, per la quale si usa l’istruzione cout, con le scritte descrittive fra virgolette e le variabili (contenenti il risultato) senza virgolette.
La comunicazione dei risultati
int main ()
{
int b, h, perim, area;
cout << “Inserisci la base del rettangolo: ”;
cin >> b;
cout << “Inserisci l’altezza del rettangolo: ”;
cin >> h;
area = b*h;
perim = 2*b + 2*h; //nota: la moltiplicazione in
// informatica va sempre esplicitata
cout << “L’area e’: ” << area << “\n”;
cout << “Il perimetro e’: ” << perim << “\n”;
system (“PAUSE”);
}
In laboratorio
In laboratorio i programmi si scrivono usando quello che si chiama un “ambiente di sviluppo”, cioèun’applicazione (noi useremo Dev C++) formata da tre strumenti fondamentali:
1) l’editor (una specie di “Word” specifico per scrivere programmi);
2) il compilatore (che si può attivare dopo aver scritto e salvato il programma usando una voce di menu o un pulsante della barra degli strumenti);
3) il caricatore (loader) che permette di eseguire il programma dopo che la compilazione è andata a buon fine.
In laboratorio
Se nel programma ci sono degli errori di scrittura, il compilatore si rifiuta di tradurre il programma in linguaggio macchina e indica gli errori; in tal caso, il programmatore deve ricorreggere gli errori usando queste indicazioni e poi provare a compilare nuovamente.
Durante l’esecuzione, il programmatore deve fingersi l’utente e verificare che il programma funzioni come deve.
Esercizi
1) Dato il raggio di un cerchio, calcolare circonferenza e area
2) Dati due numeri, calcolare la loro media
3) Dati tre numeri, calcolare la loro media
4) Dati a e b, risolvere l’equazione a*x + b = 0
5) Scrivere un programma che funzioni da calcolatrice (prima solo con la somma, poi con le quattro operazioni intere, poi con il resto, poi con la divisione fra double).
Le tre modalità
La modalità basilare di esecuzione di un programma è la sequenza: le istruzioni vengono eseguite una dopo l’altra, riga per riga, dall’alto in basso.
Le strutture di controllo modificano l’esecuzione sequenziale permettendo al programma di scegliere fra blocchi di istruzioni differenti (selezione) o di ripetere un blocco di istruzioni (iterazione).
Il teorema di Böhm-Jacopini (1966) afferma che qualunque algoritmo può essere codificato usando soltanto sequenza, selezione e iterazione.
L’idea è che per spiegare a qualcuno che cosa deve fare, dobbiamo farlo procedere un passo alla volta, ma anche, in certi punti, farlo scegliere o ripetere.
Selezione
La selezione è la struttura di controllo che permette all’algoritmo di decidere fra due blocchi di istruzioni, in base al valore di una condizione.
Un blocco è una sequenza di istruzioni raggruppate.
La condizione è una proposizione logica, cioèun’espressione il cui valore può essere vero oppure falso. Essa è generalmente basata sugli operatori di confronto (uguale, diverso, maggiore, minore…), Es. a>3 è vera per a che vale 5 mentre è falsa per a
che vale 1.
Se la condizione è vera viene eseguito il primo blocco di istruzioni, se la condizione è falsa viene eseguito il secondo blocco.
SelezioneLa forma algoritmica della selezione:
se (condizione) allora { blocco-1 }
altrimenti { blocco-2 }
La forma grafica della selezione (flow chart):
cond.
b1 b2
V F
Qualunque sia il blocco eseguito (b1 o b2), al suo termine l’algoritmo prosegue dal medesimo punto di sincronizzazione p.
p
La Selezione in C/C++
La selezione in C/C++ si scrive usando la costruzione if-else (se-altrimenti):
if (condizione)
{
blocco-1
}
else
{
blocco-2
}
// punto di sincronizzazione
La Selezione in C/C++
Dopo che si è eseguito il blocco-1 oppure il blocco-2, il programma riprende dal punto di sincronizzazione.
La condizione si scrive usando gli operatori aritmetici: >, >=, <, <=, ==, != e se occorre anche gli operatori logici:&& (AND), || (OR), ! (NOT).
Attenzione a non confondere mai l’operatore = (assegnazione) con l’operatore == (confronto).
La parte “else + blocco-2” può anche non esserci: nel qual caso, se la condizione è falsa, il programma non esegue nessuna istruzione e poi prosegue sempre a partire dal punto di sincronizzazione.
Esempio di selezione
Scontare del 20% i prezzi > 100 euro, del 5% gli altri
int main ()
{
double pr;
cout << “PROGRAMMA: SCONTO”;
cout << “Inserisci il prezzo: ”;
cin >> pr;
if (pr>100)
{
pr = pr – pr*20/100;
}
else
{
pr = pr – pr*5/100;
}
cout << “Il prezzo scontato è “ << pr << “\n”;
}
V
Esercizi sulla selezione (I)
1) Leggere un voto e controllare che sia esatto (cioècompreso fra uno e dieci)
2) Modificare il programma “Sconto” in modo che siano esclusi dallo sconto i prezzi troppo alti (> 1000 euro) e quelli troppo bassi (<2 euro).
3) Leggere il saldo di un conto corrente e la cifra da prelevare (massimo: 700 euro e comunque non si può andare in negativo); se il prelevamento èpossibile effettuarlo e comunicare il nuovo saldo.
4) Scrivere un programma che aiuti un bambino a imparare le 4 operazioni facendogli inserire due operandi e il risultato, e correggendolo se sbaglia.
Esercizi sulla selezione (II)
1) Leggere un intero e trovarne il valore assoluto
2) Leggere le coordinate di un punto e dire in quale quadrante si trova.
3) Leggere tre interi e calcolare: a) la somma di quelli che sono divisibili per due o per cinque; b) il prodotto di quelli che sono divisibili per due e per cinque; c) la media di quelli che non sono divisibili né per due né per cinque.
4) Eseguire la divisione (trovando quoziente e resto) fra due interi letti da tastiera controllando che il divisore non sia zero (se lo è, dire “Impossibile”)
Esercizi sulla selezione (III)
1) Leggere i risultati di andata e ritorno di una gara di qualificazione (regola: i punti “fuori casa” valgono doppio) e dire quale squadra si è qualificata.
2) Scrivere un programma che risolva un’equazione generica di primo grado.
3) Scrivere un programma che risolva un’equazione generica di secondo grado. Nota: per calcolare la radice quadrata usare l’istruzione sqrt(x) aggiungendo all’inizio: #include <math.h>
Iterazione
Proviamo a pensare a un programma che deve stampare venti volta la stessa frase, oppure a un programma che deve leggere una serie di numeri e sommarli, fino a quando l’utente non scrive zero.
Con le istruzioni che abbiamo visto finora, nel primo caso sarebbe un programma molto lungo, nel secondo caso un programma impossibile.
L’iterazione permette invece di risolvere questo tipo di problemi – che richiedono di ripetere tante volte le stesse operazioni - in maniera molto semplice.
Iterazione
L’iterazione è la struttura di controllo che permette all’algoritmo di ripetere un blocco di istruzioni, fino a quando una condizione risulta vera.
Per blocco e condizione valgono le definizioni date in precedenza.
A ogni passaggio, prima di eseguire il blocco, si controlla la condizione: se è vera, si ripete il blocco;
se è falsa, si prosegue con le istruzioni successive.
La condizione deve poter diventare falsa, per cui le variabili in essa presenti devono essere modificate dentro al blocco.
Iterazione
La forma algoritmica dell’iterazione:
finché (condizione) ripeti { blocco }
La forma grafica dell’iterazione (flow chart):
cond.
b1
V F
L’iterazione in C/C++: il while
L’interazione in C/C++ si scrive usando le costruzioni while (finché), do-while (ripeti-finché), for (per tutti).
Iniziamo a vedere la forma più semplice che è il while.
while (condizione)
{
blocco
}
Es. stampare venti volte la parola ciao:
i=1;
while (i<=20)
{
cout << “ciao \n”;
i = i+1; // si può scrivere anche: i++
}
L’iterazione in C/C++: il for
Il for è un’alternativa al while che permette di inserire su un’unica riga l’inizalizzazione e l’incremento del contatore. Si usa soprattutto quando il numero di ripetizioni da effettuare è predefinito.
for (inizializzazione; condizione; incremento)
{
blocco
}
for (i=1; i<=20; i++)
{
cout << “ciao \n”;
}
L’iterazione in C/C++: il do-while
Il do-while è un’alternativa al while che permette di effettuare il controllo della condizione alla fine del blocco anziché all’inizio. E’ utile ad esempio quando si vuole controllare la correttezza dei dati inseriti.
do
{
blocco
} while (condizione);
Es. programma divisionecout << “inserisci dividendo: “; cin>> x;
do
{
cout << “inserisci divisore: “; cin >> y;
} while (y == 0);
ris = x / y;
cout << “Il quoziente è “ << ris << “\n”;
Esempio di iterazione
Trovare somma e media di 20 interi letti da tastieraint main ()
{
int x, s=0, i;
double m;
cout << “PROGRAMMA: SOMMA E MEDIA”;
i=1;
while (i<=20)
{
cout << “inserisci: “;
cin>> x;
s = s+x;
i = i+1;
}
m = ( (double) (s) )/20;
cout << “La somma è “ << s << “\n”;
cout << “La media è “ << m << “\n”;
}
Esercizi sull’iterazione
1) Leggere una serie di prezzi e quantità acquistate e calcolare il totale della spesa (terminare quando viene inserita una quantità zero).
2) Sia N un numero letto da tastiera a inizio programma. Leggere una serie di N voti e trovare la quantità e la percentuale dei sufficienti.
3) Sia N un numero letto da tastiera a inizio programma. Leggere una serie di N voti e trovare il voto più alto e il più basso.
Esercizi sull’iterazione (II)
1) Un veicolo V1 si muove con una velocità di 10 m/s, mentre un veicolo V2 va a 2,5 m/s. V2 parte con un vantaggio di X metri. Stampare la distanza, secondo per secondo, finché V1 raggiunge V2.
2) Scrivere un programma che converta un numero da decimale a binario col metodo delle colonne.
3) Scrivere un programma che converta un numero da binario a decimale (suggerimento: dividere per 10 a ogni passaggio usando il resto come singola cifra binaria da convertire)
Numeri casuali in C
In alternativa alla lettura da tastiera (cin), i dati del programma C possono essere estratti a caso:
• Fra le librerie negli vanno aggiunte:#include <stdlib.h>
#include <time.h>
• Come prima istruzione del main va scritta:srand(time(NULL));
• Per generare un numero casuale in [a, b] e salvarlo nella variabile x si scrive: x = rand()%(b-a+1) + a;
Nota: si sfrutta la proprietà del resto di essere sempre minore del divisore.
Esercizi
1) Stampare venti numeri presi a caso in [10, 30].
2) Estrarre un numero in [1, 90] e chiedere all’utente di indovinarlo. A ogni passaggio il programma comunica se il numero inserito è più alto o piùbasso rispetto al numero da indovinare. Quando l’utente indovina, il programma gli comunica quanti tentativi sono stati effettuati.
3) “Blackjack”. Estrarre un numero in [1, 10] e poi aggiungere ogni volta un altro valore in [1, 10] finché l’utente “si ferma” oppure supera quota 21.
4) Aggiungere al “Blackjack” un secondo giocatore (utente/computer) e alla fine dire chi ha vinto.
I vettori
Un vettore è un insieme di variabili tutte delle stesso tipo che occupano uno spazio contiguo di memoria e che hanno un nome composto da una prima parte comune e da una seconda parte (indice) specifica.
Es. int v[4];
39 v[0]
195 v[1]
0 v[2]
74 v[3]
I vettori
I vettori offrono due grandi vantaggi:
1) Possibilità di creare tante variabili quante se ne vogliono con un’unica riga di programma;
2) Possibilità di ripetere la stessa operazione su tutti gli elementi del vettore usando un ciclo for.
Es. (stampa degli elementi di un vettore)
int v[30];
[…]
for (i=0; i<30; i++)
{
cout << v[i] << “ “;
}
I vettori di caratteri
Un vettore di N caratteri corrisponde a una parola (stringa) di al massimo N-1 caratteri (l’ultimo è ‘\0’):
char v[20]; // parola di al massimo 19 caratteri
Per creare un vettore di parole (stringhe), occorre usare una matrice:
char v[70][21]; // 70 parole di al più 20 caratteri ognuna