CODEXSPRAWL

sulle tracce della periferia cibernetica

Lezione 8. Funzioni e vettori in C++

websiteNella lezione precedente avevamo parlato di loop, switch e statments oggi, invece, ci dedichiamo un po’ ai vettori che mi ricordano tanto la fisica e l’unico tipo di argomento che continuo a non amare particolarmente.

E, se ricordate, avevamo anche visto il comando sqrt(i) che altro non è che una FUNZIONE il cui argomento è i. Per definizione, quindi, una funzione è una sequenza nominata di statments, o affermazioni. Il risultato che la funzione restituisce viene chiamato RETURN VALUE. 

La lista di argomenti richiesti dalla gunzione vengono chiamati PARAMETER LIST (lista dei parametri) mentre i loro elementi sono i parameters o formal arguments (parametri o argomenti formali). La lista dei parametri può essere vuota e se non ci interessa il risultato che la funzione restituisce scriviamo VOID come return type.

Le funzioni servono per i soliti motivi di cui abbiamo già parlato parecchie volte ovvero:

  • Separano logicamente la computazione
  • Rendono il testo del programma più chiaro e semplice da leggere
  • Danno la possibilità di usare la funzione in più sezioni del nostro programma e, quando lavoriamo con una lunga lista di codici, ci aiutano ad orientarci
  • Rendono più semplice la possibilità di testare il programma

Detto questo piccolo sommario, passiamo ai nostri bei vettori! Un vettore è semplicemente una sequenza di elementi che può essere raggiunta da un INDEX (indice). Per esempio, vediamo uno schema segnalato sul libro di Stroustup, Programming Principles and Practice Using C++, che rende l’idea visiva di un vettore denominato v:

Va sottolineato che un vettore non archivia solamente i propri elementi ma, come vediamo, anche la loro grandezza.Vector

Come possiamo, notare, quindi dall’immagine abbiamo un vettore di grandezza 6 i cui elementi corrispondono a 5,7,9,4,6,8 ed archiviati rispettivamente in v[0], v[1], v[2], v[3], v[4] e v[5]: va quindi ricordato che la numerazione dell’indice parte sempre dal numero 0 e che per fare un vettore devono essere specificati i numeri di elementi e il loro iniziale numero. Lo schema sopra potrebbe, quindi, essere scritto in termini di programmazione nel seguente modo:

vector <int> v(6)  //vettore con 6 numeri interi
v[0] = 5;
v[1] = 7;
v[2] = 9;
v[3] = 4;
v[4] = 6;
v[5] = 8;

Il tipo di elemento (in questo caso int) viene scritto, quindi, dopo il vettore e tra < > e l’iniziale numero di elementi viene segnalato dopo di esso (in questo caso 6).

Ovviamente, un vettore accetterà sempre e solo elementi del tipo dichiarato inizialmente: ricordiamoci quindi che non possiamo mettere un numero intero al posto di un nome proprio o viceversa.

Spesso inizializziamo un vettore vuoto e lo facciamo crescere fino alla grandezza desiderata oppure ne computiamo i dati che vogliamo metterci dentro. L’operazione base per questo è push_back(), la quale aggiunge un nuovo elemento al vettore che sarà anche il suo ultimo. Per esempio, sempre recuperando Stroustrup vediamo: Vettors

Nella prima stringa, quindi vediamo come il vettore non abbia elementi e venga inizializzato dal valore 0; in seconda istanza, poi, viene aggiunto l’elemento con valore 2.7 come primo elemento e via dicendo con gli altri valori.

Diamo un’occhiata, ora, a degli esempi pratici perché ogni qualvolta siamo interessati ad analizzare dati abbiamo due possibilità una è l’utilizzo dei vettori l’altra è una strutturazione dei dati un po’ più avanzata di cui parleremo più avanti.

Dato che lavorare coi numeri secondo me complica un po’ le cose con i vettori utilizzerò l’esempio del dizionario:

#include "iostream"
#include "string"
#include "vector"
#include "algorithm"
using namespace std;

int main ()
{
 vector<string>words;
 string temp;
 while (cin>>temp) //leggi le parole separate dagli spazi
 words.push_back(temp); //vettorializza
cout<<"Numero di parole: " <<words.size() << endl;

sort (words.begin(), words.end()); //organizza dall'inizio alla fine

int i = 0;
for(int i=0; i<words.size(); ++i)
 if (i==0 || words[i-1]!=words[i]) //è una nuova parola?
 cout << words[i]<<"\n";
}

Vediamo, ora, in specifico ogni passo che abbiamo scritto nel nostro programma. Prima di tutto, come sempre, dobbiamo selezionare le librerie utilizzando #include. Considerando che stiamo lavorando con i vettori, oltre alle solite librerie di iostream a string, dobbiamo inserire #include vector e #include algorithm senza dimenticare, poi, dall’obbligatorio (ammenoché non vi piaccia posticipare davanti ad ogni stringa la dicitura std::) using namespace std seguito da un bel punto e virgola.

Nel corpo della funzione, quindi, dichiariamo un vettore che contenga i dati ed una variabile in cui possiamo leggere ogni parola che arriva come input con i due comandi: vector<string>words; e string temp; se, invece avessimo lavorato con i numeri reali avremmo utilizzado al posto di string la parola double ed anziché words avremmo preferito temps come segue: vector<double>temps; e double temp; questo è il luogo dove viene menzionato il type dell’input e dove leggiamo ed archiviamo, nel caso del programma a dizionario su cui stiamo lavorando, le parole (o words).

In seconda istanza, troviamo il loop: creato da while (cin>>temp) che legge le parole separate dagli spazi e, poi, attraverso il comando words.push_back(temp); le vettorializza. Qui, quindi, notiamo che stiamo utilizzando while (cin>>temp) come condizione per creare il loop. Questo implica che cin>>temp risulta vero se il valore inserito viene letto correttamente, altrimenti risulta falso cosicché il while-loop leggerà tutte le parole inserite e si fermerà quando gli daremo un diverso input (nel caso dei numeri se per esempio, quindi, scriviamo 1, 2, 3, 4, | il programma di fermerà a | senza leggerlo e considerandolo falso ma, nel caso delle stringhe e quindi del nostro esempio del dizionario bastaerà utilizzare CTRL-Z). Ricordiamoci anche che il comando >> significa “get from”, cioè “prendi da” e cin si riferisce allo standard input stream definito dalla libreria iostream. Poi, chiederemo, con il comando cout << “Numero di parole: ” di scrivere quante parole sono. Se non ce lo fossimo ricordati endl funge allo stesso modo di \n, ovvero come fine comando.

Ora, vediamo in specifico perché abbiamo anche aggiunto la libreria #include algorithm: con l’utilizzo del comando sort (words.begin(), words.end()); necessitiamo proprio di questa libreria per poter ordinare gli elementi. La libreria standard per sort che sarebbe appunto quella denominata algorithm richiede due argomenti: la dichiarazione dell’inizio della sequenza di elementi che è da ordinare e la dichiarazione della conclusione della sequenza.

Poi, utilizzando il for-statement di cui avevamo parlato la volta scorsa nella Lezione 7, dove per creare il loop bisogna dichiarare la variabile i ed inizializzarla con zero o qualsivoglia numero come avviene nel while-statement. Dopodiché preceduti dal for e tra parentesi metteremo in ordine la condizione necessaria per concludere il loop ovvero i<words.size(); ed il loop stesso per aumentare ogni volta e passare alla parola successiva ++i.

Il comando if (i==0 || words[i-1]!=words[i]) che controlla se la parola che è stata scritta precedentemente è diversa da quella che sta per inserire. Utilizziamo l’operatore logico di overload (sovraccarico) || per combinare, appunto, il controllo della parola precedente con quella successiva. Va notato che qui possiamo anche comparare le stringe utilizzando, per esempio:

  • != non uguali
  • == uguali
  • <= meno di o uguale
  • >= più di o uguale
  • < meno di
  • > più di

Alla fine il nostro programma dovrebbe scrivere in ordine alfabetico ed uno sotto l’altro le parole che avevamo inserito.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *