INTRODUZIONE AL C++
Transcript
INTRODUZIONE AL C++
INTRODUZIONE AL C++ 1) Cos'è il C++ E' un linguaggio ad alto livello che ingloba il linguaggio C, col quale è completamente compatibile (ogni programma C viene compilato da un compilatore C++) ed al quale aggiunge alcune caratteristiche quali i concetti di CLASSE. 2) Cos'è una CLASSE? Una classe è un tipo di dato che consente la PROGRAMMAZIONE AD OGGETTI, cioè una programmazione più adatta ad implementare programmi di grosse dimensioni. 3) Qual è il più semplice programma C++? E' il seguente: //programma ciao, mondo #include <iostream> using namespace std; int main() { cout << "Ciao, Mondo!" << endl; system("pause"); } 4) Cosa significa la linea: //programma ciao, mondo Significa che tale linea è un commento, ovvero una frase che viene posta per chiarire quanto si sta facendo. Ogni commento inizia col simbolo // e termina a fine riga. 5) Esiste un modo per fare un commento su più righe? Si può fare un commento che inizia col simbolo /* commento può occupare più righe. e termina col simbolo */. In questo modo il 6) Cosa significa la riga di programma: #include <iostream> Tale riga non è una istruzione ma è una DIRETTIVA per il compilatore. Essa dice al compilatore di includere (al posto della direttiva) il contenuto del file iostream (che si trova nella sottocartella include della cartella che contiene il compilatore). Tale file contiene i prototipi di tutte le funzioni che serviranno per l'ingresso e l'uscita dei dati, come la funzione cout. 7) Cos'è una funzione? Una funzione è una parte di programma (sottoprogramma) dotata di un titolo e di un corpo. Il titolo della funzione specifica il tipo del valore di uscita, il nome della funzione e l'elenco degli argomento con la relativa specifica di tipo. 8) Può fare un esempio di titolo di funzione? int somma(int x, int y) 1 Il precedente è un titolo di funzione (se il titolo è seguito dal carattere ; diventa un prototipo) che restituisce un intero (int) e si applica a due argomenti x,y entrambi interi. 9) Cosa significa la riga: using namespace std; ? Un programma C++ molto complesso può essere costituito da più file ciscuno dei quali verrà compilato separatamente. I risultati della compilazione vengono assemblati da un programma che si chiama LINKER. Se un identificatore (nome di variabile, di funzione eccetera) viene definito extern in un file F1 esso verrà riconosciuto anche da tutti gli altri file linkati assieme a F1. Si possono così creare dei conflitti se lo stesso identificatore viene ridefinito per errore in file diversi. Per evitare tali conflitti si consente di ridefinire lo stesso identificatore su file diversi a condizione di creare degli SPAZI DEI NOMI (namespace) e di porre gli identificatori su namespace diversi. 10) Cos'è il namespace std? Nel C++ tutti gli identificatori della libreria standard sono inseriti tutti entro il medesimo namespace che si chiama std (standard) 11) E' possibile evitare l'uso dell'istruzione: using namespace std? Si, ma in questo caso gli identificatori che forniscono i nomi di tutte le funzioni contenute nella libreria standard come cin e cout devono essere preceduti da std:: (scope resolution) Ad esempio il programma precedente può scriversi: #include <iostream> int main() { std::cout<< "Ciao, Mondo! "<<std::endl; system("pause"); } 12) Cosa significa la riga: int main() ? Tale riga è il titolo della funzione principale del programma. Tale funzione deve essere sempre presente in un programma ed è la funzione che viene eseguita per prima. La parola int significa che la funzione restituisce un intero. Una funzione qualsiasi restituisce un valore mediante una istruzione del tipo: return valore ; Nel caso della funzione main tale istruzione può essere omessa. Se invece nel main si inserisce l'istruzione return valore; il valore deve essere un intero. 13) Che utilità può avere l'istruzione return valore; inserita nel main? Il main può essere chiamato dal sistema operativo. Inserire tale istruzione può servire al sistema operativo per sapere ad esempio se il programma è stato eseguito fino alla fine oppure se c'è stata una uscita anticipata in seguito ad un errore nel programma. 14) Che cos'è una variabile, come si dichiara il suo tipo, come le si assegna un valore? Le variabili sono lo strumento fondamentale col quale si comunicano i dati fra l'utente ed il sistema di calcolo (computer). Le variabili servono cioè sia per l'INPUT dei dati di ingresso, sia per l'OUTPUT dei dati di uscita, frutto dell'elaborazione. 2 15) Quali sono gli attributi di una variabile? Sono il suo NOME, il suo TIPO, ed il suo VALORE. 16) Come si assegna un nome ad una variabile? Una variabile segue la sintassi degli IDENTIFICATORI, ovvero: <identificatore>=<lettera>/<identificatore><cifra> Cioè un identificatore è una lettera seguita da una qualsiasi sequenza di lettere o cifre. Si noti che in C++ il carattere _ (underscore) è considerato una lettera. Sono esempi di identificatori: numero, num1, num, numComplesso, num_complesso, x, x0 Non sono naturalmente ammessi come identificatori i TERMINI RISERVATI che esprimono nomi di funzioni predefiniti o termini utilizzati in istruzioni del linguaggio (if, int, main …) 17) Un programma C++ è generalmente scritto in lettere minuscole. E' consentito l'uso delle maiuscole? Il programmatore può utilizzare lettere maiuscole in un identificatore, tuttavia il compilatore distingue le minuscole dalle corrispondenti maiuscole. Ad esempio le variabili numero e NUMERO sono due variabili distinte. 18) Come si dichiara che una variabile ha tipo intero? Si dichiara premettendo il termine riservato int prima del nome della variabile. Ad esempio per dichiarare che la variabile numero è intera si scriverà: int numero; 19) Quali sono i tipi numerici fondamentali? Sono short, int, long, float, double, long double. Ciascuno di questi tipi ha una occupazione di memoria che dipende dal compilatore utilizzato. Per il DEV-CPP i precedenti tipi occupano rispettivamente 2 (short), 4(int), 8(long), 4(float) ,8 (double), 12 (long double) come si rileva facendo girare il seguente programma: //occupazione di memoria dei diversi tipi #include <iostream> using namespace std; int main() { cout<<"dimensioni tipo short"<<sizeof(short)<<endl; cout<<"dimensioni tipo int:"<<sizeof(int)<<endl; cout<<"dimensioni tipo long:"<<sizeof(long)<<endl; cout<<"dimensioni tipo double:"<<sizeof(double)<<endl; cout<<"dimensioni tipo long double:"<<sizeof(long double)<<endl; system("pause"); } Si noti infatti che l'operatore sizeof fornisce il numero di byte occupato dal tipo posto come suo argomento. 20) Cosa significa short? Significa numero intero avente occupazione minima di memoria (2 byte nel DEV-CPP). Tenendo presente che due byte sono 16 bit, e che un bit serve per il segno, il massimo short vale allora 2^15-1= 32767. Mentre il minimo short vale -32768. Ciò può essere controllato col programma: 3 //massimo e minimo short #include <iostream> #include <climits> using namespace std; int main() { cout<<"massimo short="<<SHRT_MAX <<endl; cout<<"minimo short="<<SHRT_MIN <<endl; system("pause"); } Si noti infatti che il file climits riporta i valori massimi e minimi dei vari tipi numerici. Tali valori sono indicati dalle costanti: SHRT_MAX, SHRT_MIN (short) INT_MAX, INT_MIN (int) LONG_MAX, LONG_MIN (long) 21) Cosa significano int e long? Significano INTERO ed INTERO LUNGO. Nel Dev-Cpp un intero occupa 4 byte, mentre un intero lungo occupa 8 byte. Varia quindi il numero massimo che si può rappresentare nei due casi. Precisamente vale: 2^31-1 = 2.1 10^9 circa per gli int Vale 2^63-1 = 9.2 10^18 per i long 22) Cosa significano float e double? Significa numero in virgola fluttuante (o mobile). Tale numero viene rappresentato nel Dev-Cpp con 4 byte (32 bit). Di questi 32 bit la maggior parte viene riservata alla mantissa ed i rimanenti (probabilmente 8) all'esponente. Si osservi che nei linguaggi artificiali il carattere che separa la parte intera da quella decimale è il punto (e non la virgola!) Con il formato float possono essere rappresentati correttamente numeri aventi 8 cifre. Mentre con il formato double (doppia precisione) possono essere rappresentati correttamente numeri con 17 cifre. Ciò può essere visto col programma: //cifre significative #include <iostream> using namespace std; int main() { const float a=-1.23456789012345678; const double b=-1.23456789012345678; cout.precision(20); cout<<"a="<< a <<endl; cout<<"b="<< b <<endl; system("pause"); } 4 Tale programma fornisce un valore di a che risulta corretto solo per le prime 8 cifre. Fornisce un valore di b che risulta corretto per le prime 17 cifre significative. Si noti la presenza della istruzione cout.precision(20); Tale istruzione imposta la precisione a 20 cifre, consentendo di apprezzare tutte le cifre esatte dei due numeri a,b. Senza tale istruzione la precisione sarebbe stata 6 (valore di default), per cui non si sarebbero potute osservare tutte le cifre esatte di a, b, ma sarebbero risultate errate tutte le cifre dalla settima in poi! 23) Quali sono le operazioni che si possono fare coi tipi numerici? Con i tipi interi (short, int e long) si possono fare le normali operazioni aritmetiche: 1) + (somma) 2) (differenza) 3) * (prodotto) 4) / (divisione) 5) % (modulo ovvero calcolo del resto di una divisione fra interi positivi) 6) ++ (incremento) 7) -- (decremento) Si noti perciò che non esiste un operatore che consenta di effettuare il calcolo della potenza. 24) Come mai il seguente programma fornisce come risultato a/b=0? #include <iostream> using namespace std; int main() { cout<<"2/4="<<2/4<<endl; system("pause"); } Sia il numero 2 che il numero 4 sono interi, perciò il compilatore fornisce il risultato come numero intero. Se almeno uno dei due numeri fosse stato float, anche l'altro numero sarebbe stato convertito in float ed il risultato sarebbe stato un float. Ad esempio scrivendo #include <iostream> using namespace std; int main() { cout<<"2.0/4="<<2.0/4<<endl; system("pause"); } si ottiene come risultato 0.5. 5 La regola è allora che se in una espressione aritmetica esistono operandi di tipo diverso, tutti gli operandi vengono convertiti nel tipo ad occupazione di memoria maggiore. Quindi il risultato sarà di quest'ultimo tipo. 25) Si può convertire una espressione di tipo A in una di tipo B diverso? Sì. La sintassi utilizzata è la seguente: (tipoA) espressione_tipoB Ad esempio: int main() { int A=100000; cout << "A=" << A << endl; cout << " (short) A = " << (short) A << endl; system("pause"); } //cast di tipo fornisce: A = 64000 (short) A = −1536 Il motivo dell'ultimo output sta nel fatto che il numero 100000 è stato convertito in uno short (intero breve) il quale occupa 16 bit. Questo numero di bit non è sufficiente ad esprimere il numero 100000, per cui questo viene troncato portando ad un risultato errato. Si osservi che per brevità nell'esempio precedente, come in quelli che seguiranno, si sono omesse le direttive per il compilatore, che generalmente sono le tre seguenti: #include <iostream> #include <conio.h> using namespace std e che vanno poste ad ogni inizio programma. 26) In quali casi può essere utile il cast di tipo? In molte situazioni. Ad esempio ogni carattere viene codificato con un codice numerico ad 8 bit (byte). In molti casi si desidererebbe conoscere il codice associato ad un carattere non presente sulla tastiera in modo da potere ottenere il carattere dalla pressione del tasto Alt accompagnata dal codice. Ad esempio il carattere ~ (tilde) si ottiene dalla pressione del tasto Alt accompagnata dal numero 126. Un programma che fornisce tale informazione è il seguente: int main() { int A=126; cout << "A=" << A << endl; cout << " (char)A= " << (char) A <<endl; system("pause"); } Tale programma prende l'intero 126 e lo converte in un carattere (la tilde) che verrà stampato dalla cout. Naturalmente per ottenere la stessa uscita si sarebbe potuto scrivere: int main() { char A=123; cout << "A=" << A << endl; system("pause"); } Si è utilizzata la prima versione solo per illustrare il cast di tipo. 6 27) Come si esprimono le costanti a virgola mobile? I numeri a virgola mobile sono i numeri con il punto. Dotati cioè di una parte intera e di una parte decimale. Tali numeri sono detti a virgola mobile poiché si può spostare il punto, che separa le due parti, utilizzando una opportuna potenza di 10. Ad esempio il numero 0.123 posso anche scriverlo come 123.0 e−3. In quest'ultima espressione la lettera e rappresenta la parola esponente. Infatti il numero che segue rappresenta l'esponente da dare al 10 affinché le due espressioni coincidano. Ciò può essere visto col programma: int main() { A=0.123; cout << "A=" << A << endl; cout << "123.0 e−3=" << 123.0e−3 <<endl; system("pause"); } che fornisce per A due valori identici. Si noti che la base e deve essere seguita immediatamente dall'esponente, senza lasciare alcuno spazio. 28) Come si esprimono le costanti carattere e le costanti stringa? Una costante di tipo carattere viene posta fra apici semplici, mentre una costante stringa viene posta fra doppi apici. Ad esempio: int main() { char A='1'; string B="esempio"; cout <<"A=" << A << endl; cout << "B=" << B <<endl; system("pause"); } 29) Come si assegna ad una variabile un valore costante? Mediante un operatore di assegnazione. Si noti che gli operatori di assegnazione sono diversi. Precisamente si possono avere assegnazioni semplici o composte. Le assegnazioni semplici si effettuano con l'operatore = Ad esempio: x=2; assegna alla variabile x, dichiarata in precedenza short, int, long, float o double, il valore 2. Naturalmente se non vi è compatibilità fra il valore assegnato ed il tipo dichiarato si produrrà un errore che tuttavia non viene segnalato dal compilatore. Ad esempio il programma: #include <iostream> using namespace std; int main() { short A=100000; short B=100000; cout <<"A+B=" << A+B << endl; system("pause"); } 7 è perfettamente corretto dal punto di vista sintattico, perciò il compilatore non fornisce alcun messaggio di errore. Tuttavia quando viene eseguito produce: A+B = −62144 Risultato che è chiaramente sbagliato! Il motivo è che una variabile short (2 byte) non può contenere il numero 100000. 30) Come si effettua una assegnazione composta? Facendo precedere l'operatore di assegnazione da uno dei seguenti dieci operatori: + (somma) − (differenza) * (prodotto) / (rapporto) % (modulo) & (AND bit a bit) | (OR bit a bit) ^ (EXOR bit a bit) >> (shift a destra) << (shift a sinistra) Ad esempio la sezione di codice: x = 3; x += 2; cout << " x= " << x ; produce x= 5 Infatti il significato di x += 2 è x = x+2. Analogo significato hanno gli altri operatori di assegnazione composta. 31) Come si stabilisce la precedenza fra gli operatori? Esistono delle tabelle che elencano tutti gli operatori del C++ in ordine di precedenza decrescente. In linea di massima si tenga presente a) Gli operatori con la massima priorità sono quello UNARI, cioè con un solo operando b) A seguire vengono gli operatori aritmetici binari c) Quindi gli operatori di shift e quelli relazionali (ovvero <,<=, >, >=, ==, !=) d) Gli operatori logici sui bit e quelli sulle espressioni logiche e) L'operatore ternario di condizione ?: (condizione?espressione1:espressione2) f) Gli operatori di assegnazione Vedremo i vari operatori un po’ alla volta. 32) Come si associano gli operatori in una espressione priva di parentesi? Si associano quasi tutti da sinistra a destra. Fanno eccezione gli operatori di assegnazione che si associano da destra a sinistra. Ad esempio l'espressione: a+=b+=2; va intesa in questo modo: a +=(b+=2); che significa: prendi il valore di b e sommagli 2. Prendi il valore di a e sommagli quello che hai ottenuto prima. Il programma: int main() { int a=3,b=4; a+=b+=2; cout << "a=" << a <<endl; system("pause"); } produce a=9. 8 33) Quali sono le principali istruzioni del C++? Sono a) le istruzioni condizionali: b) le istruzioni iterative: if-else, for, switch while, do-while, 34) Qual è la sintassi ed il significato della istruzione if-else? La sintassi dell'istruzione di selezione if è la seguente: if (<condizione>) <istruzione1 semplice o composta> else <istruzione2 semplice o composta>; Nella precedente <condizione> indica una espressione logica che possa cioè assumere i valori vero o falso. Tale espressione va posta fra parentesi tonde. Si tenga presente che nel C++ esiste il tipi semplice bool che assume solo i valori true e false. Tuttavia si è mantenuta la compatibilità col C ammettendo che il valore 0 (zero) indica il FALSO, qualsiasi altro valore, anche di tipo float che non sia zero, indica il VERO. <istruzione semplice o composta> indica invece una qualsiasi istruzione o sequenza di istruzioni racchiuse fra parentesi graffe. Il significato è evidente: Se la <condizione> è vera verrà eseguita la <istruzione1>, altrimenti verrà eseguita la <istruzione2>. Ad esempio il programma: int main() { float a=0; if (a) cout<<"a=vero \n"; else cout <<"a=falso \n"; system("pause"); } produce a=falso 35) Come si costruisce una espressione condizionale? Utilizzando gli operatori relazionali: == (uguaglianza:si noti la differenza rispetto all'assegnazione) > (maggiore) < (minore) >= (maggiore od uguale) <= (minore od uguale) != (diverso) 36) Si possono ottenere condizioni composte utilizzando gli operatori logici? Si, sono utilizzabili gli operatori: && and) || (or) ! (not) Ad esempio: 9 int main() { bool a=0,b=0; if ((a)||(b)) cout << "vero \n"; else cout <<"falso \n"; system("pause"); } produce l'uscita falso. Cambiando i valori iniziali di a e di b si può ottenere la tavola di verità del simbolo || (or). Si noti che ciascuna condizione semplice e l'inera condizione composta vanno racchiuse fra parentesi. 37) Esiste un operatore condizionale ternario? Si. E' l'operatore ?: In questo caso i due caratteri non costituiscono una unità simbolica, ma nel loro uso sono separati. L'uso dell'operatore condizionale ternario è il seguente: Il valore della espressione condizione?espressione1: espressione2 coincide col valore dell'espressione1 se la condizione è vera; coincide invece col valore della espressione2 se la condizione è falsa. Ad esempio: int main() { (2>3) ? cout << "maggiore \n" : cout <<"minore \n"; system("pause"); } Il precedente programma scrive minore, dal momento che la condizione (2<3) è falsa. Si noti che cout<<variabile/costante è una espressione particolare il cui valore è il valore della variabile oppure è la costante posta a video. 38) Esiste un operatore che consente di inserire due o più espressioni laddove la sintassi prevede l'inserimento di una singola espressione? Si. E' l'operatore , (virgola). Ad esempio: int main() { int a; (2>3)? a=2 , a++ : a=3 , a++; cout << "a=" << a <<endl; system("pause"); } Nel precedente, l'espressione posta fra i simboli ? e : è una espressione composta, ottenuta applicando l'operatore virgola. Ovvero a=2 , a++ Anche l'espressione posta dopo il simbolo : è composta. Essa è infatti a=3 , a++ Il risultato del programma si ottiene calcolando quest'ultima espressione composta, che fornisce il valore 4, ottenuto INCREMENTANDO il valore assegnato ad a. 10 39) Qual è il significato dell'operatore unario ++ ? E' quello di INCREMENTO dell'espressione che lo segue o lo precede. Si noti infatti che tale operatore può essere prefisso (esempio ++a) oppure postfisso (esempio a++). Nel caso che l'espressione ++a venga assegnata alla variabile b , PRIMA viene incrementata a e poi avviene l'assegnamento a b. Viceversa se a++ viene assegnato a b, prima avviene l'assegnamento e poi l'incremento. Ad esempio: int main() { int a=1,b; b=++a; cout<<"b dopo PREINCREMENTO="<<b<<endl; a=1; b=a++; cout<<"b dopo POSTINCREMENTO="<<b<<endl; system("pause"); } Il primo valore di b vale 2 (piochè a viene prima incrementata e poi assegnata) Il secondo valore di b vale 1, poiché a viene prima assegnata e poi incrementata. 40) Come viene effettuata la lettura dei dati di ingresso al programma? Mediante lo streaming di ingresso standard (cin). Questo è un canale associato normalmente all'unità di ingresso principale, ovvero alla tastiera. Lo stream cin viene utilizzato facendo seguire il nome cin dall'operatore >> (che indica la direzione dei dati di ingresso) seguito dal nome della variabile che deve essere letta e che è stata dichiarata in precedenza. Ad esempio: int main() { short int a=3; cout<<"Inserisci un valore numerico"<<endl; cin>>a; cout<<"a="<<a<<endl; system("pause"); } Il precedente programma chiede di inserire un valore numerico. Se tale valore è del tipo dichiarato per la variabile allora il valore viene assegnato alla variabile a. Se viceversa tale valore non è compatibile con il tipo dichiarato la variabile, quest'ultima conserva il suo valore iniziale (in questo caso 3). Se ad una variabile intera non viene assegnato alcun valore iniziale, per default viene inizializzata a zero. Se viene assegnato un valore non del tipo dichiarato, ma compatibile con questo, viene fatta la conversione dal un tipo all'altro. Ad esempio se la variabile a viene dichiarata intera e le viene assegnato il valore 3.2, la variabile riceverà il valore 3. 41) E' possibile leggere più variabili contemporaneamente? Si. Ad esempio il programma: 11 int main() { int numero1, numero2; char operatore; cout<<"Inserisci numero1 operatore numero2"<<endl; cin>>numero1>>operatore>>numero2; cout<<"numero1="<<numero1<<endl; cout<<"operatore="<<operatore<<endl; cout<<"numero2="<<numero2<<endl; system("pause"); } Consente di inserire la stringa 123+456 ottenendo le assegnazioni: numero1=123 operatore=+ numero2=456 Tuttavia si deve stare molto attenti a che vi sia rispondenza fra i tipi dichiarati per le variabili ed i valori inseriti, poiché se per errore si batte un solo valore errato potranno risultare errati i valori assegnati a molte variabili. 42) Come viene effettuato l'output dei dati? Mediante lo streaming standard cout seguito dall'operatore << (che indica la direzione dei dati di uscita), seguito a sua volta dalla variabile (o dalla costante) che deve essere mandata sull'unità di uscita standard (schermo). Si possono inviare all'uscita i valori di più variabili (o costanti) a condizione di separarle dall'operatore <<. Ad esempio: int main() { int num1=123,num2=456; cout<< "numero1=" << num1<< "\n numero2=" << num2<< endl; system("pause"); } fornisce: numero1=123 numero2=456 43) Cosa significa il simbolo \n che appare nel programma precedente? Nel programma precedente si è utilizzato il carattere speciale \n (newline), detto carattere di escape, ottenuto facendo seguire il carattere \ (backslash) dalla lettera n (iniziale di newline). Caratteri analoghi sono: \t (tab) \a (alarm) \" (virgolette) \' (apice) \\ (backslash) \0 (carattere NULL : terminatore di stringa) 44) Quali sono le funzioni associate allo stream di uscita cout? Lo stream di uscita cout è un oggetto, ovvero una variabile di tipo classe, la quale, come si dirà nel seguito è un aggregato di variabili e di funzioni, utilizzabili dagli oggetti della classe. Le variabili di una classe vengono dette ATTRIBUTI. Le funzioni sono dette METODI. Gli attributi della classe cout sono i seguenti: 12 a) width(intero) Consente di definire il numero di caratteri del campo in cui verrà scritto il dato in uscita con l'istruzione cout successiva a width(). Ad esempio l'istruzione cout.width(10); significa che il dato che verrà scritto con la successiva cout verrà scritto in un campo di 10caratteri. Si noti che l'impostazione precedente vale solo per il prossimo cout, non per i successivi. Ad esempio: int main() { int num1=123,num2=456; cout.width(10); cout<<num1<<endl; cout<<num2<<endl; system("pause"); } Produce: 123 456 Se il numero di caratteri del dato è inferiore a quelli del campo, allora i caratteri del campo non utilizzati saranno degli spazi, oppure saranno i caratteri specificati con l'istruzione: cout.fill('carattere'). b) precision(intero) Vale solo per i NUMERI REALI, e consente di fissare il numero di cifre utilizzato per visualizzare il numero. Se questo è più grande della precisione fissata, viene arrotondato. Ad esempio: int main() { float num=12.3456; cout.precision(4); cout << "num=" << num << endl; system("pause"); } produce num=12.35 Si noti che per default la precisione è 6. Per cui il programma: int main() { double num=12.3456789; cout << "num=" << num << endl; system("pause"); } produce num=12.3457 OVVERO ARROTONDA LA SESTA CIFRA, producendo un errore anche se il tipo scelto per rappresentare la variabile è ampiamente sufficiente per il valore assegnato a quest'ultima. L'errore precedente si può eliminare facendo precedere la cout da: cout.precision(9); c) flag(argomento) Consente di allineare a sinistra il dato nel campo (argomento=ios::left), oppure a destra (ios::right) . L'allineamento è mantenuto per tutte le stampe successive. Per default è a destra. Consente anche di fissare la notazione dei numeri reali che può essere fissa (ios::fixed), oppure scientifica (ios::scientific). Nel caso di notazione scientifica la precisione fornisce il numero di cifre dopo la virgola. 13 CICLI 45) In che modo è possibile ripetere un blocco di istruzioni più volte? Utilizzando l'istruzione do-while. Si noti che questa istruzione prevede che il blocco delle istruzioni sia eseguito almeno una volta, dopodiché sarà RIESEGUITO fintantoché la condizione che segue il while rimane vera. La sintassi è: do { sequenza di istruzioni; }while (condizione_di_ripetizione); Ad esempio un ciclo che continua a leggere un numero fintantochè il valore inserito è minore di 10 o maggiore di 20 è il seguente: int main() { int x; do { cout<<"Inserisci un numero fra compreso fra 10 e 20, estremi inclusi. \n"; cin>>x; }while ( x<10 || x>20 ); } cout << "numero inserito:"<<x<<"\n"; system("pause"); Si noti che la lettura del numero deve essere ripetuta finchè (fintantochè) si verifichino delle condizioni indesiderate. Tali condizioni sono x<10 oppure x>20. Il simbolo || equivale all'operatore logico OR. Perciò la condizione di riesecuzione del ciclo è una condizione composta dalle due condizioni semplici precedenti, tramite l'operatore OR. 46) Quali sono gli operatori logici che si possono utilizzare per ottenere una condizione composta? Sono gli operatori: ! NOT || OR && AND Per ottenere una condizione composta occorre utilizzare gli operatori logici di negazione, congiunzione e disgiunzione, ovvero gli operatori logici NOT, AND e OR. Tali operatori si esprimono coi simboli ! (NOT) && (AND) || (OR) Quando si scrive una espressione condizionale senza parentesi occorre fare attenzione alla PRECEDENZA fra gli operatori. Ad esempio gli operatori relazionali di uguaglianza, maggioranza e minoranza hanno la precedenza rispetto agli operatori logici binari. Ad esempio il programma: 14 int main() { int x; do { } cout<<"Inserisci numero maggiore di 10"; cin>>x; }while (!x<10) ; entra in un loop infinito. Infatti la condizione: (!x<10) a causa del fatto che l'operatore unario ! ha la precedenza rispetto all'operatore relazionale <, viene intesa come segue: Nega il valore logico di x (se x diverso da 0 la negazione logica è zero, mentre se x=0 la negazione logica produce 1) e controlla se quello che ottieni è minore di 10. Poiché quello che si ottiene è sempre minore di 10 non si esce mai dal ciclo. Fra i due operatori && e || ha la precedenza &&. Ciò può essere visto col programma: int main() { bool A=true, B=false, C=false; cout << "A || B && C=" << (A||B && C) <<endl; system("pause"); } che fornisce A || B && C=1 (cioè vero). Ciò significa che viene effettuato prima l'and e poi l'or (altrimenti si sarebbe ottenuto 0 (cioè falso) 47) Qual è l'istruzione iterativa più usata? E' l'istruzione for. Utilizzando solo tale istruzione assieme all'assegnazione si possono scrivere una quantità innumerevole di programmi. La sintassi è la seguente: for( espr_iniziale; condizione_esecuzione; espr_finale) {sequenza_istruzioni;} L' espressione iniziale viene valutata prima di eseguire il ciclo. Si noti che anche una semplice assegnazione è una espressione (una espressione è una stringa di costanti, variabili ed operatori). La condizione_di esecuzione viene valutata per stabilire se rieseguire il ciclo. Il ciclo si riesegue fintantochè tale condizione è vera. Infine la espressione finale viene eseguita al termine di ogni ciclo. Ad esempio il seguente programma esegue la somma dei primi 10 interi. const int N=10; int main() { int i, somma=0; for (i=1; i<=N; i++) somma=somma+i; cout << "somma dei primi 10 interi =" << somma << endl; system("pause"); } 15 48) Qual è il significato del termine riservato const che appare nel programma precedente? La istruzione const int N=10; è una DICHIARAZIONE DI COSTANTE. Essa consente non solo di dichiarare il tipo della costante, ma anche di assegnargli un valore che non potrà essere cambiato nel corso dell'esecuzione del programma. 49) E' possibile omettere una o più espressioni che appaiono nella sintassi del for? Si, ma non si può omettere il corrispondente punto e virgola. Ad esempio il programma precedente si può scrivere: const int N= 10; int main() { int i=1, somma=0; for ( ; i<=N ; i++) somma=somma+i; } //si noti che l'espressione iniziale del for è vuota cout<< "somma dei primi 10 interi=" <<somma <<endl; system("pause"); Ovvero si può inizializzare la variabile i fuori dal ciclo, tuttavia il ; che separa la prima espressione del for dalla condizione di esecuzione, utilizzata generalmente per inizializzare le variabili del ciclo, deve apparire nel for. 50) Si possono utilizzare due for innestati l'uno dentro l'altro? Certo. Come istruzione del ciclo for può essere utilizzata qualsiasi altra istruzione. Quindi anche un altro for. Ad esempio il seguente programma legge (e scrive) una matrice per righe. //matrice #include <iostream> using namespace std; const int N= 3; int main() { int i, j, A[N][N]; cout << "Inserisci una matrice intera 3x3" << endl; for ( i=0 ; i<N ; i++) { for ( j=0 ; j<N; j++) cin >> A[i][j]; cout << endl; } cout<< "Matrice:" <<endl; for ( i=0 ; i<N ; i++) { for ( j=0 ; j<N ; j++) { cout.width(6); cout << A[i][j]; } cout << endl; } system("pause"); } 16 ARRAY 51) Cosè una matrice? Una matrice è un ARRAY a più dimensioni. A sua volta un array è un insieme di elementi, tutti dello stesso tipo, caratterizzati da un NOME e da un indice intero. Quando si fa riferimento ad un particolare elemento di un array ,l'indice di tale elemento va posto in parentesi quadre. Ad esempio: const int A[10]={1,2,3,4,5,6,7,8,9,10}; dichiara che A è un array costituito da 10 elementi interi e assegna un valore iniziale ad ogni elemento. Volendo riferirsi al primo elemento di A si utilizzerà la scrittura: A[0]. Ad esempio volendo sommare tutti i valori di A si utilizzerà un for del tipo: int somma=0; for(i=0;i<10;i++) somma=somma+A[i]; Il programma: int A[10] = {1,2,3,4,5,6,7,8,9,10}; int main() { cout<<"Vettore="; for (int i=0; i<10; i++) cout << A[i] << '\t'; system("pause"); } dopo aver dichiarato l'array A ed avergli assegnato dei valori iniziali, fa la stampa dei suoi elementi. Gli elementi sono separati dal carattere \t (tab) Si noti che il valore dell'indice iniziale deve essere zero. Perciò se l'array ha dimensioni N, i valori dell'indice varieranno da 0 ad N-1 52) E' possibile una uscita anticipata da un ciclo? Si, utilizzando l'istruzione oppure l'istruzione break; continue; La prima provoca l'uscita immediata dal ciclo in cui è inserita. La seconda provoca il salto alla fine del ciclo e l'esecuzione del ciclo successivo. Ad esempio: int main() { for (int i=0; i<20; i++) { if (i%2==1)continue; cout<<i<<'\n'; } system("pause"); } 17 produce in uscita l'elenco dei numeri pari minori di 20. Infatti ogni volta che si incontra un numero dispari, ovvero che i%2==1 (resto della divisione per due uguale ad uno) si salta a fine ciclo attuale, saltando l'istruzione di stampa. Se si fosse scritto break al posto di continue si sarebbe ottenuto la stampa del solo numero 0, poiché break provoca l'uscita definitiva dal ciclo. STRINGHE 53) Come si gestiscono le stringhe nel C++? Le stringhe nel C++ sono considerate degli array di caratteri terminanti col carattere speciale '\0' (NULL). Per leggere una stringa si può utilizzare la funzione gets(stringa) contenuta nella libreria conio.h Ad esempio il programma seguente legge e scrive una stringa: #include <iostream> #include <conio.h> using namespace std; int main() { char s[80]; cout<<"Inserire stringa:"<<endl; gets(s); //è preferibile rispetto a cin<<s poichè quest'ultima non consente //di inserire nella stringa spazi bianchi cout<<"s="<<s; system("pause"); } 54) Esiste una libreria standard che consente operazioni sulle stringhe? La libreria cstring consente di effettuare sulle stringhe una serie di operazioni. Fra queste: sono importanti: a) strcpy(s1,s2) copia la stringa s2 sulla stringa s2 b) strcat(s1,s2) concatena la stringa s2 alla stringa s1) c) strlen(s) fornisce il numero di caratteri di s, compresi gli spazi d) strstr(s1,s2) fornisce la sottostringa di s1 che inizia con s2 Il funzionamento delle precedenti funzioni è illustrato dal programma: #include <iostream> #include <cstring> #include <conio.h> using namespace std; int main() { char s1[80]="prima stringa lunga", s2[80]="seconda stringa", s3[80]=""; //s3=stringa vuota cout << "lunghezza s1=" << strlen(s1); getch(); cout << " sottostringa di s1 iniziante con stringa:" << strstr(s1,"stringa"); getch(); strcpy(s3,s1); //copia s1 su s3 cout << "s3=" << s3 << endl; strcat(s3,s2); //concatena s2 ad s3 cout << "s3=" << s3 << endl; system("pause"); } 18 STRUTTURE 54) Cosa sono le strutture? Le strutture sono tipi di dati molto importanti, perché generalizzando tale tipo nascono le CLASSI che sono alla base della programmazione ad oggetti (OOP). Una struttura è un insieme di dati aventi generalmente tipi diversi fra loro e tuttavia riferentesi al medesimo "oggetto". I divcersi elementi di una struttura sono detti MEMBRI. Se s è una variabile di tipo struttura si accede ad un membro m di s con la scrittura s.m Il seguente programma definisce la stuttura punto come un insieme dei campi interi x ed y, dichiara la variabile p di tipi punto e ne legge il valore. #include <iostream> using namespace std; struct punto { int y; }; int x; int main() { struct punto p; p.x=2; p.y=3; cout << "punto=(" << p.x << "," << p.y<< ")"; system("pause"); } 55) Si possono definire array di strutture? Si. Ad esempio il programma seguente definisce la struttura studente . Dichiara un array di N studenti. Legge i dati relativi agli N studenti e li scrive. #include <iostream> using namespace std; struct studente { char cognome[16]; int eta; float mediaVoti; }; const int N=3; //N=numero studenti int main() { int i; struct studente s[N]; for(i=0; i<N; i++) { cout << "Inserisci cognome studente " << i+1 << "\t: " ; cin >> s[i].cognome; cout << "Inserisci eta' studente " << i+1 << "\t: " ; cin >> s[i].eta; cout << "Inserisci media voti studente "<< i+1 << "\t: " ; cin >> s[i].mediaVoti; } cout<<"\nDati inseriti:"<<endl; for(i=0; i<N; i++) { cout << "\ncognome studente "<< i+1<<"\t:" ; cout << s[i].cognome<<endl; cout << "eta studente "<< i+1 << "\t\t:"; cout << s[i].eta<<endl; cout << "media voti studente " << i+1<< "\t:"; cout << s[i].mediaVoti<<endl; } system ("pause"); } 19