Libro 1 – Capitolo 6 – Primi passi con la programmazione in C++

Indice degli argomenti

Introduzione

Se vuoi approfondire iscrivi al mio corso Udemy online con i laboratori Virtuali clicca sul titolo e accedi alla promozione “Corso Dall’Algoritmo al C++ Base

Il linguaggio C++ nasce come evoluzione del C ed è un linguaggio molto utilizzato in ambito scientifico e professional. Esso è caratterizzato come tutti i linguaggi di programmazione ad alto livello di una sintassi e semantica molto rigida e da un lessico finito di termini.
La caratteristica principale è quella di essere modulare ovvero organizzato in funzioni che svolgono compiti specifici. In C++ vi sono funzioni per la gestione dell’input/ouput, manipolazione di numeri, gestione stampa. Ciascun gruppo di funzione viene incluso in librerie che sono dei file che contengono le istruzioni elementari per l’uso delle funzioni. In ogni programma C++ ogni volta che occorre una funzione devo assicurarmi che essa sia inclusa nelle librerie che io dispongo all’interno del programma. Ogni libreria sarà disponibile con un nome che identifica la classe di funzione e un estensione. Ad esempio string.h è la libreria per la gestione delle stringhe.

Struttura di un programma C++

Un programma C++ può essere pensato e suddiviso in tre parti

intestazione o header

dichiarazione delle variabili e costanti

programma

Intestazione o header

Rappresenta l’elenco delle funzioni che devono essere disponibili all’interno del programma che stiamo creando.
Nel C++ definisco le intestazioni mediante la parola chiave include secondo la sintassi seguente:

#include <nome libreria>

posso ripetere più volte l’istruzione include per ogni libreria che mi occorre.

Dichiarazione di variabili e costanti.

Nel C++ come in tutti i linguaggi di programmazione sono ammesse variabili di tipo numerico, alfanumerico, logico. La dichiarazione di una variabile avviene secondo la sintassi generale:

tipo_dato nome variabile;

ad esempio

int p; dichiara un numero p intero

string cognome; dichiara una variabile stringa cognome

float x; dichiara una variabile reale x in singola precisione

Notare che al termine di ogni dichiarazione è previsto un punto e virgola, il linguaggio C++ prevede la terminazione di ogni riga con il punto e rigola, salvo per alcune eccezioni. Ad esempio nella sezione #include non è necessario.

Per dichiarare una costane si usa

la sintassi: #define nome costane valore

ad esempio #define pigreco 3.14 definisce una costante reale.

programma

Ogni programma in C++ deve essere racchiuso in una funzione nel caso più semplice

int main (){

istruzione 1

istruzione 2

return 0;

}

fare molto attenzione a scrivere le variabili sempre in minuscolo o in maiuscolo fa differenza !

Inoltre terminare ogni istruzione con un punto e virgola.
Le dichiarazioni delle variabili sono opportune nella sezione main in quanto sono riferite alla funzione principale. E’ possibile dichiarare le variabili all’esterno del main, ma in questo caso tale dichiarazione ha uno scopo differente che sarà esaminato più avanti.
Ogni programma C++, deve inoltre terminare con l’istruzione return 0; questa istruzione indica al sistema opertivo che il programma termina, con valore di uscita 0.
Cosa sta ad indicare il valore “0” ? Nel linguaggio di programmazione C++ è stata definito int main() come la funzione principale, la quale restituisce zero o altro valore al termine della sua esecuzione.
Un valore zero indica un’esecuzione del programma regolare. Un valore diverso da zero indica una condizione di errore nell’esecuzione del programma.

Gestione dell’Input/Output

In C++ ci sono diverse librerie per la gestione dell’Input/Output le più utilizzate sono le funzioni della libreria iostream che permettono di formattare automaticamente i dati numerici.
Il supporto della gestione dell’Input e Output è fornito per attraverso la libreria <iostream> che gestisce l’I/O su Console, ovvero in una finestra a caratteri che in Windows è il prompt dcel DOS, ma in MAC/Linux è il terminale.

L’istruzione di scrittura e cout la quale prevede diverse sintassi:

cout << variabile per la stampa di un valore;

cout << “messaggi” per la stampa di messaggi;

Nella prima è possibile gesitre la visualizzazione del valore di una variabile, nella seconda la stampa del messaggio a video.
E’ inoltre possibile combinare le diue cose ad esempio: cout << “La somma di due numeri è: “<< somma;

Per la gestione dell’Input si usa l’istruzione cin << variabile

In C++ per poter utilizzare le funzioni cin e cout si deve dichiarare sotto la sezione #include e comunque prima della dichiarazione delle variabili e costanti la frase:

using namespeca std; per evitare di incorrere nell’utilizzo di funzioni senza qualificare la classe di cui fanno parte. Nel nostro caso la classe è std. Se non vi fosse tale dichiarazione ogni volta che utilizziamo cin o cout si deve premettere il prefisso “std::”.

Gestione avanzata dell’Input Output da console

Sono stati esaminati, solo degli esempi semplici di gestiore dell’Input Output, ma esistono alcune sintassi e istruzioni che gestiscono casi più complessi.
Ad esempio un listato del tipo:

#include <iostream>
#include <string>
using namespace std;
int main ()
{ string nome,cognome;
 cout << "inserisci il nome ";
 cin >> nome;
 cout << "Inserisci il cognome ";
 cin >> cognome;
return 0;
}

E’ un banale pezzod di codice, che richiede all’utente di inserire un nome e cognome che sono poi merozzati in una stringa.

Quando proviamo ad inserire nomi con spazi ad esempio “francesco paolo” la seconda parte dell’input dopo lo spazio non viene catturata, anzi viene saltata anche la richiesta di input del cognome e il programma

termina.
Osserva la schermata per comprendere meglio:

Screenshopt dell'esecuzione del programma.

Modifichiamo il listato precedente con il seguente:

#include <iostream>
#include <string>
using namespace std;
int main ()
{
string nome,cognome;
cout << "inserisci il nome ";
getline(cin,nome);
cout << "Inserisci il cognome ";
getline(cin,cognome);
cout << "\ndati inseriti: " << nome << endl;
cout << cognome <<endl;
return 0;
}

In questo codice C++ è stata introdotta l’istruzione geline che consente di catturare l’input di tuta la riga digitata dall’utente, inclusi gli spazi.
Sono stati poi utilizzati i simboli “\n” e endl per indicare quando occorre andare a capo riga.
Provate il listato per esercizio.

La Manipolazione dei dati in C++

Nella lezione precedente abbiamo visto che la gestione dell’Input Output è delegata alla libreria <iostream> la quale mette a disposizione del programmatore le istruzioni cin e cout. Ora tali istruzioni sebbene utili non consentono la formattazione dell’Input e dell’Output.

Ad esempio se il risultato di una divisione fra due numeri ha un numero elevato di cifre decimali come fare per troncare ad un numero di cifre voluto il numero ?

Dobbiamo innanzitutto ricordare che i numeri reali in singola e doppia precisione in C++ sono dichiarati con float e double che la rappresentazione nel calcolatore dei numeri reali avviene in virgola mobile ovvero scrivendo il numero in notazione scientifica normalizzata.

Ad esempio il numero x=-432,334441 in notazione normalizzata si esprime come x=-0,432334441 x10E3.

Quindi il numero si compone di una mantissa parte frazionaria compressa fra 0 e 1 e da una caratteristica esponente della base 10.

Il C++ calcola e visualizza i risultati in forma scientifica. E’ opportuno richiamare prima delle funzioni per il passaggio di un numero in rappresentazione in virgola mobile a virgola fissa.

Per far questo negli header del programma si deve richiamare la libreria <iomanip> che aggiunge nuove caratteristiche alle istruzioni cin e cout e non solo per la manipolazione dei numeri ma anche delle stringhe.

Ora per passare alla rappresentazione in virgola fissa si utilizza la parola riservata fixed e per impostare il numero di cifre decimale.

Il tutto deve precedere la stampa del numero nell’istruzione cout in quanto deve preparare il formato opportuno.

In altri termini tornando al numero x si ha che per stamparlo con tre cifre decimali avrò:

cout << fixed << setprecision(3) << x;

Quindi l’istruzione fixed passa alla rappresentazione in virgola fissa, mentre l’istruzione setprecision imposta il numero di cifre decimali.

Un modo alternativo ma del tutto equivalente è scrivere:

cout << setioflags(ios::fixed) << setprecision(3) << x;

La manipolazione dei dati in C++ Nella lezione precedente abbiamo visto che la gestione dell’Input Output è delegata alla libreria iostream la quale mette a disposizione del programmatore le istruzioni cin e cout. Ora tali istruzioni sebbene utili non consentono la formattazione dell’Input e dell’Output.

Ad esempio se il risultato di una divisione fra due numeri ha un numero elevato di cifre decimali come fare per troncare ad un numero di cifre voluto il numero ?

Dobbiamo innanzitutto ricordare che i numeri reali in singola e doppia precisione in C++ sono dichiarati con float e double che la rappresentazione nel calcolatore dei numeri reali avviene in virgola mobile ovvero scrivendo il numero in notazione scientifica normalizzata.

Ad esempio il numero x=-432,334441 in notazione normalizzata si esprime come x=-0,432334441 x10E3.

Quindi il numero si compone di una mantissa parte frazionaria compressa fra 0 e 1 e da una caratteristica esponente della base 10.

Il C++ calcola e visualizza i risultati in forma scientifica. E’ opportuno richiamare prima delle funzioni per il passaggio di un numero in rappresentazione in virgola mobile a virgola fissa.

Per far questo negli header del programma si deve richiamare la libreria iomanip che aggiunge nuove caratteristiche alle istruzioni cin e cout e non solo per la manipolazione dei numeri ma anche delle stringhe.

Ora per passare alla rappresentazione in virgola fissa si utilizza la parola riservata fixed e per impostare il numero di cifre decimale.

Il tutto deve precedere la stampa del numero nell’istruzione cout in quanto deve preparare il formato opportuno.

In altri termini tornando al numero x si ha che per stamparlo con tre cifre decimali avrò:

cout << fixed << setprecision(3) << x;

Quindi l’istruzione fixed passa alla rappresentazione in virgola fissa, mentre l’istruzione setprecision imposta il numero di cifre decimali.

Un modo alternativo ma del tutto equivalente è scrivere:

cout << setioflags(ios::fixed) << setprecision(3) << x;

Una scrittura invece del tipo:

cout << setioflags(ios::floatfield) << setprecision(3) << x

arrotonda il numero su tre cifre complessive.

Per finire un listato C++ per verificare le varie possibilità:

#include <iostream>
#include <iomanip>
using namespace std;
int main (){
double x;
int p;
cout << "inserisci il numero x" << endl;
cin >> x;
cout << "inserisci il numero di cifre decimali "<<endl;
cin >> p; cout << endl;
cout << "Numero a p cifre inclusi i decimali"<<endl;
cout << setiosflags(ios::fixed) << setprecision(p)<< x << endl;
cout << setiosflags(ios::floatfield) << setprecision(p) << x << endl;
cout << fixed << setprecision(4) << x << endl;
return 0;}

L’output del problema:

inserisci il numero x
10.1121321313
inserisci il numero di cifre decimali
5
Numero a p cifre inclusi i decimali
10.11213
0x1.4396961f9874fp+3
10.1121

alcune annotazioni il primo output è un numero con 5 cifre dopo la virgola come indicato nella nostra richiesta di input, il secondo p un numero in virgola fissa in notazione scientifica normalizzata, il terzo è lo stesso numero solo con quatrro cifre dopo la virgola.

Per finire un listato C++ per verificare le varie possibilità:

#include <iostream>
#include <iomanip>
using namespace std;

int main (){
double x;
int p;
cout << “inserisci il numero x” << endl;
cin >> x;
cout << “inserisci il numero di cifre decimali “<<endl;
cin >> p; cout << endl;
cout << “Numero a p cifre inclusi i decimali”<<endl;
cout << setiosflags(ios::fixed) << setprecision(p)<< x << endl;
cout << setiosflags(ios::floatfield) << setprecision(p) << x << endl;
cout << fixed << setprecision(4) << x << endl;
retrun 0;}

Quale sarà l’output del seguente programma ? Svolgere per esercizio la codifcia citata.

Funzioni matematiche in C++

Il linguaggio C++, possiede innumervoli funzioni di libreria matematiche implementate mediante la libreria <math> o <cmath> (la seconda è quella derivante dal linguaggio C, dal quale il C++ ha ereditato numerose caratteristiche).
Alcune delle funzioni della libreria <math> sono:

Nome FunzioneDescrizioneEsempio C++
sqrt si applica a float o doubleRadice quadrataEs: x=sqrt(y);
log si applica a float o doubleLogaritmo NeperianoEs: z=log(y);
log10 si applica a float o doubleLogaritmo in Base 10Es: z=log10(x);
pow si applica a float o doublePotenza di un numeroEs: p=(pow(q,x);
equivale a q elevato a x
Exp si applica a float o doubleEsponenziale NeperianoEs: z=exp(x);

Altre funzioni disponibili sono classificate in:;

  • Trigonometriche come sin(double x(, cos(double x), tan(double x)
  • Trigonometriche inverse come asin(double x), acos(double x), atan(double x)
  • Iperboliche con sinh(double x), cosh(double x), tanh(double x)
  • Numeriche come cell(double x) che approssima all’intero più piccolo vicino a x.

Un primo esempio di codice C++ che sfrutta le funzioni della libreria math è:

#include <iostream>
#include <math>
using namespace std;
int main ()
{
float x=3.0;
float rx,y=10,ly,z=3.0,logz,k=3.0,pe;
float q=-3,p=2;
rx=sqrt(x);
cout <<"Radice Quadrata di x\\n’’ << rx);
ly=log(y);
cout<<"\nLogartimo in base E d y \n’’<<ly);
logz=log10(y);
cout<<"\nLogartimo in base 10 di z\n’’<<logz;
pe=exp(k);
cout <<"\nEsponenziale di k base 10 di k n’’<<pe;
p=pow(q,p);
cout<<"La potenza di q alla p\t%f«\n’’<<p;
return 0;
}

Funzioni di conversione:

Nel linguaggio C++, sono disponibili alcune funzioni di conversione da sistemi di numerazione in base diversa dalla decimale.
Ad esempio la funzione hex converte un numero decimale in esadecimale, la funzione dec converte un numero in formato decimale, e la funzione oct lo converte in formato ottale.
Esse sono usate come combinazione di cout prima di stampare il valore.
Se si vuole visualizzare un numero k intero in formato esadecimale, basterà scrivere:

cout << hex << k;

Per completezza nel listato che segue utilizziamo tutte le tre funzioni:

#include <iostream>
using namespace std;
int main () {
int n = 70;
cout << dec << n << endl;
cout << hex << n << endl;
cout << oct << n << endl;
return 0;
}

Il risultato dell’esecuzione sarà:
70
46
106

il primo numero è in base 10, il secondo in base 16, il terzo in base 8.
Per l’uso di funzioni matematiche si può utilizzare la libreria cmath che dispone di numerose funzioni matematiche secondo la tabella sotto riportata:

Esercizi di ripasso

  • Scrivere un programma in C++ che riceva da tastiera tre numeri reali a 12 cifre intere e 4 decimali, e esegua la somma. I numeri devono esere visualizzati in modo corretto.
  • Scrivere un semplice programma C++ che riceva tre numeri interi esegua la somma e stampi a video il risultato sia in notazione ottale che esadecimale.

La codifica delle strutture fondamentali degli algoritmi in C++

Una volta, esamiti i fondamenti del C++, occorre vedere le strutture fondamentali della programmazione proceduare, bovvero i costrutti del linguaggio di programmazione che corrispondono a delle figure algoritmiche viste nei capitoli precedenti.
I primi costrutti sono le condizioni che sono classificate in:

  • Condizione semplice
  • Condizione nidificata (una sequenza di condizioni semplice arbitraria innestate)
  • Condizione di selezione multipla molto utile quando occorre verificare che una variabile assume un numero finito di valori

Condizione Semplice

Il Frammento di algoritmo sotto codificato in C++nel momento in cui incontra la condizione esegue l’istruzione 1 se la condizione è verificata, l’istruzione 2 e 3 se la condizione non è verificata.

In termini di codifica in Linguaggio C++ si ha

if condizione
somma:=a+b:
else
{ differenza:=a-b;
somma:=0;}

In questo frammento di codifce se si verifica una condizione che può essere espressa con gli operatori relazionali <,>,>=,<=,!=,== o medinate gli operatori logici or (||), and ($$), o mediante il not (!), se la condizione è verificata esegue la somma di due numeri a e b, in caso contrario esegue la differenza tra a e b e azzera la somma. Questo è giusto un esempio di come articolare un’istruzione di condizione semplice.
Da notare che il linguaggio C++ obbliga all’utilizzo delle parentesi graffe di apertura e chiusura solo nel caso in cui all’interno della condizione vero o falso indifferentemente sia presentepiù di un’istruzione. e virgola.

Condizioni nidificate

Molto spesso durante lo svolgimento dell’algoritmo è necessario verificare se si verificano più condizioni. Ad esempio per verificare che un numero x è interno ad un intervallo a e b occorrono più condizioni. La struttura con condizioni nidificate proprio perchè deriva da un insieme di condizioni semplice connesse secondo quelle che sono le richieste del problema non ha una struttura unica.
un tipico esempio di una condizione concatenata codificata in C++ è sotto riportata.

if condizione 1
if condizione 2
istruzione 3;
else
istruzione 4;
else {
istruzione 1;
istruzione3;
}

E’ utile notare come quando ci sono più istruzioni if .. then non sono necessarie le parentesi graffe.

Condizione multipla

Quando all’interno di un algoritmo occorre controllare che una variabile assuma una gamma finita di valori conviene utilizzare una struttura detta di condizione multipla che però risulta essere utilizzabile solo se la variabile oggetto della condizione ha un numero finito di valori interi o di tipo carattere. Non è quindi possibile a meno di manipolazioni all’interno dell’algoritmo utilizzare la condizione multipla nel C++ per controllare se una data variabile assume un range di valori.
Nel flow chart la condizione multipla si può rappresentare come tante condizioni in cascata come mostrato sotto:

La codifica in C++ di questo spezzone di codice è:

switch (variabile){
case valore 1:
istruzione;
break;

case valore 2:
istruzione;
break;

case valore 3:
istruzione;
break;

default:
istruzione;

}

In C++ la condizione multipla prende nome di switch in quanto lè possibile controllare solo valori enumerativi e non intervalli. Infatti non è possibile controllare se una data variabile è all’interno di un intervallo numerico ma solo se assume valori precisi.

Esercizio:

Un giocatore partecipa ad un gioco a estrazione di palline puntando un importo x. A seconda del colore della pallina estratta egli realizza una vincita secondo lo scherma sottoriportato:
COLORE VINCITA
NERA 0
ROSSA 2 VOLTE LA PUNTATA
VERDE 4 VOLTA LA PUNTATA

Questo problema ha le segeunti variabili

Input X reale, C colore pallina estratta “N”,”R”,”V” per i colori nero, rosso, verde quindi un tipo carattere
Output Vincita Reale.

L’algoritmo viene lasciato per esercizio allo studente.
La codifica in C++ è:

#include <iostream>
#include <string>
using namespace std;
char c;
float x,vincita;
int main () {
 vincita=0;
 cout << "Inserisci l'importo che desideri giocare" << endl;
 cin >> x;
 cout << endl << "Inserisci colore estratto" << endl;
 cin >> c;
 switch (c) {
  case 'n':
   vincita=0;
   break;
  case 'r':
   vincita =2*x;
   break;
  case 'v':
   vincita=4*x;
   break;
  default:
   cout << "colore non valido" << endl;
}
cout << "Hai totalizzato vincita pari a : ";
cout <<endl<< vincita << endl;
return 0;
}

In questo listato C++ è utile notare che è importante racchiudere fra apici singoli i valori di tipo char. E’ gestito anche l’errore qualora il colore inserito non sia valido.

Le strutture cicliche in C++

Come visto nel capitolo precedente, tutti i linguaggi di programmazione con delle differenze permettono la costruzione di algoritmi basati sui cicli. I cicli per altro già classificati in cicli a ripetizione definita e indefinita sono codificati in C++, con i seguenti costrutti:

Ciclo definito detto ciclo “for”

for (contatore=inizio, (condizione contatotre); contatore= (+ o -) passo
{
istruzione 1;
istruzione 2;
…..
istruzione n;
}

Questo ciclo permette di ripetere una sequenza di operazione un numero prefissato di volte esempi di come organizzare il ciclo for sono;

for (cont=0;cont<10;cont++) // esegue 10 ripetizioni infatti il ciclo parte da zero e non supera dieci, con passo unitario, esempio utile per gli array //

for (cont)2;cont>=30;cont)cont+2) // il contatore effettua un conteggio di passo due; in questo modo sono selezionati i primi 15 numeri divisibili per due //

for (cont=10;cont >0;cont –) // effettua un ciclo for a decremento unitario //

Come per altro è stato illustrato esistono anche cicli a ripetizione indefinita ovvero il numero delle ripetizioni è determinato da una condiizone. Sono pertanto definiti nel linguaggio di programmazione C++ il ciclo indefinito pre-condiionale e il cclo indefinito post-condizionale.
Le strutture sintattiche in C++ sono:

Ciclo indefinito pre-condizionale

while (condizione)
{

istruzione 1;
istruzione 2;
istruzione 3;
…..
istruzione n;
}

ciclo indefinito post-condizionale

do
{

istruzione 1;
istruzione 2;
…..
istruzione n;
}

Un esempio tipico d’uso dei cicli indefiniti sono i cosidetti cicli a “rottura di codice”, ovvero è l’utente che interrompe la sequenza ripetitiva, sulla base della pressione di un tasto. Ad esempio:

#include <iostream>
using namespace std;
int main()
{ char risposta=’n’;
do
{ cout << “inserisci in pordine nome e cognome”;
cout << endl;
cin.getline(nome,20);
cin.getline(cognome,20);
cout << “Altri dati S/N o s/n ?”;
cin >> risposta;
} while ((risposta==’s’) || (rispota == ‘S’);

Lo stesso frammento di codice, che vi invito a completare e testare con il ciclo while potrebbe essere.

rispsota=’S’;
while ((rispsota==’S’) || (rispsota==’s’))

return 0;
}

Per concludere , vi illustro un ciclo for per calcoalre la media di N numeri con (N input) inseriti da tastiera.

Codice C++

#include <iostream>
using namespace std;
int main ()
{
float num, somma, media;
int N, cont;
cout << "\n Calcolo della media di N numeri; inserisci N>2");
do
{
   cin >> N;
   if (N<2)
    cout << "\n Devi inserire N superiore a 2 grazie !");
while /N<=2);
media=0.0;
somma=0.0;
for (Cont=0;Cont <N;Cont++)
{
   cout << "\n Digita un numero reale";
   cin >> num;
   somma=somma+num;
}
media= somma/N;
cout << "\n La media è: "<< media;
cout << endl << "Arrivederci\n";
return 0;
}

Il programma non è molto complesso, è stato previsto un ciclo do…while per controllare il corretto inserimento di N. Il ciclo for richiede N input di numeri e poi calcola la somma, la media essendo un dato di riepilogo è calcolata all’esterno del ciclo for.