C/C++: introduzione semplice
Il linguaggio C e C++
Il C è un linguaggio nato negli anni 70 per permettere di realizzare applicazioni per il sistema operativo Unix, un sistema operativo utilizzato ancora oggi, e di cui Linux è il più famoso discendente nel mondo PC e server (Linux è scritto in C). Il linguaggio C ha una sintassi molto semplice, e ha istruzioni formali che permettono di effettuare istruzioni che svolgono singole azioni, molto vicine concettualmente alle instruzioni che svolge la macchina. Esso quindi si differenzia da linguaggi più moderni, che invece contengono singole istruzioni che svolgono azioni molto più complesse. Anche in C è possibile svolgere azioni complesse, ma queste richiedono più istruzioni rispetto ad un linguaggio di concezione successiva. Vedremo però più avanti che questo è anche uno svantaggio.
Il C++ è un linguaggio nato negli anni 80 che aggiunge nuove funzioni al C e che oggi viene utilizzato per molte applicazioni, come per esempio la realizzazione del sistema operativo Windows, i motori dei videogiochi, le applicazioni di controllo di sistemi di sicurezza, i sistemi di calcolo numerico, ed infine le principali librerie che oggi guidano i sistemi di intelligenza artificiale. Ma aldilà del loro uso specifico sia il C che il C++ sono linguaggi di programmazione che permettono di realizzare qualsiasi tipo di applicazione.
La sintassi di base (quindi le istruzioni e i formalismi) di questi linguaggi è semplice da imparare, infatti oggi la maggior parte dei linguaggi di programmazione ha una sintassi derivata da questi linguaggi (es. Java, JS, C#, PHP, ed in parte anche Python e Swift).
Struttura generale di un programma C/C++
Un programma C++ è costituito da un file di testo chiamato sorgente composto da istruzioni da impartire al computer, con una sintassi formale e l’uso di parole chiave predefinite.
Un programma è composto dalle seguenti parti:
– una intestazione, dove si richiede l’inclusione di librerie esterne;
– l’eventuale uso di un “namespace”;
– una o più funzioni, che sono il programma vero e proprio.
Le librerie sono funzioni già pronte all’uso scritte dai creatori del linguaggio o altri fornitori. Per usarle dobbiamo dichiarare esplicitamente che le vogliamo includere nel programma.
Possono essere previste istruzioni speciali precedute dal carattere #: sono le direttive del compilatore, che vanno inserite all’inizio del nostro sorgente. Tra queste la direttiva include che vuol dire appunto che andiamo ad includere una libreria per usarne le funzioni.
I namespace sono un modo per raggruppare nomi di variabili in un contenitore, anche in sorgenti differenti. Questa necessità nasce dal fatto che un programma C++ può essere costituito da molti sorgenti, realizzati anche da differenti sviluppatori: diventa probabile quindi un conflitto di nomi di variabili o funzioni, col rischio quindi di riusare lo stesso nome di variabile senza volerlo. Il namespace permette di identificare univocamente un qualsiasi nome come se fosse un “contenitore”. Se si vogliono usare variabili di un altro namespace è necessario usare un prefisso. Per capire bene il concetto di namespace, possiamo pensare a questo come ad una specie di “cognome” che serve per evitare di confondere nomi identici ma che in realtà identificano cose differenti. In un sorgente possiamo inserire un namespace, e quindi utilizzare senza prefisso tutte i nomi di quel namespace.
Le funzioni sono parti del programma identificate da un nome e da un insieme di operazioni. Come vedremo più avanti le funzioni sono dei “sottopgrammi” che raggruppano insieme delle istruzioni per fare un compito specifico, sono etichettate con un nome e permettono di essere richiamate dal programma principale o anche da altri sottoprogrammi. In C anche il programma principale è una funzione speciale che si chiama main. Questa è infatti il punto di ingresso nel programma, cioè la prima funzione che viene eseguita quando facciamo partire il programma. Vedremo in dettaglio le funzioni più avanti, ma quello che ci interessa ora sapere è che main è una funzione obbligatoria, che deve ritornare un valore numerico e che se tutto funziona bene, deve ritornare il valore 0, che significa che ha terminato correttamente.
Vediamo il tutto con un esempio:
#include <iostream>
using namespace std;
int main()
{
cout << "Salve mondo!";
return 0;
}
Identifichiamo quindi:
<iostream> è una libreria di funzioni che permette di utilizzare nello specifico la funzione di stampa cout.
std è un namespace, stiamo dicendo al programma di usare la famiglia dei nomi “std” (che contiene cout).
int main() {… } è il contenitore della funzione principale, cioè il blocco di istruzioni che viene eseguito all’avvio del programma.
Questo programma contiene una istruzione di stampa “Salve mondo!”, e poi conclude l’esecuazione ritornando 0 (correttamente terminato).
Eseguire un programma C/C++
Il sorgente non è immediatamente eseguibile.
Per essere eseguito è necessario usare un programma, detto compilatore, che verifica che il codice sia corretto formalmente e poi lo trasforma in un applicativo che comprende anche le librerie eventualmente incluse.
Non è detto però che un programma formalmente corretto sia anche senza errori.
Infatti come sappiamo un algoritmo può essere formalmente corretto ma nella sostanza essere sbagliato.
Un programma di esempio
Coi diagrammi di flusso si è visto che è possibile eseguire le seguenti operazioni:
– input/output da tastiera e schermo
– assegnazione di valori a variabili tramite espressioni (es. a = b+c)
– verifica condizioni
– cicli
E’ possibile tradurre il diagramma di flusso in codice C codificando il comportamento tramite istruzioni.
Le istruzioni saranno quindi di assegnazione, condizione e ciclo, oppure di input/output.
Qui un semplice esempio di programma sorgente.
#include <iostream>
using namespace std;
int main()
{
cout << "Inserisci il valore di a: ";
int a;
cin >> a;
cout << "Inserisci il valore di b: ";
int b;
cin >> b;
int somma = a + b;
cout << "La somma è: " << somma;
return 0;
}
Tipi di dato e variabili
In C è possibile usare le variabili, ma vanno dichiarate prima e devono avere un tipo di dato associato.
I tipi di dato base fondamentali del C++ sono: int, float (virgola mobile), bool, char. Ne sono presenti molti altri, che vedremo più avanti.
In C++ ogni variabile va dichiarata indicando prima di tutto il tipo.
int i = 0;
Sintassi
La sintassi di C++ prevede le seguenti regole:
– ogni istruzione deve terminare con un ;
int i = 0;
Sono consentiti spazi nelle dichiarazioni di variabile, sono invece obbligatori nelle definizioni di tipo e nell’uso di parole chiave riservate.
– una istruzione può essere sostituita da un blocco:
{
int i=0;
int j=i+2;
}
Le variabili dichiarate in un blocco non sono visibili anche all’esterno del blocco.
Una variabile dichiarata in un blocco con lo stesso nome di una variabile dichiarata esternamente, la va a sostituire (come simbolo) all’interno del blocco.
Le variabili possono essere globali se dichiarate fuori da una funzione, locali se dichiarate in una funzione(visibili quindi solo in quella funzione) o di blocco (visibili solo nel blocco).
Espressioni
Una espressione è una struttura codificata di dati e operatori che viene valutata quando eseguita.
Il risultato dell’espressione poi può essere assegnata ad una variabile. Es.
j=i+2;
Essa può essere oggetto di assegnazione o parametro di funzione. L’espressione viene sempre valutata prima del suo utilizzo (ovvero stampa o assegnazione).
Espressioni principali di C++:
– literal: valori numerici o stringhe assoluti. es 1, False, “Ciao”.
– espressioni aritmetiche. Es. “5+4”, “90/2”. Possono essere applicati operatori matematici (+,-,/,*,%, ecc.).
– espressioni logiche: es.. 5 > 3. Possono essere solo True o False. Possono essere applicati operatori booleani (<, <=, >, >=, !=, ==, !== e !==).
– operatori unari. Es. c++ (incrementa di 1 il valore di c)
Vedremo in dettaglio le varie espressioni logiche e booleane.
Input e output
Per l’input e l’output si usano cin e cout. Questi due simboli rappresentano gli “stream” ovvero dei flussi, rispettivamente in ingresso e uscita.
cin: con questo simbolo richiediamo esplicitamente dal flusso di input l’inserimento di un valore tramite operatore >>. Esempio:
int n;
cin >> n;
A runtime, quando viene eseguita questa istruzione, il programma lascia il controllo all’utente, che da tastiera può inserire un valore. Questo viene passato (operatore >>) a n che ne assume il valore. Occorre fare attenzione: il flusso di cin si interrompe quando l’utente preme invio o spazio.
cout: con questo simbolo inviamo al flusso di output una espressione o più espressioni, tramite operatore <<
Esempio:
cout >> "Hello world";
int n = 4;
cout >> "Il valore è: " >> n;
cout >> "Ciao" >> endl;
endl è una espressione speciale, indipendente dal sistema operativo, che indica il carattere di fine linea.
E’ possibile concatenare più espressioni con l’operatore >>.
Riepilogo
Rivediamo velocemente le istruzioni e le funzioni utilizzate
Codice | Significato |
---|---|
#include <iostream> | permette di includere la libreria che contiene le funzioni cin e cout |
using namespace std | permette di utilizzare lo spazio dei nomi std, e quindi utilizzare cin/cout senza mettere un prefisso |
int main(){ … return 0; } | è la funzione principale del programma, è obbligatorio metterla in tutti i programmi. La funzione restituisce un dato di tipo int (intero) e normalmente ritorna il valore 0 (che vuol dire che ha finito correttamente). |
cout << “..” | cout ci permette di stampare del testo sulla console |
cin >> myVar | cin ci permette di far inserire del testo dall’utente |
int myVar | questa è una istruzione di dichiarazione che istruisce il computer di creare una variabile che si chiama myVar e che è di tipo intero. Il tipo di dato (il C++ prevede diversi tipi di dato) è obbligatorio. |