Sta volta ci ho messo piรน del solito a scrivere l’articolo per due motivi: il Natale, il lavoro, lo studio e il blog non vanno troppo d’accordo se allineati nello stesso spazio-tempo e questa lezione si รจ rivelata un tantino piรน lunga e complessa delle altre per la sua specifica natura.
Piรน o meno, nelle precedenti lezioni, abbiamo cercato di osservareย tutte le basi per poter iniziare a programmare ed abbiamo visto, con un esempio, anche come organizzare il nostro lavoro, suddividerlo e renderlo piรน semplice per altri da comprendere. Spesso, ci siamo imbattuti in una serie di possibili errori che bene o male spuntano sempre quando lavoriamo su un programma: dobbiamo perรฒ sempre trovarli e correggerli di modo che il nostro lavoro funzioni al meglio.
Ci sono varie tipologie di errori come, per esempio, gli errori logici derivanti dai risultati; gli errori cosiddetti di run-time individuati dal pc o da una libreria o dal codice (ad esempio, quando ci dimentichiamo di aggiungere una libreria come math.h); gli errori di link-time individuati dal linker il momento in cui tenta di combinare gli object files in programmi esecutivi; ย e gli errori trovati dal compiler che possono essere sia di sintassi (come, per esempio, la dimenticanza di un punto e virgola a fine stringa oppure una parentesi mancata, etc.) che di genere (ovvero errori relativi all’incompatibilitร tra i type dichiarati e le loro variabili, funzioni, etc.).
Trovare tutti questi possibili errori richiede tempo e pazienza ma, soprattutto, una metodologia per poterli limitare. Inoltre, esercitarsi con il linguaggio di programmazione aiuterร tantissimo nel tempo a fare meno errori e, soprattutto, ad individuarli prima. Ciรฒ significa, quindi, rispettare i seguenti punti:
- Organizzare il software come si era visto, qui, durante l’esercizio della scrittura di una lettera semplice (ovviamente in quel caso il programma era limitato ma piรน lungo diventa piรน la suddivisione in sezioni ed i commenti ci aiuteranno a controllarlo alla fine).
- Eliminare la maggior parte degli errori grazie al debugging ed al testing interni al nostro compiler che, inizialmente, ad un principiante potranno anche sembrare incomprensibili ma, col tempo, diverranno sempre piรน semplici da capire.
- Assicurarsi che il resto degli errori non sia serio.
Questo perchรฉ alla fine tutti i software hanno quelli che chiamiamo spessoย bug ovvero quegli errori del computer che probabilmente sono sfuggiti ai programmatori e, di norma, vengono corretti successivamente grazie alle cosiddetteย patch.
Inoltre, quando lavoriamo su un programma dobbiamo sapere esattamente cosa vogliamo esattamente creare poichรฉ, in mancanza di specificitร , rischieremo di perderci nella costruzione del codice. In questo caso anche creare degli schemi mentali o su carta puรฒ, inizialmente, aiutare.
Non dimentichiamoci, oltre a questo, che appoggiarsi solamente al compiler sia una buona idea: stiamo pur sempre parlando di un software che, in quanto tale, puรฒ sbagliare e non accorgersi della presenza di errori come per esempio l’inserimento di un area che presenta un indice negativo. Piรน il programma su cui stiamo lavorando รจ complicato piรน errori di questo tipo possono presentarsi: ciรฒ significa che se il nostro compiler ha messo insieme il codice (o compiled se vogliamo utilizzare una parola piรน tecnica) non รจ detto che il nostro programma funzioni o che sia totalmente privo di errori.
Vediamo, ora, alcuni errori presi da una lista selezionata dal solito libro di Stroustrup,ย Programming, Principles and Practice using C++.
Cout << " Success!\n" ;
Qui sopra, come si puรฒ notare count รจ stato scritto in maiuscolo anzichรฉ in minuscolo: รจ un errore che si corregge facilmente imparando ad utilizzare il compiler.
In questo caso il compiler ci segnalerร l’errore in questo modo:ย error C2065: ‘Cout’ : undeclared identifier.
cout << " Success !\n ;
Eccole appena dimenticate le virgolette ” che vanno sempre messe per chiudere la frase dopo la n.
Il compiler allora per questa semplice mancanza ci segnalerร due tipi di errori:ย error C2001: newline in constant eย error C2143: syntax error : missing ‘;’ before ‘}’. Come si nota, allora, il compiler non ci avverte direttamente della mancanza delle virgolette ma crede manchi, invece, il punto e virgola.
cout << " Success" << !\n"
In questo caso ci aiutano anche i colori utilizzati in automatico dal nostro compiler notiamo infatti che abbiamo un ” Success” che verrร ovviamente stampato ma un << che non รจ seguito da nessun altro possibile ordine come, per esempio, la possibilitร di inserire una stringa denominata all’inizio della scrittura del programma come potrebbe essere first_name (error C2143: syntax error : missing ‘;’ before ‘string’); in tal caso dovremo anche ricordare di aggiungere dopo first_name di nuovo <<. Inoltre, mancano il punto e virgola alla fine (error C2143: syntax error : missing ‘;’ before ‘}’) e,ย anche qui, le virgolette ” da porre prima del punto esclamativo. Otteniamo cosรฌ una stringa del tipo: cout << ” Success” << first_name << ” !\n”;
Un’altra soluzione piรน semplice sarebbe eliminare le virgolette ” e << dopo la parola Success ed aggiungere il punto e virgola alla fine.
cout << success << endl;
Beh, qui abbiamo un cout dove non sono presenti le virgolette ” ” e, questo renderร impossibile al nostro programma la stampa della parola success (error C2065: ‘success’ : undeclared identifier). Mentre endl, come avevamo giร visto in altre lezioni, funziona come \n.
string res = 7 ; vector<inl> v(10); v[S] = res
cout << "Success!\n ";
Qui, basilarmente, il problema รจ che non si possono archiviare degli int in una stringa senza convertirli.
Il nostro compiler quindi ci segnalerร una marea di errori che qui elenco:
- error C2065: ‘inl’ : undeclared identifier
- error C2923: ‘std::vector’ : ‘inl’ is not a valid template type argument for parameter ‘_Ty’
- error C2514: ‘std::vector’ : class has no constructors
- see declaration of ‘std::vector’
- error C2065: ‘S’ : undeclared identifier
- error C2146: syntax error : missing ‘;’ before identifier ‘cout’
Allora,ย i primi errori che saltano all’occhio sono C2065 e C2923, ovvero inl non esiste, semmai dovrebbe essere corretto con int. Lo stesso vale per string che andrebbe sostituito con int proprio perchรฉ stiamo lavorando con dei numeri, integers, e non con delle stringhe.
Infine, la S, all’interno delle parentesi quadre segnalata dall’errore C2065, non va vene perchรฉ nonย segnala la grandezza del vettore (per informazioni piรน specifiche sulle grandezze dei vettori cliccate qui) cosicchรฉ dovremo sostituirla con un numero come, per esempio, 5.
Otterremo, quindi, la stringa: int res = 7; vector<int> v (10); v[5] = res; cout << “Success!\n”;.
vector<int> v(10); v(S) = 7; if (v(5)! =7)
cout << " Success!\n" ;
Qui il compiler ci segnalerร due errori, in spedifico:ย error C2065: ‘S’ : undeclared identifier eย error C2064: term does not evaluate to a function taking 1 arguments.ย Il primo errore, quindi, lo abbiamo giร incontrato ed era relativo, diciamo, ad un miss-type ovvero l’uso di S anzichรฉ del 5. Il secondo errore, invece, si trova in due specifici punti ed รจ relativo alle parentesi tonde che vanno sostituite con le quadre poichรฉ la grandezza del vettore viene segnalata in questo modo. Notiamoย anche che รจ corretto non mettere dopo l’if il punto e virgola.
Il codice che, quindi, riscritto otterremo sarร :ย vector<int> v (10); v[5] = 7;ย if (v[5] != 7) cout <<ย “Success!\n”;
i f (cond) cout << "Success!\n "; else cout << "Fail!\n" ;
Anche qui troveremo con il compilerย un bel po’ di errori.
- error C2146: syntax error : missing ‘;’ before identifier ‘f’
- error C2065: ‘cond’ : undeclared identifier
- error C2146: syntax error : missing ‘;’ before identifier ‘cout’
- error C3861: ‘f’: identifier not found
- error C2181: illegal else without matching if
Prima di tutto, quindi, vediamo di eliminare gli spazi sbagliati tra i, f e ( per gli errori C2146 (letto male dal compiler poichรฉ non manca nessun punto e virgola) e C3861 scrivendo, finalmente,ย if correttamente ed eliminando anche l’errore C2181.
Infine, C2065 ci fa notare cheย cond non รจ stato dichiarato: infatti per poter creare unย if-statement dobbiamo prima di tuttoย porreย i valori su cui vogliamo lavorare. Quindi, recuperiamo la stringa precedente relativa a vector <int> v(10); v [5]ย = 7; per, poi, scrivere al posto diย cond le condizioni su cui creare l’if-statement come sopra.
Quindi, unendo per comoditร l’esempio sopra a questo su cui stiamo lavorandoย la correzione risulterร essere:ย vector<int> v(10); v[5] = 7; if (v[5] != 7) cout << “Success!\n”;ย if (v[5] == 7) cout << “Success!\n “; else cout << “Fail!\n”;
Ovviamente tutti questi esempi con correzioni estrapolati da un programma non hanno molto senso per cui, bene o male, quando li correggiamo dobbiamo solo vedere se hanno o meno un senso logico-sintattico che in qualche modo funzioni.
bool c = false; if (c) cout << "Success !\n"; else cout << "Fail!\n " ;
Qui non ci sono errori per cui possiamo lasciare cosรฌ le stringe.
string s = "ape " ; boo c = "fool"<s; i f (c) cout << "Success!\n ";
Allora, qui troviamo un’altra serie di errori che perรฒ abbiamo giร visto prima:
- error C2065: ‘boo’ : undeclared identifier
- error C2146: syntax error : missing ‘;’ before identifier ‘c’
- error C2065: ‘i’ : undeclared identifier
- error C2146: syntax error : missing ‘;’ before identifier ‘f’
- error C2146: syntax error : missing ‘;’ before identifier ‘cout’
- error C3861: ‘f’: identifier not found
Logicamenteย boo non esiste quindi puรฒ essere solo un misstype perย bool; come sopra, inoltre, abbiamo un if scritto male a causa degli spazi tra le due lettere che lo compongono (ed ecco perchรฉ ci sono l’errore C2065 e C2146). Quindi avremo:ย string s = “ape “; bool c = “fool”<s; if (c) cout << “Success!\n “;.
string s = "ape "; if (s=="fool") cout < "Success !\n " ;
Semmai o quando decideremo di unire i vari errori connessi qui troveremo un errore, ovveroย error C2374: ‘c’ : redefinition; multiple initialization, che ci farร notare che abbiamo scritto due volte nel nostro codice string s = “ape ” quindi vediamo di cancellarne uno. Inoltre abbiamo anche l’error C2678: binary ‘<‘ : no operator found which takes a left-hand operand of type ‘std::ostream’ (or there is no acceptable conversion) per cui vi รจ una dimenticanza ovvero dopo cout vร aggiunto un altro <.
In tal modo avremo:ย string s = “ape “; if (s==“fool”) cout <<ย “Success !\n “ ;
string s = "ape"; if (s+"fool ") cout < " Success!\n " ;
Abbiamo, qui, due nuovi errori:
- error C2451: conditional expression of type ‘std::basic_string<char,std::char_traits<char>,std::allocator<char>>’ is illegal
- error C2678: binary ‘<‘ : no operator found which takes a left-hand operand of type ‘std::ostream’ (or there is no acceptable conversion)
Qui abbiamo un errore nuovo ed uno appena visto (il C2678 in cui manca una < davanti a cout). Mentre, per quanto riguarda il C2451 abbiamo un problema con l’operatore + che si puรฒ applicare solo con i numeri e non con le stringhe, quindi, in questo caso dovremo sostituirlo con uno dei seguenti operatori != (non uguale), == (uguale), <= (meno di o uguale), >= (piรน di o uguale), < (meno di), > (piรน di).
ย Quindi, in definitiva, potremo correggere la stringa in questo modo:ย string s = “ape”; if (s != “fool “) cout < ” Success!\n “;
vector<char> v(S); for (int i=O; O<v.size(); ++i) ; cout << " Success !\n " ;
Abbiamo qui, di nuovo, la famosa S che proprio non ci sta come grandezza del vettore, segnalata dall’error C2065: ‘S’ : undeclared identifier ed unย error C2065: ‘O’ : undeclared identifier che segnala la presenza di una O (che probabilmente avrebbe dovuto essere uno zero) dato che dovrebbe essere un int (ovvero un numero intero).
Cosรฌ abbiamo:ย vector<char> v(5); for (int i = 0; 0<v.size(); ++i); cout << ” Success !\n”;
vector<char> v(S); for (int i=O; i<=v.size(); ++i) ; cout << "Success !\n " ;
Ritroviamo i medesimi errori C2065 di cui sopra, quindi la S e la O al posto di quelli che dovrebbero essere un 5 ed un 0, ed un nuovo errore:ย warning C4018: ‘<=’ : signed/unsigned mismatchย che prima non avevamo trovato ma che, in realtร , era presente. Se, infatti, guardiamo meglio tra le parentesi relative al for notiamo i<=v.size(); immaginiamo, quindi, che il programmatore avesse voluto intendere per v.size() la grandezza del vettore oppure una grandezza nulla quindi dovremo sostituire questa dicitura con un numero.
Avremo quindi, per esempio:ย vector<char> v(5); for (int i = 0; i<=5; ++i); cout << “Success !\n “;
string s = "Success!\n " ; for (int i=O; i<6; ++i) cout << s[i];
La stringa รจ giusta, il compiler non ci segnalerร nessun errore, ma, se facciamo correre il programma, noteremo che con questo comando non verrร stampata tutta la frase “Success!” ma, solamente, “Succes” a causa dei comandi prestabiliti. Ciรฒ significa che, per poter stampare l’intera parola compresa di punto esclamativo, dovremo sostituire il 6 con un bel 9 (ovvero il numero di caratteri + 1 della frase).
Avremo quindi:ย string s = “Success!\n “; for (int i = 0; i<9; ++i) cout << s[i];
if (true) then cout << "Success!\n " ; else cout << "Fail!\n " ;
Qui, invece, troviamo tre errori nel compiler:
- error C2065: ‘then’ : undeclared identifier
- error C2146: syntax error : missing ‘;’ before identifier ‘cout’
- error C2181: illegal else without matching if
Quelย then dopo l’if proprio non ci sta: per il programma รจ incomprensibile quindi vร tolto. Il punto รจ virgola che manca (C2146) in realtร non manca perchรฉ, come sappiamo, dopo l’if non vร messo e, cosรฌ, anche l’errore C2181 scompare automaticamente.
Cosรฌ avremo:ย if (true)ย cout << “Success!\n “; else cout << “Fail!\n “;
int x = 2000; char c = x; i f (c==2000) cout << " Success!\n " ;
A parte questo benedetto if sempre con lo spazio in mezzo segnalato dagli errori C2065 e C2146. Probabilmente, qui, il programmatore vorrebbe schiacciare un grosso numero intero in un carattere, x. Sebbene il compiler non ce lo segnali dovremo anche aggiungere un int a da cui derivi il valore diย c. Infine, non servirร usare il 2000 nell’uguaglianza ma solamente la x.
string s = "Success !\n "; for (int i=0; i<10; ++i) cout << s[i] ;
Qui nessun errore viene rilevato dal nostro compiler. Vi รจ comunque un errore di stile relativo alla scritta Success dove sarebbe meglio eliminare lo spazio tra la parola ed il punto esclamativo.
vector v(5); for (int i=0; i<=v.size(); ++i) ; cout << "Success !\n " ;
Qui troviamo nel compiler i seguenti errori:
- error C2955: ‘std::vector’ : use of class template requires template argument list
- error C2514: ‘std::vector’ : class has no constructors
- error C2662: ‘_Vector_alloc<!std::is_empty<_Alloc_types::_Alloc>::value,std::_Vec_base_types<_Ty,_Alloc_types::_Alloc>>::size_type std::vector<_Ty,_Alloc>::size(void) throw() const’ : cannot convert ‘this’ pointer from ‘std::vector’ to ‘const std::vector<_Ty,_Alloc> &’
Tutti questi si limitano semplicemente a dirci che ci siamo dimenticati l’argomento del vettore che potrebbe essere, per esempio, a seconda di quello che stiamo utilizzando, <char>. <string>, <doble>.
Quindi avremo:ย vector<char> v(5); for (int i = 0; i <= v.size(); ++i); cout << “Success !\n “;
int i = 0 ; int j = 9; while (i<10) ++j; if (j<i) cout << "Success !\n";
Anche qui il nostro compiler non ci segnalerร alcun errore.
int i=0; while (i<10) ++j; if (j<i) cout << " Success !\n ";
Qui troviamo, invece, il solitoย error C2065: ‘j’ : undeclared identifier che in questo caso ci avverte che il programmatore si รจ dimenticato di dichiarare, per esempio, int j = 7 per poterlo utilizzare.
Quindi avremo:ย int i = 0; int j = 7; while (i<10) ++j; if (j<i) cout << ” Success !\n “;
int x = 4; double d = 5/(x-2); if (d=2*x+0.cout << " Success!\n " ;
Qui c’รจ un errore abbastanza evidente: un punto al posto della parentesi; una cosa, infatti, che dobbiamo ricordarci quando programmiamo รจ controllare che tutte le parentesi si aprano e si chiudano.
Il compiler ce lo segnalerร cosรฌ:ย error C2146: syntax error : missing ‘)’ before identifier ‘cout’
cin << "Success!\n ";
Qui l’errore รจ abbastanza evidente poichรฉ il cin vร sempre utilizzato con l’operatore >> e non <<, inoltre, non viene trattato come un cout, ovvero non stamperร la frase ma piuttosto legge i caratteri inseriti in un eventuale stringa che lo precedeva, dopodichรฉ un cout stamperร la parola success.
Quindi in definitiva o cambiamo semplicemente cin con cout oppure scriviamo qualcosa del tipo:ย string_fn; cin >> fn; cout << “Success!\n”;
La cosa migliore e che, per quanto mi riguarda, funziona sempre quando si cercano degli errori รจ prendersi, dopo un po’, del tempo per rilassarsi, farsi un caffรจ o prendersi una boccata d’aria: quando si tornerร alla postazione di lavoro sarร piรน semplice beccare quel malefico errore che ci stava facendo impazzire poco prima! Un’altra cosa che puรฒ aiutare รจ andare a capo nei momenti giusti cosรฌ da rendere piรน semplice la lettura del codice ed individuare prima l’errore.
Lascia un commento