Ultima modifica:
Introduzione
Visti i numerosi post a riguardo, mi sono deciso a rispondere a quelle che potrebbero essere le domande di chi ha intenzione di avvicinarsi alla programmazione in C e C++.
Iniziamo subito a chiarire un luogo comune: non c'è bisogno di imparare il C prima di imparare il C++. Così come noi italiani abbiamo imparato subito l'Italiano, senza imparare prima il latino, perché l'Italiano è la lingua che necessitavamo per comunicare con la gente, anche chi ha scelto (per volontà o necessità) di imparare il C++ non deve perdere tempo ad imparare il C. Tuttavia se per scelta vostra avete intenzione di imparare entrambi i linguaggi, allora la strada più logica è imparare il C prima del C++.
Se volete semplicemente imparare un linguaggio di programmazione, ma non avete nessun progetto in mente e non siete in grado di scegliere tra C o C++ (o altri linguaggi), allora riceverete quasi esclusivamente delle risposte opinabili basate sull'esperienza che ha avuto chi vi risponde e dalle sue preferenze. Quindi se volete un consiglio sul linguaggio da imparare otterrete due tipi di risposte: quelle basate sul vostro obbiettivo (ammesso che ne abbiate uno), oppure quelle basate sulle esperienze e preferenze di chi vi risponde.
Quali sono le principali differenze tra questi due linguaggi?
Il C è un linguaggio molto snello e semplice, rimasto quasi invariato dalla sua prima standardizzazione (1989), mentre il C++ è uno dei linguaggi più grandi che vi capiterà di incontrare. Il C++ non è pulito come il C, il C++ che abbiamo adesso è frutto di innumerevoli cambiamenti nello standard dove la parola d'ordine è retrocompatibilità: se una feature del linguaggio al giorno d'oggi viene ritenuta superflua o addirittura dannosa, non la vedremo rimossa in futuro.
Queste modifiche (o meglio, aggiunte) allo standard hanno permesso al C++ di essere sempre moderno, tuttavia il fatto che non sia un linguaggio progettato in una volta sola lo ha reso molto poco pulito e disordinato: ci sono diversi modi molto diversi tra loro per ottenere risultati concettualmente identici, ma tecnicamente molto diversi.
Quando è nato il C++, è stato pensato per essere un superset del C: una grossa porzione dei programmi in C possono essere compilati in C++ senza cambiare una riga di codice. Tuttavia non vuol dire che se imparate il C++, state imparando anche il C senza fare la doppia fatica, prima di tutto perché imparare il C++ è molto più difficile che imparare il C e in seconda battuta perché il C++ moderno ha poco a che fare con il C.
Tra alcune delle più importanti features presenti in C++, ma non in C, vi cito: paradigma object-oriented, programmazione generica e metaprogrammazione, exception handling, overloading di funzioni e operatori e supporto basilare al paradigma funzionale. Se non sapete il significato di questa roba passate avanti senza dargli molta importanza o chiedete spiegazioni, non voglio divagare troppo.
Sostanzialmente, sebbene siano apparentemente simili, sono due linguaggi molto diversi tra loro, sia per mentalità (uno minimale, l'altro enorme) che per caratteristiche. Siamo arrivati al punto che il C++ è talmente grande che sebbene il C ne sia quasi interamente una sottoparte, questa sottoparte è molto piccola. Inoltre nelle regole che definiscono quello che è un codice moderno in C++, le caratteristiche verbalmente deprecate sono in gran parte quelle derivate dal C.
Quali sono i vantaggi di programmare in C e quali in C++?
Risposta. Per motivi pratici mi sono concentrato solo sui vantaggi del C++ rispetto al C e vice versa, se qualcuno fosse interessato ad un confronto diretto rispetto ad un altro linguaggio, basta che chieda. In generale C e C++ sono i linguaggi principali (più diffusi e più convenienti da utilizzare) quando si necessitano alte prestazioni oppure operazioni a basso livello.
Cosa devo installare per programmare con uno di questi due linguaggi?
Gli unici programmi indispensabili sono un text editor (altrimenti come li scrivete i codici?) e un compilatore, ovvero il programma che traduce il vostro codice in un codice binario comprensibile dal computer. Detto banalmente: il programma che vi genera l'eseguibile.
Tuttavia la scelta più gettonata è quella di installare un IDE (Integrated Development Environment - ambiente di sviluppo integrato), ovvero un programma che contiene oltre al compilatore e al text editor una serie di tools che vi semplificano la vita durante lo sviluppo. Gli IDE solitamente vi forniscono funzionalità come sintax highlighting, autocompletamento, controllo degli errori in fase di scrittura, linking delle dipendenze automatico, debugger, eccetra eccetra...
Il mio consiglio, visto che siete agli inizi, è di partire direttamente con un IDE, che è il classico strumento che viene usato in ambito professionale. Se poi vi trovate male e/o volete vedere e capire cosa fa l'IDE in maniera automatica, passate ad un text editor + compilatore e avete piena visione su cosa sta succedendo. Poi una volta che imparate a muovere i primi passi sarete in grado di scegliere cosa preferite fare.
Dato che il C++ è quasi interamente un superset del C, potete capire che alcuni IDE impostano un compilatore C++ di default. Imparare il C usando un compilatore C++ non è il massimo della vita, quindi prima assicuratevi di aver impostato correttamente il vostro IDE.
Alcuni degli IDE che vi consiglio sono: Visual Studio (Windows), Eclipse (multipiattaforma), Code::Blocks (multipiattaforma), QtCreator (multipiattaforma), XCode (mac), CLion (multipiattaforma) e NetBeans (multipiattaforma). Tutti questi IDE permettono di programmare in C, in C++ e in altri linguaggi (a seconda dell'IDE). Se state programmando in C vi sconsiglio l'uso di Visual Studio, visto che è meno intuitivo dirgli di compilare in C e il suo compilatore C è mantenuto a stento (per il C++ invece è molto valido).
Ma soprattutto vi sconsiglio di usare DevCpp: è un IDE purtroppo molto conosciuto (perché?), ma fa veramente schifo e i principianti non sono in grado di accorgersene. Evitate di partire con abitudini sbagliate.
Se volete usare un semplice text editor (notepad, vim, gedit, sublime text, emacs o quello che vi pare), i compilatori che potete usare sono principalmente tre: MinGW-w64 (windows), GCC (linux), Clang (mac e linux). Per compilare dovete aprire il terminale (prompt dei comandi) e digitare un codice di questo tipo:
In ogni caso la questione text editor vs IDE è discutibile. Ci sono developers molto famosi che preferiscono usare text editors, ad esempio Linus Torvalds utilizza uEmacs (micro Emacs), un text editor molto semplice. Sono per lo più casi particolari, ma visto che se n'è discusso in passato vi rimando a questa discussione.
Che guida devo usare?
Inglese
Per il C: The C Programming Language, C Programming A Modern Approach, C Primer Plus, Head First C
Per il C++: The C++ Programming Language, Programming Principles and Practices Using C++, Thinking in C++, C++ Primer
Italiano
Per il C: Il Linguaggio C (K&R), Programmazione in C, Il Linguaggio C Fondamenti e Tecniche di Programmazione (Deitel&Deitel)
Per il C++: C++ Linguaggio Libreria Standard Principi di Programmazione, C++ Fondamenti di Programmazione, Pensare in C++
Se volete ulteriori libri vi invito ad usare il tasto cerca e a sfogliare questa discussione.
La maggior parte di quelli che ho linkato sono a pagamento, credo che l'unica eccezione sia Thinking in C++ (Pensare in C++), ma nella discussione che ho linkato ne trovate degli altri. Comunque sia sentitevi liberi da partire da quello che volete, anche se usare un libro è altamente consigliato. Se avete altri libri non è un grosso problema: anche solo per il fatto che si sono meritati la carta stampata, vuol dire che come risorsa non sono malaccio.
Tra le altre risorse utili, da usare come riferimento quando avete qualche dubbio mentre programmate, vi linko: http://en.cppreference.com/w/, http://www.cplusplus.com/reference/, http://linux.die.net/man/
Da questi link potete ricercare funzioni, classi e quant'altro per avere una documentazione su come vanno usate. Il terzo link (il manuale linux) è per il C, mentre gli altri due sono principalmente per il C++ (ma sono rilevanti anche per il C).
Come capisco che standard sto usando?
Se siete degli studenti, alcuni professori vi richiederanno di utilizzare uno standard ben preciso del linguaggio. Se volete sperimentare per i fatti vostri, può essere che siate interessati ad usare qualche feature nuova, ma il compilatore è impostato per compilare con una versione vecchia.
Ogni IDE e ogni compilatore ha un modo diverso per impostare la versione dello standard da utilizzare (a patto che sia supportata), di default tendono ad usare lo standard più recente a patto che questo sia supportato sufficientemente. Il procedimento per cambiare la versione dello standard utilizzata dipende dal vostro IDE e dal vostro compilatore, se avete qualche richiesta scrivetela che la aggiungo in questa sezione.
Ad esempio se volete compilare in ANSI C (standard C del 1989) usando clang e gcc, dovete usare la seguente sintassi:
Il mio codice ha un errore o non fa quello che mi aspetto. Come chiedo aiuto?
È importante specificare dettagliatamente cosa ti aspetti di ottenere e cosa ottieni, postare un esempio di input/output ottenuti e aspettati è un buon punto di partenza. È inoltre necessario postare il pezzo di codice che non funziona (più è grande e meglio è, se è tutto il codice è più facile per noi aiutarti) e in caso di errore è molto utile postare l'errore che che viene segnalato dal compilatore (letteralmente un copia/incolla dell'errore). Dato che abbiamo sottolineato che C e C++ sono due linguaggi distinti, mentre noi abbiamo una sezione unica per i due, è molto utile dire quale dei due si sta utilizzando.
Esistono due tipi di avvisi: Error e Warning. Gli Error sono errori veri e propri, se hai un error il tuo codice non viene compilato, mentre i Warning sono degli avvisi. Il compilatore usa gli avvisi per segnalarti che hai scritto un codice compilabile (la sintassi è corretta e il codice viene effettivamente compilato), ma probabilmente hai fatto un errore di distrazione.
Quando avvio l'eseguibile non vedo niente, anche se il programma è corretto. Dove sbaglio?
Tutti i programmi quando finiscono di fare quello che devono fare, si chiudono. Supponiamo che hai questo programma (lo scrivo in C, ma è un discorso valido anche in C++)
Se lo avvii con il classico doppio click, il programma si apre, stampa "Hello World" e si chiude nel giro di qualche millisecondo. Per vedere bene cosa succede bisogna avviare il programma da terminale, in questo modo sebbene il programma termini, la console rimane aperta (dato che non è stata lanciata dal tuo programma) e tu hai l'opportunità di leggere l'output.
Se vuoi che il tuo programma resti aperto anche con l'avvio da doppio click, allora lo devi programmare in modo tale che attenda qualcosa prima di uscire, ad esempio:
Avrete probabilmente spesso incontrato system(pause) per risolvere questo problema, tuttavia è una soluzione pessima dato che chiede l'intervento del sistema operativo per risolvere un problema molto semplice. Se potete evitare di usarlo, e potete sempre evitarlo, non usatelo. Vi complicate un po' di più la vita, ma risolvete il problema in un modo più corretto.
Se il codice che vi ho fornito precedentemente non dovesse funzionare, è perché rimane della sporcizia nel buffer stdin. In questo caso rimuovete i decommentate le righe e leggete il punto dedicato a questo problema.
L'input non funziona correttamente, l'utente non ha la possibilità di inserirlo. C'è della sporcizia nel buffer stdin.
Generalmente la gestione dell'input e dell'output è una cosa che sembra semplice e scontata (per motivi pratici è tra le prime cose che si impara), ma non lo è. Qui, per motivi pratici, do solo un overview del problema e di come risolverlo, se volete qualche dettaglio in più non vi resta che chiedere.
Cos'è il buffer stdin?
Tutto l'input del terminale passa per attraverso il buffer di stdin (standard input). Questo stdin è sostanzialmente un grosso array di caratteri che vi permette di leggere tutto l'input in una botta sola. Detto banalmente, quello che vi interessa sapere è che ogni volta che avete a che fare con l'input dal terminale, state prelevando (andate proprio ad estrarre) parte del contenuto di questo stdin. Quando chiedete un input all'utente, il programma controlla se c'è qualcosa da leggere nel buffer stdin: se c'è qualcosa allora legge direttamente da li, altrimenti il programma si blocca in attesa che l'utente scriva qualcosa.
Cosa può andare storto?
Principalmente le problematiche sono due: state prelevando una porzione di buffer più piccola di quella che a voi interessa oppure avete della sporcizia (dati che non vi interessano) nella parte iniziale di questo buffer. Come è facile intuire queste due problematiche sono abbastanza vicine tra loro: se prima non leggete tutta la parte che vi interessa, dopo avrete la prima parte del buffer con dei valori non attesi.
In questa sezione discutiamo della sporcizia nel buffer stdin.
Come capisco se ho questo problema?
Partendo dal presupposto che ogni volta che aprite il programma, il buffer stdin è pronto all'uso (è pulito), la problematica tipica è che il programma vi salta delle richieste di input. Come abbiamo detto, se c'è qualcosa nel buffer stdin non è richiesto l'intervento dell'utente. Quindi se credete di dover inserire un input, ma invece il programma prosegue, probabilmente rientrate in questo problema.
Ovviamente non è scontato che il problema sia questo, per capire bene cosa succede dovete avere un po' più di esperienza e magari utilizzare un debugger. Ma questo è un problema tipico causato dalla sporcizia nel buffer stdin.
Come risolvo questo problema?
La funzione che avrete probabilmente incontrato è fflush(stdin), ma non è una soluzione portable visto che lo standard C (e quindi per ereditarietà anche lo standard C++) dice esplicitamente che il comportamento di questa funzione su dei buffer di input non è specificato. Evitate di usarla.
Non esiste una funzione standard per flushare (letteralmente "scaricare") il buffer di input, quello che potete (e dovete) fare è ignorare questa prima parte di buffer che contiene della sporcizia. Lo fate in questo modo:
Stiamo ignorando fino al carattere di '\n' (a capo) perché tipicamente la sporcizia che troviamo nel buffer è delimitata da un carattere '\n'. Questo problema può capitare, ad esempio, se usiamo getchar() per leggere un singolo carattere: l'utente oltre ad inserire il carattere che noi stiamo prelevando preme invio (per dire: "ho terminato di scrivere"), però l'invio inserisce il carattere '\n'. Quindi noi ci aspettiamo di leggere un carattere, ma l'utente inserisce una stringa composta dal carattere + l'invio. Questo '\n' rimane nel buffer stdin che, se non lo ripuliamo/ignoriamo, lo preleveremo alla successiva richiesta di input (apparentemente, "salteremo" una richiesta di input).
Altro
Se c'è qualche domanda che vi piacerebbe vedere in questa lista o se parte di quello che ho detto non è chiaro o sembra sbagliato, segnalatelo nei commenti e provvederò a fixxare quel che serve. Stessa cosa se volete qualche approfondimento o cose del genere.
Ovviamente siete invitati a leggere anche il resto del thread!
Visti i numerosi post a riguardo, mi sono deciso a rispondere a quelle che potrebbero essere le domande di chi ha intenzione di avvicinarsi alla programmazione in C e C++.
Iniziamo subito a chiarire un luogo comune: non c'è bisogno di imparare il C prima di imparare il C++. Così come noi italiani abbiamo imparato subito l'Italiano, senza imparare prima il latino, perché l'Italiano è la lingua che necessitavamo per comunicare con la gente, anche chi ha scelto (per volontà o necessità) di imparare il C++ non deve perdere tempo ad imparare il C. Tuttavia se per scelta vostra avete intenzione di imparare entrambi i linguaggi, allora la strada più logica è imparare il C prima del C++.
Se volete semplicemente imparare un linguaggio di programmazione, ma non avete nessun progetto in mente e non siete in grado di scegliere tra C o C++ (o altri linguaggi), allora riceverete quasi esclusivamente delle risposte opinabili basate sull'esperienza che ha avuto chi vi risponde e dalle sue preferenze. Quindi se volete un consiglio sul linguaggio da imparare otterrete due tipi di risposte: quelle basate sul vostro obbiettivo (ammesso che ne abbiate uno), oppure quelle basate sulle esperienze e preferenze di chi vi risponde.
Quali sono le principali differenze tra questi due linguaggi?
Il C è un linguaggio molto snello e semplice, rimasto quasi invariato dalla sua prima standardizzazione (1989), mentre il C++ è uno dei linguaggi più grandi che vi capiterà di incontrare. Il C++ non è pulito come il C, il C++ che abbiamo adesso è frutto di innumerevoli cambiamenti nello standard dove la parola d'ordine è retrocompatibilità: se una feature del linguaggio al giorno d'oggi viene ritenuta superflua o addirittura dannosa, non la vedremo rimossa in futuro.
Queste modifiche (o meglio, aggiunte) allo standard hanno permesso al C++ di essere sempre moderno, tuttavia il fatto che non sia un linguaggio progettato in una volta sola lo ha reso molto poco pulito e disordinato: ci sono diversi modi molto diversi tra loro per ottenere risultati concettualmente identici, ma tecnicamente molto diversi.
Quando è nato il C++, è stato pensato per essere un superset del C: una grossa porzione dei programmi in C possono essere compilati in C++ senza cambiare una riga di codice. Tuttavia non vuol dire che se imparate il C++, state imparando anche il C senza fare la doppia fatica, prima di tutto perché imparare il C++ è molto più difficile che imparare il C e in seconda battuta perché il C++ moderno ha poco a che fare con il C.
Tra alcune delle più importanti features presenti in C++, ma non in C, vi cito: paradigma object-oriented, programmazione generica e metaprogrammazione, exception handling, overloading di funzioni e operatori e supporto basilare al paradigma funzionale. Se non sapete il significato di questa roba passate avanti senza dargli molta importanza o chiedete spiegazioni, non voglio divagare troppo.
Sostanzialmente, sebbene siano apparentemente simili, sono due linguaggi molto diversi tra loro, sia per mentalità (uno minimale, l'altro enorme) che per caratteristiche. Siamo arrivati al punto che il C++ è talmente grande che sebbene il C ne sia quasi interamente una sottoparte, questa sottoparte è molto piccola. Inoltre nelle regole che definiscono quello che è un codice moderno in C++, le caratteristiche verbalmente deprecate sono in gran parte quelle derivate dal C.
Quali sono i vantaggi di programmare in C e quali in C++?
Risposta. Per motivi pratici mi sono concentrato solo sui vantaggi del C++ rispetto al C e vice versa, se qualcuno fosse interessato ad un confronto diretto rispetto ad un altro linguaggio, basta che chieda. In generale C e C++ sono i linguaggi principali (più diffusi e più convenienti da utilizzare) quando si necessitano alte prestazioni oppure operazioni a basso livello.
Cosa devo installare per programmare con uno di questi due linguaggi?
Gli unici programmi indispensabili sono un text editor (altrimenti come li scrivete i codici?) e un compilatore, ovvero il programma che traduce il vostro codice in un codice binario comprensibile dal computer. Detto banalmente: il programma che vi genera l'eseguibile.
Tuttavia la scelta più gettonata è quella di installare un IDE (Integrated Development Environment - ambiente di sviluppo integrato), ovvero un programma che contiene oltre al compilatore e al text editor una serie di tools che vi semplificano la vita durante lo sviluppo. Gli IDE solitamente vi forniscono funzionalità come sintax highlighting, autocompletamento, controllo degli errori in fase di scrittura, linking delle dipendenze automatico, debugger, eccetra eccetra...
Il mio consiglio, visto che siete agli inizi, è di partire direttamente con un IDE, che è il classico strumento che viene usato in ambito professionale. Se poi vi trovate male e/o volete vedere e capire cosa fa l'IDE in maniera automatica, passate ad un text editor + compilatore e avete piena visione su cosa sta succedendo. Poi una volta che imparate a muovere i primi passi sarete in grado di scegliere cosa preferite fare.
Dato che il C++ è quasi interamente un superset del C, potete capire che alcuni IDE impostano un compilatore C++ di default. Imparare il C usando un compilatore C++ non è il massimo della vita, quindi prima assicuratevi di aver impostato correttamente il vostro IDE.
Alcuni degli IDE che vi consiglio sono: Visual Studio (Windows), Eclipse (multipiattaforma), Code::Blocks (multipiattaforma), QtCreator (multipiattaforma), XCode (mac), CLion (multipiattaforma) e NetBeans (multipiattaforma). Tutti questi IDE permettono di programmare in C, in C++ e in altri linguaggi (a seconda dell'IDE). Se state programmando in C vi sconsiglio l'uso di Visual Studio, visto che è meno intuitivo dirgli di compilare in C e il suo compilatore C è mantenuto a stento (per il C++ invece è molto valido).
Ma soprattutto vi sconsiglio di usare DevCpp: è un IDE purtroppo molto conosciuto (perché?), ma fa veramente schifo e i principianti non sono in grado di accorgersene. Evitate di partire con abitudini sbagliate.
Se volete usare un semplice text editor (notepad, vim, gedit, sublime text, emacs o quello che vi pare), i compilatori che potete usare sono principalmente tre: MinGW-w64 (windows), GCC (linux), Clang (mac e linux). Per compilare dovete aprire il terminale (prompt dei comandi) e digitare un codice di questo tipo:
Codice:
# Compilare il C
gcc -o nome_eseguibile nome_file.c # sia gcc che minwg-w64
clang -o nome_eseguibile nome_file.c # clang
# Compilare il C++
g++ -o nome_eseguibile nome_file.c # sia gcc che minwg-w64
clang++ -o nome_eseguibile nome_file.c # clang
In ogni caso la questione text editor vs IDE è discutibile. Ci sono developers molto famosi che preferiscono usare text editors, ad esempio Linus Torvalds utilizza uEmacs (micro Emacs), un text editor molto semplice. Sono per lo più casi particolari, ma visto che se n'è discusso in passato vi rimando a questa discussione.
Che guida devo usare?
Inglese
Per il C: The C Programming Language, C Programming A Modern Approach, C Primer Plus, Head First C
Per il C++: The C++ Programming Language, Programming Principles and Practices Using C++, Thinking in C++, C++ Primer
Italiano
Per il C: Il Linguaggio C (K&R), Programmazione in C, Il Linguaggio C Fondamenti e Tecniche di Programmazione (Deitel&Deitel)
Per il C++: C++ Linguaggio Libreria Standard Principi di Programmazione, C++ Fondamenti di Programmazione, Pensare in C++
Se volete ulteriori libri vi invito ad usare il tasto cerca e a sfogliare questa discussione.
La maggior parte di quelli che ho linkato sono a pagamento, credo che l'unica eccezione sia Thinking in C++ (Pensare in C++), ma nella discussione che ho linkato ne trovate degli altri. Comunque sia sentitevi liberi da partire da quello che volete, anche se usare un libro è altamente consigliato. Se avete altri libri non è un grosso problema: anche solo per il fatto che si sono meritati la carta stampata, vuol dire che come risorsa non sono malaccio.
Tra le altre risorse utili, da usare come riferimento quando avete qualche dubbio mentre programmate, vi linko: http://en.cppreference.com/w/, http://www.cplusplus.com/reference/, http://linux.die.net/man/
Da questi link potete ricercare funzioni, classi e quant'altro per avere una documentazione su come vanno usate. Il terzo link (il manuale linux) è per il C, mentre gli altri due sono principalmente per il C++ (ma sono rilevanti anche per il C).
Come capisco che standard sto usando?
Se siete degli studenti, alcuni professori vi richiederanno di utilizzare uno standard ben preciso del linguaggio. Se volete sperimentare per i fatti vostri, può essere che siate interessati ad usare qualche feature nuova, ma il compilatore è impostato per compilare con una versione vecchia.
Ogni IDE e ogni compilatore ha un modo diverso per impostare la versione dello standard da utilizzare (a patto che sia supportata), di default tendono ad usare lo standard più recente a patto che questo sia supportato sufficientemente. Il procedimento per cambiare la versione dello standard utilizzata dipende dal vostro IDE e dal vostro compilatore, se avete qualche richiesta scrivetela che la aggiungo in questa sezione.
Ad esempio se volete compilare in ANSI C (standard C del 1989) usando clang e gcc, dovete usare la seguente sintassi:
Codice:
gcc -ansi -o nome_eseguibile nome_file.c
clang -ansi -o nome_eseguibile nome_file.c
Il mio codice ha un errore o non fa quello che mi aspetto. Come chiedo aiuto?
È importante specificare dettagliatamente cosa ti aspetti di ottenere e cosa ottieni, postare un esempio di input/output ottenuti e aspettati è un buon punto di partenza. È inoltre necessario postare il pezzo di codice che non funziona (più è grande e meglio è, se è tutto il codice è più facile per noi aiutarti) e in caso di errore è molto utile postare l'errore che che viene segnalato dal compilatore (letteralmente un copia/incolla dell'errore). Dato che abbiamo sottolineato che C e C++ sono due linguaggi distinti, mentre noi abbiamo una sezione unica per i due, è molto utile dire quale dei due si sta utilizzando.
Esistono due tipi di avvisi: Error e Warning. Gli Error sono errori veri e propri, se hai un error il tuo codice non viene compilato, mentre i Warning sono degli avvisi. Il compilatore usa gli avvisi per segnalarti che hai scritto un codice compilabile (la sintassi è corretta e il codice viene effettivamente compilato), ma probabilmente hai fatto un errore di distrazione.
Quando avvio l'eseguibile non vedo niente, anche se il programma è corretto. Dove sbaglio?
Tutti i programmi quando finiscono di fare quello che devono fare, si chiudono. Supponiamo che hai questo programma (lo scrivo in C, ma è un discorso valido anche in C++)
C:
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
Se vuoi che il tuo programma resti aperto anche con l'avvio da doppio click, allora lo devi programmare in modo tale che attenda qualcosa prima di uscire, ad esempio:
C:
/* Codice C */
#include <stdio.h>
int main()
{
/* int c; */ /* necessario se decommentate le righe sotto */
printf("Hello World\n");
/* while ((c = getchar()) != '\n' && c != EOF); */ /* flusha il buffer stdin */
getchar(); /* resta in attesa della pressione di un tasto (prendi in input un carattere) */
return 0;
}
C++:
// Codice C++
#include <iostream>
int main()
{
std::cout << "Hello World" << std::endl;
// std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n') // flusha il buffer stdin
// std::cin.clear(); // pulisci le error flags, correlato all'istruzione precedente
std::cin.get();
return 0;
}
Avrete probabilmente spesso incontrato system(pause) per risolvere questo problema, tuttavia è una soluzione pessima dato che chiede l'intervento del sistema operativo per risolvere un problema molto semplice. Se potete evitare di usarlo, e potete sempre evitarlo, non usatelo. Vi complicate un po' di più la vita, ma risolvete il problema in un modo più corretto.
Se il codice che vi ho fornito precedentemente non dovesse funzionare, è perché rimane della sporcizia nel buffer stdin. In questo caso rimuovete i decommentate le righe e leggete il punto dedicato a questo problema.
L'input non funziona correttamente, l'utente non ha la possibilità di inserirlo. C'è della sporcizia nel buffer stdin.
Generalmente la gestione dell'input e dell'output è una cosa che sembra semplice e scontata (per motivi pratici è tra le prime cose che si impara), ma non lo è. Qui, per motivi pratici, do solo un overview del problema e di come risolverlo, se volete qualche dettaglio in più non vi resta che chiedere.
Cos'è il buffer stdin?
Tutto l'input del terminale passa per attraverso il buffer di stdin (standard input). Questo stdin è sostanzialmente un grosso array di caratteri che vi permette di leggere tutto l'input in una botta sola. Detto banalmente, quello che vi interessa sapere è che ogni volta che avete a che fare con l'input dal terminale, state prelevando (andate proprio ad estrarre) parte del contenuto di questo stdin. Quando chiedete un input all'utente, il programma controlla se c'è qualcosa da leggere nel buffer stdin: se c'è qualcosa allora legge direttamente da li, altrimenti il programma si blocca in attesa che l'utente scriva qualcosa.
Cosa può andare storto?
Principalmente le problematiche sono due: state prelevando una porzione di buffer più piccola di quella che a voi interessa oppure avete della sporcizia (dati che non vi interessano) nella parte iniziale di questo buffer. Come è facile intuire queste due problematiche sono abbastanza vicine tra loro: se prima non leggete tutta la parte che vi interessa, dopo avrete la prima parte del buffer con dei valori non attesi.
In questa sezione discutiamo della sporcizia nel buffer stdin.
Come capisco se ho questo problema?
Partendo dal presupposto che ogni volta che aprite il programma, il buffer stdin è pronto all'uso (è pulito), la problematica tipica è che il programma vi salta delle richieste di input. Come abbiamo detto, se c'è qualcosa nel buffer stdin non è richiesto l'intervento dell'utente. Quindi se credete di dover inserire un input, ma invece il programma prosegue, probabilmente rientrate in questo problema.
Ovviamente non è scontato che il problema sia questo, per capire bene cosa succede dovete avere un po' più di esperienza e magari utilizzare un debugger. Ma questo è un problema tipico causato dalla sporcizia nel buffer stdin.
Come risolvo questo problema?
La funzione che avrete probabilmente incontrato è fflush(stdin), ma non è una soluzione portable visto che lo standard C (e quindi per ereditarietà anche lo standard C++) dice esplicitamente che il comportamento di questa funzione su dei buffer di input non è specificato. Evitate di usarla.
Non esiste una funzione standard per flushare (letteralmente "scaricare") il buffer di input, quello che potete (e dovete) fare è ignorare questa prima parte di buffer che contiene della sporcizia. Lo fate in questo modo:
C++:
// C++
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n') // flusha il buffer stdin (ignora fino al carattere '\n')
std::cin.clear(); // pulisci le error flags
// adesso puoi prendere l'input
C:
/* C */
int c;
while ((c = getchar()) != '\n' && c != EOF); /* flusha il buffer stdin (ignora fino a '\n' oppure fino a end of file) */
/* adesso puoi prendere l'input */
Stiamo ignorando fino al carattere di '\n' (a capo) perché tipicamente la sporcizia che troviamo nel buffer è delimitata da un carattere '\n'. Questo problema può capitare, ad esempio, se usiamo getchar() per leggere un singolo carattere: l'utente oltre ad inserire il carattere che noi stiamo prelevando preme invio (per dire: "ho terminato di scrivere"), però l'invio inserisce il carattere '\n'. Quindi noi ci aspettiamo di leggere un carattere, ma l'utente inserisce una stringa composta dal carattere + l'invio. Questo '\n' rimane nel buffer stdin che, se non lo ripuliamo/ignoriamo, lo preleveremo alla successiva richiesta di input (apparentemente, "salteremo" una richiesta di input).
Altro
Se c'è qualche domanda che vi piacerebbe vedere in questa lista o se parte di quello che ho detto non è chiaro o sembra sbagliato, segnalatelo nei commenti e provvederò a fixxare quel che serve. Stessa cosa se volete qualche approfondimento o cose del genere.
Ovviamente siete invitati a leggere anche il resto del thread!