Professional Documents
Culture Documents
NunzioBrugaletta
C++:programmazioneedoggettipag.1
(2015.10)
Indice
0Guidaall'uso:avvertenzaimportante................................................................................................3
1Introduzioneallaprogrammazione....................................................................................................4
1.1Concettifondamentalisuglialgoritmi.......................................................................................4
1.2Rappresentazionedialgoritmi,istruzionielementari................................................................4
1.3Lestrutturedicontrollo.............................................................................................................6
1.4Accumulatoriecontatori...........................................................................................................9
1.5Cicliacontatore.......................................................................................................................11
1.6Applicarelestrutturedicontrollo:esempiostepbystep........................................................13
2FondamentidiC++:costruttidibase..............................................................................................15
2.1Cennisuilinguaggidiprogrammazione..................................................................................15
2.2IllinguaggioCeilC++...........................................................................................................15
2.3Strutturadiunprogramma.......................................................................................................16
2.4Codificadiunprogrammaconstrutturasequenziale..............................................................17
2.5Variabiliedassegnamenti........................................................................................................19
2.6Lostreamdioutput..................................................................................................................21
2.7Lostreamdiinput....................................................................................................................22
2.8Costruttoifedichiarazionidicostanti.....................................................................................23
2.9Istruzionicomposte..................................................................................................................25
2.10Loperatore?..........................................................................................................................26
2.11Autoincrementoedoperatoridoppi.......................................................................................26
2.12Preepostincremento............................................................................................................27
2.13Cicliecostruttowhile............................................................................................................28
2.14Cicliecostruttofor................................................................................................................29
2.15Cicliecostruttodowhile.......................................................................................................31
2.16SoftwareEngineering:lostilediscrittura.............................................................................31
2.17Dall'algoritmoalcodice:procedimentostepbystep............................................................33
3Vettori,stringhe,costruttiavanzati.................................................................................................36
3.1Tipididatiemodificatoriditipo.............................................................................................36
3.2Ilcast........................................................................................................................................39
3.3Introduzioneaclassieoggetti:ivettori...................................................................................41
3.4Iteratori.....................................................................................................................................43
3.5Elaborazionidibasesuivettori.Unesempiostepbystep.......................................................44
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.2
3.6Utilizzometodidellaclassevector..........................................................................................49
3.7Laclassestring.........................................................................................................................51
3.8Stringhe:esempidiutilizzodeimetodidellaclasse................................................................53
3.9Lasceltamultipla:costruttoswitchcase.................................................................................57
3.10Vettoridistringhe..................................................................................................................59
4Ilparadigmaprocedurale.................................................................................................................62
4.1Costruzionediunprogramma:losviluppotopdown.............................................................62
4.2Comunicazionifrasottoprogrammi.........................................................................................63
4.3Visibilitenamespace.............................................................................................................65
4.4Tipidisottoprogrammi............................................................................................................66
4.5LefunzioniinC++.Istruzionereturn......................................................................................67
4.6Ilmetodotopdown:unesempiostepbystep.........................................................................69
5Struttureetabelle.............................................................................................................................74
5.1Lestrutture...............................................................................................................................74
5.2Tabelle:vettoridistrutture......................................................................................................75
6Ilparadigmaadoggetti....................................................................................................................81
6.1Estensionedellestrutture:leclassi..........................................................................................81
6.2OOP:progettoeusodiclassistepbystep.Costruttori...........................................................83
6.3Gestionebibliotecastepbystep(1):laclasselibro.................................................................87
6.4Gestionebibliotecastepbystep(2):laclasselibreria.............................................................91
6.5Gestionebibliotecastepbystep(3):lafunzionemain............................................................94
6.6Ereditariet:dalibroalibSocio...............................................................................................98
6.7Rivisitazionedelprogrammadigestioneprestiti..................................................................102
6.8Leclassimodello:itemplate.................................................................................................102
6.9Utilizzodelleclassitemplate.................................................................................................105
7Datisumemoriedimassa..............................................................................................................107
7.1Input/Outputastratto..............................................................................................................107
7.2Esempidigestionedifileditestosudischi:ifileCSV........................................................107
8Riferimentibibliografici................................................................................................................111
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.3
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.4
Cio:sesisommaunvalorequalsiasiconsstessosiottieneildoppiodelvalorestesso.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.5
Ognivariabileidentificatadaunnomechepermettedidistinguerladallealtre.Inlineateoricail
nomepotrebbeesserequalsiasimaperragionidichiarezza,diopportunitlegatealleregoledei
linguaggidiprogrammazionebenerispettarealcuneregole:
1. nel nome possono essere usati caratteri (dell'alfabeto inglese e, quindi, niente lettere
accentate presenti per esempio nella lingua italiana), cifre numeriche e il carattere di
sottolineatura (_). Non possono essere usati n spazi n segni di punteggiatura (hanno
significatiparticolarineilinguaggidiprogrammazione).Ricordarechealcunilinguaggidi
programmazione, per esempio il C++ di cui si tratta in questi appunti, distinguono fra
maiuscole e minuscole e che, in questi casi, convenzione usare lettere minuscole e
riservarelemaiuscoleperdistinguereleparolesesivuoleattribuireilnomeadunavariabile
inmodochepossaesserecompostodapiparole.Es.:AltezzaTriangolo
2. ilnomedeveesserequantopipossibileesplicativoe,contemporaneamente,ilpibreve
possibile. Es.: potrebbe andare bene AltTriang ma va un po' meno bene a (poco
comprensibile)
Aprescinderedallinguaggiodiprogrammazionechetradurr,perchpossaessereeseguitodaun
computer,unalgoritmo,neitempisonostatiadottatidiversisistemiperrappresentareglialgoritmi
inmodochesiasemplicecomprendernelalogica.Inquestiappuntisiesporrannoinparallelodue
sistemi:idiagrammidiNassiSchneiderman(NS)elapseudocodificaolinguaggiodiprogetto
(L.P.).
Ilprimounsistemagraficocheevidenziachiaramente,acolpod'occhio,lastrutturacomplessiva
dell'algoritmo ed possibile verificare la correttezza dell'algoritmo utilizzando un programma
(vedere riferimenti bibliografici per maggiori informazioni) che permette di esaminare l'effetto
passopassodelleistruzionichevengonoeseguite.unostrumento,quindi,chefornisceunvalido
aiutoquandosideveimparareacomporreiprimialgoritmieverificarnelacorrettezza.
Lapseudocodificapiadattaperlagestionedelpassaggioalgoritmoprogramma.Utilesempre
quandosihanecessitdifissareleideeinfasidelicatedellaprogettazionediunprogramma.
Leistruzionielementarichepossonoessereusatepercomporreunalgoritmosono:
Listruzionediassegnamentofainmodocheundeterminatovaloresiaconservatoinuna
variabile. In questo modo si prepara la variabile per lelaborazione o si conserva nella
variabileunvaloreintermedioprodottodaunaelaborazioneprecedente.Sipuassegnaread
una variabile un valore costante come anche il valore risultante da una espressione
aritmetica.
alfa <- beta+gamma*2
L'espressionearitmeticavienevalutataeilvalorerisultantevieneinseritonellavariabile
ricevente(nell'esempio alfa).Nell'espressionealgebricapossonoessereusatiglioperatori
aritmetici+(somma),-(sottrazione),*(prodotto),/(divisione).Laprioritdeglioperatori
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.6
quelladell'aritmeticaepuesseremodificatautilizzandoleparentesitonde.
alfa <- ((beta+gamma)*2+delta)/10
Ogninuovaassegnazioneallastessavariabiledistruggeilvaloreconservatoinprecedenza
perfarepostoalnuovo.
Listruzionediinputfainmodochelalgoritmo,durantelasuaesecuzione,possaricevere
dallesternounvaloredaassegnareadunavariabile.Nelcasodialgoritmieseguitidaun
elaboratore,questiattendechedaunaunitdiinput(peresempiolatastiera)arriviuna
sequenzadicaratteritipicamenteterminanticonlapressionedeltasto Invio.Ildatoverr
assegnatoallavariabileappositamentepredisposta.Praticamentesitrattadiunaistruzionedi
assegnamentosoloche,stavolta,ilvaloredaassegnareprovienedallesterno.
leggi omega
Listruzionedioutput fainmodochelalgoritmocomunichiallesternoirisultatidella
propriaelaborazione.Nelcasodiunelaboratorevieneinviatosuunaunitdioutput(per
esempioilvideo)ilvalorecontenutoinunadeterminatavariabileounasequenzadicaratteri
(unastringa)dastamparecoscome.
scrivi delta
scrivi buon giorno
necessariointrodurre,oltrealleistruzionielementari,delleleggidicomposizionedelleistruzioni,
deglistrumentichepermettanodicontrollarelesecuzionedellalgoritmoinconseguenzadieventi
chesiverificanoinsedediesecuzione:lestrutturedicontrollo.L'algoritmospecificacosafarein
generale. Durante l'esecuzione verranno forniti i dati e l'algoritmo produrr dei risultati di
conseguenzaaidatiinseritiealleelaborazionispecificate.
Laprogrammazionestrutturata(disciplinanataallafinedeglianni'60perstabilireleregoleper
lascritturadibuonialgoritmi)imponelusoditresoleregoledicomposizionedeglialgoritmi:
la sequenza: questa struttura permette di specificare lordine con cui le istruzioni si
susseguono:ogniistruzioneproduceunrisultatoperchinseritainuncontestochequello
determinatodalleistruzionichelaprecedono.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.7
NS
L.P.
CalcoloAreaRettangolo
INIZIO
leggi base
leggi altezza
area <- base*altezza
scrivi area
FINE
L.P.
CalcoloQuoziente
INIZIO
leggi divid
leggi divis
if (divis != 0)
quoz <- divid/divis
scrivi quoz
else
scrivi impossibile
end-if
FINE
Dopolasequenzachespecifical'acquisizionedeivaloridaassociareallevariabili divide
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.8
Lacondizioneespressanellastrutturaifpermettelascelta,inrelazionealvalorediverito
falsitdellacondizionespecificata,dellaelaborazionedasvolgere.Lasequenzacontenuta
nellaparteelse(F)potrebbemancaresesivolessesoltantounrisultatoladdovepossibile:
in tale caso se la condizione risultasse non verificata, non si effettuerebbe alcuna
elaborazione. L'esecuzione di questo algoritmo porter l'esecutore, nel caso specifico il
computer, a decidere cosa fare, quali istruzioni eseguire, in conseguenza dei dati che
vengonointrodotti.Insedediscritturadell'algoritmo,nonconoscendoivalori,sipossono
solospecificareicasipossibili,elencareleistruzionidaeseguireefornireglielementi(la
condizionedaverificare)persceglierelacorrettasequenzadielaborazione.
Laend-ifnelL.P.indicailpuntodoveterminaladifferenzadielaborazioneel'algoritmo
pu proseguire con le prossime istruzioni che, nel caso di esempio, non esistono.
L'algoritmo dell'esempio prevedeunasequenzacomposta dalledueistruzioni diinpute
dallaselezione.
InNSsipunotarevisivamentecheleduestradesonoalternative.InL.P.talecaratteristica
evidenziata dal rientro delle istruzioni rispetto al bordo in cui allineata l'istruzione
precedente.
Nella condizione da testare, fra le parentesi, possono essere utilizzati gli operatori di
confronto: ==(uguale), != (diverso), < e<= (minore,minoreouguale), > e>= (maggiore,
maggioreouguale).Ilconfrontopuesserefattofra:duevariabili,unavariabileeunvalore,
unavariabileeilrisultatodiunaespressionealgebricacheproduceunvalore.
literazione: la struttura iterativa permette di ripetere pi volte la stessa sequenza di
istruzionimentrecontinuaaessereverificataunadeterminatacondizione(cicloWHILE).
Chiaramente non avrebbe alcun senso ripetere sempre le stesse istruzioni se non
cambiassero i valori a cui si applicano le operazioni specificate nella sequenza. Le
elaborazioni previste nella sequenza iterata devono potersi applicare a variabili che
cambianoillorovalore:vuoiperunaassegnazionediversaperogniiterazione,vuoiperun
input.Atitolodiesempio,riportatounalgoritmochecalcolaestampasuvideoiquadrati
diunaseriedinumeripositivi.Sitratta,inaltritermini,dieffettuarelastessaelaborazione
(calcoloevisualizzazionedelquadratodiunnumero)effettuatasunumeridiversi(quelli
chearriverannodallinput):
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.9
L.P.
SerieQuadrati
INIZIO
leggi num
while(num > 0)
quadrato <- num*num
scrivi quadrato
leggi num
end-while
FINE
Nelcorpodellastrutturaiterativa(lapartecompresafra whileeend-while)sonospecificatele
istruzioniperilcalcolodelquadratodiunnumero:literazionepermettediripeteretalecalcolo
pertuttiinumericheverrannoacquisititramitelistruzionediinputinseritanelliterazionestessa
che,nonsuperfluosottolineare,fornisceunsensoatuttalastruttura(irisultati,nonostantele
istruzioni sianosemprelestesse,cambiano perch cambiano ivalori). Lacondizione num>0
vienechiamata condizionedicontrollodelciclo especificaivaloripercuil'elaborazioneha
senso(ilvaloreintrodottodainputpositivo):siricordachelalgoritmodeveesserefinitoenon
sipuiterareallinfinito.Ilprimoinputfuoriciclohaloscopodipermetterelimpostazionedella
condizionedicontrollosulciclostessoestabilire,quindi,quandoterminareleiterazioni.Seil
valoreintrodottonellavariabile num nulloonegativo ilcicloterminaesutalenumeronon
viene effettuata alcuna elaborazione. Il valore introdotto perfarterminare il ciclo talvolta
chiamatovaloresentinella.
Leregoleperlacomposizione dellacondizione dicontrollodelciclocoincidono conquelle
esaminateinprecedenzaperlacondizionediunaselezione.
Ingeneralesipudirechelastrutturadiunaelaborazioneciclica,controllatadalverificarsidi
unacondizione,assumeilseguenteaspetto:
Considera primo elemento
while elementi non finiti
Elabora elemento
Considera prossimo elemento
end-while
Lestrutturedicontrollodevonoesserepensatecomeschemidicomposizione:unasequenzapu
contenereunaiterazioneche,asuavolta,contieneunaselezionecheasuavoltapucontenere
dell'altroecosvia.Ogniistruzione,laddoveprevista,puessereunaqualunquedellestrutturedi
controllo. Quando si parla di istruzione non si intende quindi, necessariamente, una singola
istruzionemaunastrutturadicontrollochepucontenere,allimite,unasolaistruzione.
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.10
Linizializzazioneservesiaadaresensoallistruzionediaggiornamento(cosasignificherebbela
frase: aggiornailvaloreesistenteconilnuovovalore senonsifossesicuridiaverassegnatoun
valoreinizialedacuifarpartirel'aggiornamento?),siaafareinmodochelaccumulatorestesso
contengaunvalorecoerenteconlelaborazionedasvolgere.Nellesempiodiprimailnuovocliente
non pu pagare prodotti acquistati dal cliente precedente: il totalizzatore deve essere azzerato,
primadicominciarelelaborazione,affinchcontengaunvalorecherispecchiesattamentetuttoci
chestatoacquistatodalclienteesaminato.
Laggiornamentovieneeffettuatoallinternodiunciclo.Seinfattisiriflettesulladefinizionestessa
ditotalizzatore,facileprendereattocheavrebbepocosignificatofuoridaunciclo:comesipu
cumularevalorisenonsihannounaseriedivalori?
Quandoivaloridaesaminaresonostatituttiintrodotti,iltotalizzatoreconterrilvalorecercato.
Nellesempio di prima tutto ci si tradurrebbe: finito lesame dei prodotti acquistati, si potr
presentarealclienteiltotaledacorrispondere.
A titolo di esempio di utilizzo di accumulatori e contatori, viene presentata la risoluzione del
seguenteproblema:dataunasequenzadinumeripositivi,senevuolecalcolarelamediaaritmetica.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.11
NS
L.P.
Media
INIZIO
tot <- 0
c <- 0
leggi n
while(n > 0)
tot <- tot+n
c <- c+1
leggi n
end-while
med <- tot/c
scrivi med
FINE
Coerentemente con quanto visto nello schema generale dell'utilizzo dei totalizzatori, tot
inizializzato, prima del ciclo, al valore nullo poich deve rispecchiare la somma dei numeri
introdotti da input e, quindi, non essendo ancora stata effettuata alcuna elaborazione su alcun
numero, tale situazione viene espressa assegnando il valore neutro della somma. Le stesse
considerazionivalgonoperilcontatore c,azzeratoperch,perilmomentononsonostatiinseriti
numeri.Sarannoaggiornati,ambedue,all'internodelciclo.
Dopolaconclusionedelciclosipossonoutilizzaretotalizzatoreecontatoreinquantoicontenuti
sonocoerenticonimotividellaloroesistenza:totdeveaccumularetuttiivalorichedevonoessere
contatidac,eciavverrquandotuttiinumeridaconsideraresarannostatielaborati,cioinuscita
dalciclo.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.12
Ciclofor
siacquisisceperprimacosailnumerorappresentantelaquantitdelleiterazioni.
Subito dopo si pu procedere con l'elaborazione ciclica: un contatore automatico si occupa di
verificareseilvalorecontenutonelcontatoreabbiaraggiuntolaquantitprefissatae,inquesto
caso,dibloccarel'iterazione.Nonnecessarioalcuninputaggiuntivo.
Comeesempiosiriportal'algoritmodelcalcolodellamediarisolto,questavolta,perunaquantit
quantidinumeri.
NS
L.P.
MediaFOR
INIZIO
tot <-0
leggi quanti
for i<-1 to quanti
leggi n
tot <- tot+n
end-for
med <- tot/quanti
scrivi med
FINE
Rispetto alla versione precedente (ciclo WHILE) qui: non necessario acquisire l'elemento
sentinella, si conosce il numero delle iterazioni da effettuare. Non necessario utilizzare un
contatoreaparteutilenelcalcolodellamedia(c'giquanti).
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.13
NoninfattiuncicloFORperchnonsiconoscelaquantitdirighedicuicompostalafattura.
Adessonecessarioadattareloschemageneralealcasoinesame,rispondendoalledomande:
Chisonoglielementidaelaborare?Lerighedellafattura.Ognielementodaelaborareuna
rigacompostadaqvenepzun.
Cosa vuol dire Considera elemento? Ovvero: come si conoscono i dati di ogni riga?
Acquisendolidall'input.
Come si capisce che le righe della fattura sono finite? Non c' nella definizione del
problemaalcunaindicazionesull'elementosentinella,mainquestocasosipuconsiderare
unarigaconquantitdioggettivenduticonvalorenulloonegativo.
Che elaborazione effettuare sulla riga? Come evidenziato in precedenza si tratta di
calcolare iltotale della riga.Totale chepotrebbe essereconservato nella variabile totr
(variabiletemporaneacheconservaunrisultatointermediodellaelaborazione).
Iltotaledellafatturaderivadall'accumulodeitotalidituttelerighedellafattura.Sitrattaquindidi
untotalizzatore:
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.14
Inizializzazione totalizzatore
Inizio ciclo aggiornamento totalizzatore
...
Aggiornamento totalizzatore
Fine ciclo
Uso del totalizzatore
Ancheinquestocasonecessariorispondereadalcunedomande:
CosavuoldireInizializzatotalizzatore?Iltotaledellafatturaaccumulaitotalidellerighee
quindiilsuovaloreinizialesarnullo.
CosavuoldireAggiornamentototalefattura?Aggiungereiltotaledellariga.
CosavuoldireUsodeltotaledellafattura?Ilproblemarichiedediconoscereinoutputtale
totale.
Aquestopuntosonostatiacquisitituttiglielementichepermettono,personalizzandoglischemi
generali,discriverel'algoritmorisolutivo:
NS
L.P.
TotaleFattura
INIZIO
totf <- 0
leggi qven
leggi pzun
while(qven > 0)
totr <- qven*pzun
totf <- totf+totr
leggi qven
leggi pzun
end-while
scrivi totf
FINE
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.15
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.16
ilcodicediUnix.
L'obiettivoallabasedellaprogettazionedellinguaggioCeraquellodicreareunlinguaggiopotente
e che potesse sfruttare le caratteristiche hardware: un linguaggio che avesse la potenza
dell'assembly,cheintendevasostituire,maallostessotempolafacilitd'usodiunlinguaggiodi
terzagenerazione. Illinguaggio C statodefinitoavoltelinguaggiodisecondagenerazionee
mezza per esprimere queste caratteristiche. Da allora ad oggi il C ha subito trasformazioni
soprattuttoinconseguenzadellaestensioneobjectorientedgenerandoC++.IlC++,comemessoin
evidenzadallostessonome,rappresentaunaevoluzionedellinguaggioC:ilsuoprogettista(Bjarne
Stroustrup)quandosiposeilproblemaditrovareunostrumentocheimplementasseleclassiela
programmazioneadoggetti,invecedicostruireunnuovolinguaggiodiprogrammazione,pens
benediestendereunlinguaggiogiesistente,ilCappunto,aggiungendonuovefunzionalit.In
questomodo,contenendoilC++illinguaggioCcomesottoinsieme,sipotevariutilizzaretuttoil
patrimoniodiconoscenzeacquisitodaiprogrammatoriinC(linguaggioestremamentediffusoin
ambito di ricerca) e si poteva fare in modo che tali programmatori avessero la possibilit di
acquisire le nuove tecniche di programmazione senza essere costretti ad imparare un nuovo
linguaggio e quindi senza essere costretti a disperdere il patrimonio di conoscenze gi in loro
possesso.
QuestiappuntifannoriferimentoallastandardizzazionedellinguaggioconosciutacomeC++98.
QualcheesempioutilizzacaratteristicheintrodottesuccessivamentenellarevisioneC++11.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.17
return 0;
}
Laprimarigadellistatoserveperincludere,nelprogramma,lefunzionalitperl'utilizzodegli
stream (flussi)diinputeoutput.IllinguaggioC++forniscedellelibreriegiprontecontenenti
funzionalit riguardanti elaborazioni varie. Il meccanismo che sta alla base delle librerie, e il
significatoesattodellariga,sarannochiaritisuccessivamente.Perilmomentobastasaperecheper
poterutilizzarelefunzionalit,disponibiliinunadeterminatalibreria,necessarioaggiungereuna
rigadelgenereconilnomedellalibreriastessa.Nelcasospecifico,senonsiaggiungessetaleriga,
ilprogrammanonpotrebbecomunicareconl'esternoperesempioconunatastieraeunvideo.
Anche il significato esatto della riga successiva (using ...) verr chiarito in seguito. Per il
momentobastadirechenecessariaquandosiutilizzanolibreriestandard( std)delC++.Lariga
conclusaconun;cheilcarattereterminatorediunaistruzionequalsiasi.
Ilprogrammaveroeproprio,perilmomentocompostodaunasolaparte,racchiusonelblocco,
delimitatodallacoppiadiparentesi{},eprecedutodaint main().
Il significato esatto dell'ultima istruzione del programma (return 0) verr chiarito meglio in
seguito.Perilmomentosipudirechesel'esecuzionedelprogrammaavvienesenzainterruzioni,e
chequindinoncisonoerrori,questasarl'ultimaistruzioneeseguitaesipotresseresicuricheil
programmastatoeseguitonelmodoprevisto.
Ilprogramma,nelloschemaproposto,suddiviso,permotividileggibilit,induepartidistinte:
dichiarazionedellevariabilidautilizzareeistruzioni.NelC++unavariabilepuesseredichiaratain
qualsiasipuntopurchprimadelsuoutilizzo.Quest'ultima unapossibilitcomodaquandosi
sviluppanoprogrammicomplessi,sihanecessitdiutilizzareunavariabileinunpuntoprecisoesi
vuoleevitarediandareindietronellistatoperdichiararelavariabileeavantinelpuntointeressato
perutilizzarla,tuttaviapenalizzalaleggibilitecomprensibilitdelprogramma.
Inquestiappuntilevariabilisarannosempredichiarate,tutte,nellaparteiniziale.
Lerighepreceduteda//sonocommenti:vengonotralasciatedalcompilatoreinsededitraduzione,
masonoindispensabilialprogrammatoreperchiarireilsensodellerighecheseguono.Questoun
aspetto importante perch nella codifica si utilizzano linguaggi simbolici e le istruzioni non
chiarisconoilsensodelleoperazionichesistannofacendo,amaggiorragionequandopassadel
tempofralastesuradelprogrammaelasualetturaoquandoilprogrammavieneesaminatoda
personadiversarispettoaquellachelohasviluppato. necessarioquindiaggiungererighedi
commentoinmododaisolareechiarirelesingolepartidelprogramma.
Icommentipossono,secondol'usodellinguaggioC,iniziaredopo /*edessereconclusida */.In
questocasoilcommentopuespandersiinpirighe:ilterminatore */chedicealcompilatore
dovefinisceilcommento.
Inquestiappunti/*e*/sonoutilizzatipersegnarelerighedeilistatichesarannocommentatenel
testo.
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.18
esaminerannoleesigenzedellacodifica.
CalcoloAreaRettangolo
INIZIO
leggi base
leggi altezza
area <- base*altezza
scrivi area
FINE
Diseguitovienepresentataunapropostadicodifica:
// Calcolo area rettangolo
#include <iostream>
using namespace std;
int main()
{
int base,altezza,area;
/*1*/
/*2*/
/*3*/
/*4*/
return 0;
}
Dopoladichiarazionedellevariabiliin1,ilprogrammasviluppatoin3particheprevedono:
acominciaredallariga2,lapresentazionedelprogrammael'acquisizionedeidatidiinput.
Rispettoall'algoritmoinpseudocodificacheevidenzialeistruzioniperlarisoluzionedel
problemaproposto,quipresenteunaistruzionecheconsentedistamparesuvideouna
brevefrasechespiegalafunzionedelprogrammastesso.Gliinput,inoltre,sonopreceduti
daun prompt,una stringadiinvito (brevefrasechechiarisceall'operatorecheesegueil
programma, il senso delle richieste del programma). Si tenga presente che durante
l'esecuzionedelprogrammavengonovisualizzatesololefrasichesonooggettodiistruzioni
dioutput:senoncifosseunabrevepresentazione,l'operatorecheesegueilprogrammanon
conoscerebbel'elaborazioneeffettuatae,inoltre,nonsaprebbecomeecosarispondereagli
inputrichiesti.Lerighedicommentosonounostrumentoutileperilprogrammatoreper
riconoscereimmediatamentelepartichecompongonoilprogrammaericordarel'algoritmo
utilizzato,masonoinutiliperl'operatorecheesegueilprogrammaechevedesologlioutput
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.19
previstichequindisidevonoprenderecaricodirenderefacilmentefruibilileelaborazioni.
Unaunicaistruzioneprovvedeariceverel'inputdelleduevariabili.
dallariga3comincialapartedelleelaborazioniche,nell'esempioproposto,costituitada
unasolaistruzione.L'operazionediassegnamentoeffettuatadall'operatore=.L'espressione
algebricaadestrarispettaleregolegiespresseinprecedenza
dallariga4vengonopresentatiglioutputdelprogramma.Anchequiivaloridioutputsono
precedutidabrevifrasiesplicative.
Laformagraficadataalprogramma,teoricamenteedalpuntodivistadelcompilatore,deltutto
opzionale; una volta rispettata la sequenzialit e la sintassi, la scrittura del codice libera. In
particolarepiistruzionipossonoesserescrittesullastessalinea.indubbioperche,inquesto
ultimocaso,ilprogrammarisulternotevolmentemenoleggibiledelprecedente.Lacodificadiun
programma, qualunque sia il linguaggio di programmazione che si utilizza, sempre criptica.
D'altra parte nello sviluppo del software capita spesso di dover riprendere il codice per poter
correggereerrori,aggiungereomodificarefunzionalit,ecc...Selascritturadelcodicefosselibera
cisarebberoproblemidicomprensionecheallungherebberoitempioccorrentiperlemodifiche.Per
poter diminuire i costi di manutenzione del software, sono state progettate delle regole per la
scritturadiun buon programma.Inunparagrafosuccessivosiesporrannoalcuneregoleminime,
ormaiuniversalmenteaccettate,daapplicareallascritturadiunprogramma.
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.20
area = base*altezza;
L'assegnamentopuessereeffettuatocontestualmentealladichiarazione:
...
int base = 3;
int altezza = 7;
...
NellinguaggioC++possibileassegnarelostessovaloreapivariabilicontemporaneamente.Per
esempioseledimensioniavesseroriguardatounquadrato,sisarebbepotutoscrivere:
base = altezza = 5;
In questo caso, in sede di esecuzione, l'ordine delle operazioni procederebbe da destra verso
sinistra: prima verrebbe assegnato il valore 5 alla variabile altezza e quindi, il risultato
dellassegnazione(cio5),verrebbeassegnatoallavariabilebase.
Ledichiarazionidellevariabilidellostessotipopossonoesserescritteinsequenzaseparatedauna
virgolaoanchedichiarate,conilpropriotipo,ognunaseparatamentedallealtre:
int base;
int altezza;
int area;
Selevariabilinonsonoautodocumentateopportunoaggiungerecommentiperspecificarneil
significato:
int base, altezza,
area;
Ladichiarazioneterminanellasecondarigamalevariabilisonodistribuiteinduerigheinmododa
aggiungereicommentiesplicativi.
Perquantoriguardalalunghezzadelnomediunavariabileoccorretenerepresentechesoltantoi
primi32caratterisonosignificativi,anchesenelleversionidelCmenorecentiquestolimitescende
a8caratteri.Nonbisognainiziareilnomedellavariabileconilcaratteredisottolineaturaedbene
tenerepresentechelelettereaccentate,permessedallalinguaitaliana,nonsonoconsideratelettere
masegnigrafici elelettere maiuscolesonoconsideratediversedallerispettiveminuscole.Nel
nome di una variabile non possono esserci inoltre caratteri particolari (spazi, segni di
punteggiatura). In definitiva si pu utilizzare una qualsiasi combinazione che preveda caratteri
dell'alfabetoingleseminuscoliemaiuscoli,cifrenumericheedeventualmentetrattinobasso_.
Oltrearispettareleregoleprecedentementeenunciate,unidentificatorenonpuessereunaparola
chiavedellinguaggio, npuessereuguale ad un nomedifunzionelibreria oscrittadal
programmatore.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.21
MentreintunaparolachiavedelC++efaparteintegrantedellinguaggio, base,altezzaearea
sonoidentificatoridivariabilisceltiadiscrezionedichiscriveilprogramma.Glistessirisultatisi
sarebberoottenutiutilizzando,alloroposto,nomigenericiquali x, y e z solocheilprogramma
sarebberisultatomenocomprensibile.
/*1*/
/*2*/
/*3*/
return 0;
}
Sesicompila,esilancial'esecuzionedelprogramma,siottiene:
Prima riga seguito della riga
Nuova riga molto lunga la riga continua ancora su video
questo viene stampato su una nuova riga
Nella1siincanala(permezzodell'operatorediinserimento<<)nellostreamcoutlastringaPrima
riga.Tuttocicheracchiusofrae(ilcaratteredoppioapice),comesinotanell'esecuzione,
verrvisualizzatosuvideocoscome.Il;chiudel'istruzione.
Nella2,nonostantesitrattidiunanuovaistruzione,lastringa,comesipunotarenell'esecuzione,
visualizzatadiseguitoallaprimapoichlostreamutilizzatoinmodosequenziale.Perandarea
riganuovasiaccodato(operatore <<)ilmodificatore endl (endline)che,appunto,terminala
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.22
lineaefapassareallaprossimariganelvideo.
L'istruzione3suddivisainpirighedilistato.L'istruzionetermina,alsolito,conil ;econsentedi
distribuireiltestodavisualizzaresupirighefisiche.Inognunasiscrittaunastringaracchiusa
daisoliticaratteri:questo viene ...verrvisualizzatalarigasuccessivaaquellachevisualizza
Nuova riga...Perpassareadunanuovarigasuvideo,siutilizzatoinquestocasoilcaratteredi
controllo\ndentrolastringadavisualizzare.Lospaziosuccessivoalcaratteredicontrollonon
necessariomastatointrodottosoloperevidenziarlo.Indefinitivaperpoterpassareallalinea
successiva si pu accodare, allo stream di output, endl o inserire nella stringa da stampare il
caratteredicontrollo\n.
All'interno della stringa da stampare si possono inserire anche altri codici di controllo, tutti
precedutidalcaratterediescape(\),dicuiquisifornisceunelencodiquellichepossonoesserepi
utili:
\nportailcursorealliniziodellarigasuccessiva
\tportailcursorealprossimofermoditabulazione(ognifermoditabulazionefissatoad8
caratteri)
\stampaunapice
\stampalevirgolette
L'esecuzionedellaistruzionedioutputpresentenelprogrammadiesempio:
...
cout << \nBase: << base << Altezza: << altezza << endl;
cout << Area: << area << endl;
produrrebbe,nelcasofosserostatiintrodottiivalori3e7rispettivamenteperbaseealtezza:
Base: 3 Altezza: 7
Area: 21
ilprimooutput,comeprevistodalcodicedicontrollopresenteverrstampatounarigasottol'ultimo
outputprecedente.
L'esecuzionediquestaistruzionefascheilsistemaattendadapartedell'utentel'immissionedidue
numeriseparatidaunospazioechelivadaaconservarenellevariabilispecificate.
Inquestaistruzionevieneutilizzatoilcanalediinputcineloperatorediestrazione>>.Sipotrebbe
interpretare listruzione come: estrai dal canale di input due dati e conservali nelle variabili
specificate.Comegievidenziatoinprecedenzaladefinizionedelcanalediinputsitrova,come
quelladelcanaledioutput,nellalibreriaiostream.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.23
Essendopresenteunastringadiinvitoprimadellaistruzionediinput,quellochel'utentevedr
visualizzatoinfasediesecuzionedelprogrammasar
Valore base e altezza separati da uno spazio: _
Inquestoistantesiattendechenelcanalediinputsiadisponibileunvaloredaestrarre.Sel'utente
digitaivalori10e13separatidaunospazioeseguitidaInvio
Valore base e altezza separati da uno spazio: 10 13
idativerrannoassegnati,rispettivamente,allevariabilibaseealtezza.
L'esecuzionedelprogramma,nell'ipotesichel'utenteinseriscaivalori10e13,sar.
Calcolo AREA RETTANGOLO
Valore base e altezza separati da uno spazio: 10 13
Base: 10 Altezza: 13
Area: 130
Gliinput,nell'esempio,sonoraggruppatiperrendereevidenteallaletturachesitrattadellabasee
dell'altezzadellostessorettangolo:iduedatiintrodottiriguardanoledimensionidi un rettangolo
anchese,materialmente,sitrattadiduevalori.
Sipotevanoacquisireiduevaloriinmanieraindipendente:
...
cout << Valore base :;
cin >> base;
cout << Valore altezza :;
cin >> altezza;
...
Selacodificafossestatafattainquestoaltromodo,ilsistemasisarebbeaspettato,diconseguenza
adogniistruzionediestrazionedallostream cin,unsolodatoseguitodaInvio.Ildatosarebbestato
conservato,diconseguenza,nellavariabilespecificata.
dovelavalutazionediespressionecontrollal'esecuzionediistruzione:seespressionevera
vieneeseguitaistruzione.
Atitolo diesempiovienepropostounprogramma cherichiede unnumeroall'utente e,setale
numerominoredi100,visualizzaunmessaggio.Datalasemplicitnevienepropostadirettamente
lacodifica.
#include <iostream>
using namespace std;
int main()
{
const int limite=100;
http://ennebi.solira.org
/*1*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.24
int i;
// valore da elaborare
cout << Introdurre un valore intero ;
cin >> i;
// verifica valore
if (i<limite)
cout << "numero introdotto minore di " << limite << endl;
/*2*/
/*3*/
return 0;
}
Nelprogrammapropostopresentelacostante100chepotrebbeessereutilizzatadirettamentenelle
istruzioni che la coinvolgono, ma pi conveniente assegnare ad essa un nome simbolico da
utilizzarealpostodelvalore.L'istruzionecontenutanella 1dichiaraunacostanteditipo intcon
nome limite evalore 100.Nelleistruzionipresentinelprogramma,quandovienecoinvoltala
costante,vieneutilizzatoilnome,coscomeevidenziatonelleistruzionicontenutenellerighe2e3.
Ladifferenzafraladichiarazionedivariabileeladichiarazionediunacostante,dalpuntodivista
dellasintassidellinguaggio,prevedelapresenza,nelsecondocaso,dellaparolachiave const e
dell'assegnazionediunvalore.Dalpuntodivistadell'esecuzioneunavariabile,dichiaratacome
costante, non pu essere modificata: se nel programma fosse presente qualche istruzione che
comportasselamodifica,peresempionelcasoproposto,di limite,ilcompilatoregenererebbeun
messaggiodierrore.
Ilmotivodell'usodelledichiarazionidicostantirisiedenelfattoche,inquestomodo,all'internodel
programma, compare solo il nome simbolico. Il valore compare una sola volta all'inizio del
programmastessoe,quindi,sec'necessitdimodificaretalevalore,peresempio,valutandose
l'inputdell'utentenonsuperi150,qualsiasisialalunghezzadelprogrammaequantichesianogli
utilizzidellacostante,bastamodificarel'unicalineadelladichiarazioneericompilareilprogramma
affinchquestofunzioniconlenuoveimpostazioni.
L'espressionei<limitepresentein2lacondizionelogicachecontrollal'istruzionedistampae
pertantolasuavalutazionepotrrestituiresoltantounodeiduevaloribooleaniveroofalsochein
C++corrispondonorispettivamenteaivaloriinteri unoezero.appuntopertaleragionecheun
assegnamentodeltipo a=i<limite,deltuttolecito.Vieneinfattivalutatal'espressionelogica
i<limite,cherestituisce1(vero)seiminoredi100o0(falso)seimaggioreougualea100:il
risultatodunqueunnumerointerochevieneassegnatoallavariabilea.
Unaulterioreconseguenzadeivaloribooleanichechiedersiseilvaloredi adiversodazerolo
stessochechiedersiseilvaloredi a vero,ilche,inC++,corrispondealcontrolloeseguitoper
default(effettuatoinmancanzadidifferentiindicazioni),percuisisarebbeanchepotutoscrivere
...
cin >> i;
a = i<limite;
if (a)
cout << "numero introdotto minore di " << limite << endl;
Lasintassicompletadell'istruzioneiflaseguente:
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.25
if(espressione)
istruzione1
[else
istruzione2]
Esempio
!a
<
a < b
<=
a <= b
>
a > b
>=
a >= b
==
a == b
!=
a != b
&&
a && b
||
a || b
Risultato
(NOTlogico)1sea0,altrimenti0
1sea<b,altrimenti0
1sea<=b,altrimenti0
1sea>b,altrimenti0
1sea>=b,altrimenti0
1seaugualeab,altrimenti0
1seanonugualeab,altrimenti0
(ANDlogico)1seaebsonoveri,altrimenti0
(ORlogico)1seavero,(bnonvalutato),1sebvero,altrimenti0
opportuno notare che, nel linguaggio C++, il confronto delleguaglianza fra i valori di due
variabilivieneeffettuatoutilizzandoildoppiosegno==.
EsempioA
if (a==b)
cout << "Sono uguali";
EsempioB
If (a=b)
cout << "Valore non zero";
Nell'esempioAsiconfrontailcontenutodellavariabileaedilcontenutodellavariabileb:sesono
ugualivienestampatalafrasespecificata.
Nell'esempio B si assegna ad a ilvaloreattualmentecontenutoin b esiverificasediversoda
zero:intalcasovienestampatalafrasespecificata.
Unaulterioreosservazionevafattaapropositodeglioperatorilogici && (ANDlogico)e || (OR
logico)chevengonousatipermettereassiemepicondizioni.Es.
if (a>5 && a<10)
cout << a compreso fra 5 e 10;
if (a<2 || a>10)
cout << a pu essere <2 oppure >10;
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.26
EsempioA
if (a>100)
cout << "Prima frase \n";
cout << "Seconda frase \n";
EsempioB
if (a>100) {
cout << "Prima frase \n";
cout << "Seconda frase \n";
};
2.10 Loperatore ?
Loperatorediassegnazionecondizionata?halaseguentesintassi:
espr1 ? espr2 : espr3
Seespr1verarestituisceespr2altrimentirestituisceespr3.
Siutilizzataleoperatoreperassegnare,condizionatamente,unvaloreadunavariabile.Inquesto
modopurendereunframmentodiprogrammamenodispersivoepicomprensibile:
EsempioA
if (a>100)
sconto=10;
else
sconto=5;
EsempioB
sconto=(a>100 ? 10 : 5);
equivaleascrivere:
n = n+1;
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.27
L'operatore--l'operatorediautodecremento.Glioperatoridiautoincrementoeautodecremento
sonoutilizzatineicontatori.
AnchepergliaccumulatorisonoprevistinellinguaggioC++deglioperatoriparticolari(operatori
doppi).
x += 37;
k1 += k2;
a += (b/2);
l'utilizzodeldoppiooperatore+=rendeleespressioniequivalentirispettivamentea:
x = x+37;
k1 = k1+k2;
a = a+(b/2);
Ledueespressionisonoequivalenti,dalpuntodivistadelrisultatofinale,solochel'utilizzodel
doppiooperatoreaumentalaleggibilitdell'assegnazione:diventamoltopichiarochesitrattadi
un aggiornamento e non dell'assegnazione di un nuovo valore, come ci si potrebbe attendere
dall'utilizzodelsimbolo=.
Neldoppiooperatoresipossonousaretuttiglioperatoriaritmetici.
Nelseguitodiquestiappuntisiconverr,comecomune,diutilizzare:
glioperatoridiautoincrementoediautodecrementotuttelevoltecheunavariabiledovr
essereaggiornataconlunit
ildoppiooperatore(es.+=,-=ecc)tuttelevoltechesiparlerdiaggiornamentogenerico
diunavariabile(peres.negliaccumulatori)
loperatorediassegnamentogenerico(cio=)intuttiglialtricasi.
++z;
ciometterel'operatore++primaodopodelnomedellavariabile.
Inquestocaso,ledueformesonoequivalenti.Ladifferenzaimportasoloquandosiscriveuna
espressionechecontienez++o++z.
Scrivendoz++,ilvaloreattualedizvieneprimausatopoiincrementato:
int x,z;
z = 4;
x = z++;
Scrivendo++z,ilvaloreattualedizvieneprimaincrementatoepoiusato:
int x,z;
z = 4;
x = ++z;
Indefinitivabastatenerepresentechel'ordinedelleoperazioni,nell'espressionedopoilsimbolodi
assegnazione,avvienedasinistraversodestra.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.28
Vieneverificatocheespsiavera,nelqualcasovieneeseguitaistruzione.Ilciclosiripetementre
esprisultaesserevera.
Naturalmente,perquantoosservatoprima, istruzione puessereunbloccoe,ancheinquesto
caso,puessereutileracchiuderelistruzioneinunbloccoancheseunasola.
Comeesempiodelleistruzionitrattatefinoaquestopunto,vienepropostounprogrammache,data
unasequenzadinumeriinteripositivi,forniscelaquantitdinumeriparidellasequenzaelaloro
somma.Unqualsiasinumeronegativo,oilvalorenullo,fermal'elaborazione.
#include <iostream>
using namespace std;
int main()
{
int vn,
conta,somma;
// inizializzazione accumulatori
cout << "Conteggio e somma dei numeri pari\n\n";
conta = somma = 0;
/*1*/
/*2*/
while (vn>0){
// verifica se numero inserito pari
if(!(vn%2)){
conta++;
somma += vn;
}
/*3*/
/*4*/
/*4*/
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.29
// risultati elaborazione
cout << "Nella sequenza c\'erano "
<< conta << " numeri pari" << endl;
cout << "La loro somma e\' " << somma << endl;
return 0;
}
Nella1siinizializzanoalvalorenulloilcontatoreel'accumulatoredeipari.
Nella2siacquisisceilprimovalorenumericodaelaborare.
Ilcontrollo della 3 permette distabilire seilnumerointrodotto pari.Viene usatol'operatore
modulo%perilcalcolodelrestodelladivisioneinterafravne2evienecontrollatosetaleresto
nulloinmodoche,nelle4,sipossanoaggiornareilcontatoreel'accumulatore.
Ilcicloiniziaconl'esecuzionediesp1(inizializzazionedelciclo)laqualenonverrpieseguita.
Quindi viene esaminata esp2 (condizione di controllo del ciclo). Se esp2 risulta vera, viene
eseguita istruzione, altrimenti il ciclo non viene percorso neppure una volta. Conclusa
l'esecuzionediistruzionevieneeseguitaesp3(aggiornamento)edinuovovalutataesp2chese
risultaessereveradluogoadunanuovaesecuzionedi istruzione.Ilprocessosiripetefinch
esp2risultaesserefalsa.
Conoscendolaquantitdivalorinumericidaelaborare,ilprogrammaprecedentedielaborazione
deinumeriparidiunasequenza,potrebbeesserecodificato:
#include <iostream>
using namespace std;
int main()
{
int vn,
conta,somma;
int qn,
i;
// inizializzazione accumulatori
cout << "Conteggio e somma dei numeri pari\n\n";
cout << "Quanti numeri devono essere elaborati? ";
cin >> qn;
/*2*/
conta = somma = 0;
// esame dei numeri
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
for(i=0;i<qn;i++){
C++:programmazioneedoggettipag.30
/*3*/
Vengonoaggiuntenella1duenuovevariabiliperlaquantitdeinumeridaelaborareeilcontatore
delciclo.
Vieneeffettuatonella2l'inputdellaquantitdeinumeridaelaborareche,conilciclocheiniziada
3,vengonoelaborati.
Ilprogrammaperprimacosaassegnailvalore 0allavariabilei(laprimaespressionedelfor),si
controllaseilvalorediiinferioreaqn(lasecondaespressione)epoichlespressionerisultavera
verrannoeseguiteleistruzioniinseritenelciclo.Terminateleistruzionichecompongonoilciclosi
eseguelaggiornamentodiicoscomerisultadallaterzaespressionecontenutanelfor,siripeteil
controllocontenutonellasecondaespressioneesicontinuacomeprimafinchilvaloredi i non
rendefalsalacondizione.
Ilciclovieneeseguito qnvolteeilcontatoreassumevalori 0, 1, 2, ..., (qn-1).Sisarebbe
potutoinizializzareilcontatoread1eterminareilcicloconilcontrolloi<=qn,maquisipreferito
adottareunaconvenzione,comunenelleapplicazioniinformatiche,diiniziareiconteggidalvalore
0.
Questomododiagiredelcicloforquellocomuneatuttiiciclidiquestotipo(cicliacontatore)
messiadisposizionedaicompilatorididiversilinguaggidiprogrammazione.IllinguaggioC++,
considerandoletrepartidelcostruttocomeespressionigeneriche,espandeabbondantementele
potenzialitdel for generalizzandolo inmaniera taledacomprendere,peresempio,comecaso
particolareilciclo while.Laprimaversionedelprogramma(quellacheutilizzailciclo while),
nellapartedicodicecomprendenteilciclodielaborazione,potrebbeesserecodificata:
...
for(conta=somma=0;vn>0;){
// verifica se, numero inserito, pari
if(!(vn%2)){
conta++;
somma += vn;
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.31
}
// prossimo numero da elaborare
cout << "Inserire numero positivo ";
cin >> vn;
}
...
Ilcicloeseguelazzeramentodicontaesomma(cheverreseguitounasolavolta)esubitodopoil
controlloseilvaloredi vn positivoe,inquestocaso,verrannoeseguiteleistruzionidelciclo.
Terminateleistruzioni,mancandolaterzaespressionedel for,vienesolamenteripetutoilcontrollo
suvn.
Le inizializzazioni di conta e somma avrebbero potuto essere svolte fuori dal for: in tal caso
sarebbemancataanchelaprimaespressione.
Inquestocasovieneeseguita istruzioneesuccessivamentecontrollatoseesprrisultavera,nel
qualcasoilciclovieneripetuto.
Comesemprel'iterazionepucomprendereunaistruzionecomposta.
beneprecisare,ancoraunavolta,cheinunblocco for, while o do...while,coscomenel
bloccoif,puesserepresenteunnumeroqualsiasidiistruzionidiognitipocompresialtriblocchi
for,whileodo...while.Iciclipossonocioessereannidati.
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.32
seguono. Ogni nuovo blocco che svolge una nuova funzionalit o che elabora un dato
intermediovaprecedutodauncommentoesplicativo.Ognirigadicommentoprecedutae
seguitadaunarigavuotaperrenderlapiindividuabile.Allostessomodoognistrutturadi
controllo(if,whileofor).
Una variabile ha un nome mnemonico che ricorda il suo uso in modo da agevolare la
comprensibilitdelcodice.
L'usodiunacorrettaindentazione(incolonnamentodellerighedicodice)difondamentale
importanzanonsoloperlacomprensionedelcodicemaancheperevitareerroricomuni.
Negliesempidiquestiappuntiutilizzataunaindentazionedi2caratteri.Persintetizzarele
regoleperl'incolonnamentodellerighedicodice:
ognirigadicodiceallineata,ingenerale,conlarigaprecedente
senellarigaprecedentesitrovaunaparantesigraffaaperta,larigavaindentataverso
destraditantispaziquantisenesonosceltiperlaindentazione.Negliesempi2spazi
ilmarginediiniziodellarigasispostaversosinistraquandosidevechiudereunblocco:
sideveinserireunaparantesigraffachiusaosiscrivel'istruzionesuccessivadopol'unica
istruzionecompresainunastrutturacondizionaleociclo.
L'usodiunacorrettaindentazionepermettedievitareerrorifrequentididimenticanzadella
chiusura (parantesi graffa chiusa) di una struttura specie quando ci sono pi strutture
nidificate(unadentrol'altra).
Leconvenzioniperl'usodelleparentesigraffeel'indentazionedellerighedicodicesipossonocos
sintetizzare:
int main()
{
// codice del programma
}
leparentesicheracchiudonoilmainoccupanounarigaaparteciascuna.
while(...){
// codice contenuto nel ciclo
}
// codice fuori dal ciclo
il blocco che racchiude il codice contenuto in un ciclo (while o for) comincia dalla riga
dell'istruzioneciclicaesichiudeconlaparentesicheoccupadasolaunariga.
if(...){
// codice per condizione vera
}
else {
// codice per condizione falsa
}
// altro codice
senellastrutturacondizionalenonpresenteilbloccoperlacondizionefalsa,sicodificacomela
strutturaciclica.Sepresenteilbloccopercondizionefalsaquestovatrattatocomesefosseuna
strutturaaparte.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.33
Insintesilacodificadiunastruttura,qualoraquestacomprendaunbloccodicodice,prevedela
parentesidiaperturanellastessarigadelcodicediiniziodellastrutturaelaparentesidichiusurada
solainunariga.Lerighechecontengonoleistruzionichedipendonodallastrutturavannoindentate
perchintalmodo,anchevisivamente,nediventachiaraladipendenza.
return 0;
}
Perladichiarazionedellevariabilisonostateutilizzate2righeinmododadistinguere,visivamente,
levariabiliininputeoutput.
Siaggiungeoraunadescrizionedelprogramma.Nonsitrattadispiegarecosafailprogrammain
manieraestesa(laletturadaunoschermodiuncomputerdifficoltosaefaperderetempo)madi
inserirefrasinonridondantichesianopibrevipossibili,eliminandoparolechenonneaumentano
lacomprensibilit(peresempioeliminaregliarticoli),maanchechesianoquantopipossibile
chiarificatrici:
#include <iostream>
using namespace std;
int main()
{
int qven, pzun;
int totf;
cout << Calcolo totale fattura dai dati delle righe << endl;
return 0;
}
lacodificadell'algoritmoprevederighedicommentocheevidenzianolevariefasidell'elaborazione
espieganoin cosa consistel'elaborazione,laddoveilcodicespiega come devonoesseretrattatii
datiperottenerequellaelaborazione.
#include <iostream>
using namespace std;
int main()
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.34
{
int qven, pzun;
int totf;
cout << Calcolo totale fattura dai dati delle righe << endl;
// inizializzazione totale fattura
// prima riga fattura
// elaborazione righe
while(qven > 0){
// calcolo totale riga
// aggiornamento totale fattura
// altra riga
};
// output totale
return 0;
}
Laprimapartedelprogrammaprevedeunasequenzacomprendentel'inizializzazionedeltotale
dellafattura(totalizzatore)el'inputdelprimoelementodell'elaborazioneciclica(laprimarigadella
fattura).Subitodoponecessarioinserireuncicloperl'elaborazioneciclicadellerighe.Aquesto
punto, per come richiesto nella condizione di controllo del ciclo, necessario stabilire la
terminazionedell'elaborazione.Poichneltestodelproblemanonspecificatalafinedellerigheda
prendereinconsiderazionesipuassumerel'acquisizionedivalorichefannoperderedivalidit,
peresempio,allaquantitdioggettivenduti:nonhasensoinfatticonsiderarepertalequantitvalori
negativioilvalorenullo.Undiscorsosimilesisarebbepotutofareconsiderandoinveceilprezzo
unitario.Lasequenzadelleoperazionidaeseguireterminaconl'outputdeltotaledellafattura.
A questo punto possono essere dettagliate le varie fasi: viene stabilito il come si effettua
l'elaborazione prendendo in considerazione la codifica, ogni volta, del frammento di codice
sottostantelasingolarigadicommento.Siisolanomentalmentelesingoleoperazionidaeffettuare:
// prima riga fattura
cout <<
<<
<<
cin >>
Ilcodicecompletoriportatodiseguitodovesi aggiuntaancheunavariabiletemporaneadi
lavoro necessaria per conservare il totale della singola riga della fattura necessario per
l'aggiornamentodeltotaledellafattura:
#include <iostream>
using namespace std;
int main()
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.35
{
int qven, pzun;
int totf;
int totr;
cout << Calcolo totale fattura dai dati delle righe << endl;
// inizializzazione totale fattura
totf = 0;
// prima riga fattura
cout <<
<<
<<
cin >>
// elaborazione righe
while(qven > 0){
// calcolo totale riga
totr = qven*pzun;
// aggiornamento totale fattura
totf += totr;
// altra riga
cout <<
<<
<<
cin >>
};
// output totale
cout << Totale fattura << totf << endl;
return 0;
}
Forsel'usodeicommentipotrebbesembrareeccessivomacidipendesolodallabanalit,dalpunto
divistadellaquantitdicodice,dell'algoritmocodificato.
Leggendosololerighedicommentosicapisceimmediatamentecosafailprogrammaedove.Ci
risultaindispensabileperindividuareipuntidiinterventoperlamanutenzione.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.36
levariabilideitipiint,float,doublepossonoconservarenumeri.Questitipipermettono
anchel'usodimodificatorichevarianol'occupazionedimemoriadellavariabilee,quindi,le
caratteristichedelnumeroconservato.Imodificatoriammessisonoshort,long,unsigned.
#include <iostream>
#include <limits>
using namespace std;
int main()
{
cout << "bit intero " << numeric_limits<int>::digits << endl;
cout << "cifre intero " << numeric_limits<int>::digits10 << endl;
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.37
<<
<<
<<
<<
cout
cout
cout
cout
<<
<<
<<
<<
cout
cout
cout
cout
<<
<<
<<
<<
cout
cout
cout
cout
<<
<<
<<
<<
return 0;
}
il programma proposto serve per far visualizzare alcune caratteristiche importanti delle
variabilidichiarateinquelmodo.Inparticolarevienechiestalavisualizzazione,perogni
tipo, di quantit bit occupati (digits), quantit cifre di precisione (digits10), valore
minimo(min())evaloremassimo(max())conservabili.Nonimportantespiegareilsenso
delle singole righe, importante solo sapere cosa produce questo codice perch
fondamentale,nellascritturadiunprogrammaqualsiasi,conoscereilgradodiaffidabilitdi
unvalorenumericoconservatoecomedichiararelavariabileinmododaconsentirnela
correttaconservazione.
Nellamacchinautilizzataperleprovedeiprogrammiriportatiinquestiappunti,econil
compilatoreutilizzato,siottengonoquestirisultati:
bit intero 31
cifre intero 9
minimo intero -2147483648
massimo intero 2147483647
bit short 15
cifre short 4
minimo short -32768
massimo short 32767
bit float 24
cifre float 6
minimo float 1.17549e-38
massimo float 3.40282e+38
bit double 53
cifre double 15
minimo double 2.22507e-308
massimo double 1.79769e+308
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.38
Ognivariabileditipointoccupa31bitinmemoria(inrealtsono32maunbitriservato
al segno),pu contenere solo numeri interi e i valori ammissibili variano tra imargini
riportati(rangedirappresentativit).Sesiapplicailmodificatoreshort,l'occupazionedi
memoriacambiaediconseguenzaancheilrangedirappresentativit.
...
int a;
short b;
...
a = 15;
b = 20;
...
Sesivuoleconservareunnumeroconparteinteraepartedecimalenecessariodichiararela
variabileditipovirgolamobile(floatingpoint)floatodouble.Inquesticasiilproblema,
da considerare, non il margine di rappresentativit, in quanto ambedue consentono la
conservazione dinumeri convaloriestremamente elevati (sivedanoil valore minimo e
massimoscrittiinnotazioneesponenziale),malaprecisione.Iltipofloatutilizza24bite
garantisceseicifrediprecisione(singolaprecisione).Inpraticailnumeropuesseremolto
grande come valore (1038) ma non pu contenere pi di 6 cifre diverse da 0: va bene
12340000000000000 ma non 123456789. Il secondo valore non conservato in modo
corretto.
Il tipo double, al costo di maggiore occupazione di memoria, garantisce un numero
maggioredicifreprecise(doppiaprecisione).Sesihanecessitdiunaprecisioneancora
maggioresipudichiararelavariabileditipo long double esiarrivaa18(quadrupla
precisione).
...
float c;
double d;
long double e;
...
c = 123.23;
d = 456970.345;
e = 789.0;
...
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.39
test = false;
if (i<100)
test = true;
...
3.2 Il cast
Quandosidichiaranovariabiliditipodiversonecessariofareattenzioneachenonsimischino
all'internodellastessaespressionealgebrica,oassegnazione,valorie/ovariabiliditipodiverso.Il
compilatoresegnalaerroregenericotypemismatch(noncorrispondenzaditipo)quandositentadi
forzareunvalorediuntipoinunavariabiledichiarataditipoincompatibileconquelvalore.In
alcunicasiilcompilatoreeffettuaunaforzatura,peresempio,sesiprovaadinserireunvalore
floatinunavariabileditipoint:chiaramentelapartedecimaleverrtroncata.
Avolte,invece,puinteressareeffettuaredeicambiamenti alvoloperconservareirisultati di
determinateoperazioniinvariabiliditipodiversoprincipalmentequandosivadauntipo meno
capiente ad un tipo pi capiente. In tali casi il linguaggio C++ mette a disposizione del
programmatoreuncostruttochiamatocast.
#include <iostream>
using namespace std;
int main()
{
int uno, due;
float tre;
uno = 1;
due = 2;
tre = uno/due;
cout << tre << endl;
return 0;
}
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.40
due = 2;
tre = static_cast<float> (uno)/due;
cout << tre << endl;
return 0;
}
Inquestocasoilrisultatodell'esecuzionedelprogrammacoincideconl'attesa.Infattiilquoziente
vienecalcolatocomefloat(ilcontenutodellavariabileunovieneforzatofloat)equindi,dopo,
assegnatoallavariabiletre.
Indefinitiva utilizzando l'operatore unario static_cast<float> applicato alla variabile uno si
forza,nelcalcolodell'espressione,ilsuovaloreadesserediuntipospecifico(nell'esempiouna
divisioneinteravieneforzataafornireunrisultatoditipovirgolamobileessendopresenteunvalore
ditaletipo).
Viene adesso proposta una interessante applicazione del casting per la trasformazione di un
carattereminuscolonellasuarappresentazionemaiuscola.Ilprogrammasfrutta,perottenereilsuo
risultato,ilfattocheunavariabileditipo char,indefinitiva,conservauncodicenumerico;qui
vieneinoltreusatoilcastingpermostraretalecodice.
#include <iostream>
using namespace std;
int main()
{
char min,mai;
const int scarto=32;
/*1*/
/*2*/
/*3*/
/*4*/
/*5*/
/*6*/
return 0;
}
Nellarigaconetichetta1definitalacostantescarto.Ilvalore32dipendedalfattoche,nelcodice
ASCII utilizzato nella rappresentazione dei caratteri nella memoria di un computer, tale la
distanzafralemaiuscoleeleminuscole(es.Ahacodice65,ahacodice97).
Nellarigaconetichetta2sieffettualinputdelcaratteredaelaborare.
Nella riga con etichetta 3 si controlla se il carattere immesso rientra nei limiti delle lettere
minuscole.Lelettereminuscole,inASCII,hannocodicecompresofra97(laletteraminuscolaa)e
122(laletteraminuscolaz).Ilconfrontopotevaancheesserefattosullarappresentazionenumerica:
if (min>=97 && min<=122)
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.41
Nellarigaconetichetta4sieffettuainpraticalatrasformazioneinmaiuscolo.Alcodicenumerico
associatoalcaratterevienesottrattoilvalore 32.Inquestocasoutilizzatoilcodicenumericodel
carattere.Sinoticheinquestocontestohasensoassegnareadun charilrisultatodiunasottrazione
(operazionenumerica).
Nellarigaconetichetta5sieffettualoutputdimaiintesocomecarattere(cosinfattidefinitala
variabile),laddovenellariga6sieffettualoutputdelsuocodicenumerico(usatouncastingsulla
variabile).
Nellevariabilisempliciperaccederealvalorecontenutoinessenecessariospecificareilnomee,
inoltre,unavariabilechedovrconservareunvalorediversoavrunnomediverso.Nelvettore
esisteunnomecheperstavoltaidentifical'interastruttura.
Glielementidelvettorevengonoallocatiinposizionidimemoriaadiacenti.
C++,nelcasodistrutture(container)complesse,metteadisposizioneunmeccanismo(classi)che
consente, una volta dichiarato un oggetto di quel tipo, all'oggetto stesso, di possedere dei
comportamentitipicidituttiglioggettidellastessafamigliafacilitandonel'elaborazione.
Ladefinizionedivettorecontenutanellalibreria vectorchequindivainclusanelcodicetuttele
voltechesihanecessitdidefinireunavariabileditipovettore.Lalibreriafapartediquelleche
vengonodefiniteSTL(StandardTemplateLibrary).
Ledifferenzesostanzialifraladichiarazionediunavariabileditipoelementare,peresempiouna
variabileditipoint,eunoggetto,peresempio,dellaclassevectorsipossonosintetizzare:
Unadichiarazionedeltipo:
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.42
int a;
comporta,inragionedeltipo,ladefinizionedialcuneoperazioni(lequattrodell'aritmetica
elementare e l'operazione modulo) che possono essere applicate al dato contenuto nella
variabileche,difatti,uncontenitoreperdatisucuisivoglionoeseguirequelleoperazioni.
Unadichiarazionedeltipo:
vector<int> v;
dichiaraunoggettodellaclassevectorchecontienenumeriinteri(iltipospecificatofrale
parentesiangolari <>)comeelementi,ma v essendounoggetto(una istanza)dellaclasse
vectorhatuttiicomportamentidefinitinellaclasse.Nonpossibilegestiredirettamentegli
elementidelvettoreperchconunoggettosiinteragisceutilizzandoi metodi definitiper
quellaclasse.Ilmetodounacompetenza,unafunzionalitchemetteadisposizioneuna
determinataelaborazionesuidatidelcontainer.Ilmetodosirichiamaperl'oggetto(simanda
unmessaggioall'oggetto)equestoreagirsecondoquantoprevistodalmetodostessocio
effettuersuglielementil'elaborazionedescritta.
Imetodipicomunidellaclasse vectorcheverrannoutilizzatinegliesempidiquestiappuntisono
sintetizzatinellatabella:
Metodo(classevector)
Comportamento
empty()
Restituisceunvalorebooleano(trueofalse)indicanteseilvettore
vuotoocontienealmenounelemento
size()
Restituiscelaquantitdielementicontenutinelvettore
begin()
end()
at()
Permettediaccedereall'elementodelvettorechesitrovainuna
certa posizione. necessario specificare l'indice come numero
interodentroleparentesi(parametro).
push_back()
insert()
Permettel'inserimentodiunelementoinunaposizionequalsiasi
del vettore. Fra parentesi vanno specificati due variabili/valori
(parametri)separati dallavirgola: il puntatoreallaposizione di
inserimento,l'elementodainserire
erase()
Permettel'eliminazionedallastrutturadiunelemento.Richiede
comeparametrounpuntatoreall'elemento.
Unmetodosiapplicaall'oggettospecificandolodopoilnomedell'oggettoe,separatodaquesto
dall'operatorediappartenenza(ilpunto).
Peresempio:
...
vector<int> v;
...
cout << v.size();
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.43
...
larigadicodiceproducelavisualizzazionedellaquantitdielementicontenutinelvettorev.
3.4 Iteratori
L'iteratoreunoggettocheconsentel'accessoaisingolielementidiuncontenitoredioggetti,per
esempiounvettore.Permezzodiuniteratoresipueffettuarelascansionelinearediunvettore,
ovveroscorrereunodopol'altrotuttiglielementicontenutiinunvettorealloscopo,peresempio,di
effettuare determinate elaborazioni. Uniteratore un puntatore all'elemento (ciofornisceuna
indicazionesudovesitrovainmemoriacentralel'elemento)epuessereaggiornatosecondole
regoledell'aritmeticainmododapuntareall'elementosuccessivodellasequenzacomunquesiano
compostiglielementidellasequenza.
Come elementare esempio di uso degli iteratori si propone un frammento di codice in cui,
utilizzandounascansionesequenzialediunvettoredinumeriinteri,vieneraddoppiatoilvaloredi
ciascunelementocontenutoinesso:
vector<int> numeri;
vector<int>::iterator it;
...
for(it=numeri.begin();it!=numeri.end();it++)
*it=*it*2;
/*1*/
/*2*/
/*3*/
/*4*/
Nella1vienedichiaratounvettoreditipo int.Nella2sidichiarauniteratoreingradodiscorrere
glielementidiunvettoredeltipospecificato.Secifossestatounvettoreditipo float,sisarebbe
dovutodefinireuniteratoreopportuno:vector<float>::iterator it.
Ilciclodella3utilizzal'iteratoreinaccordoallestesseregoledeinumeriinteri:vieneassuntocome
valoreinizialedell'iteratorelaposizionedelprimoelementodelvettore( numeri.begin()),sipassa
poialprossimoelemento(it++)finoaquandoilvaloredell'iteratorerappresentiunaposizione
validadiversa,cio,rispettoaquellarestituitadalmetodoend().Passandoalprossimoelemento,
infatti,l'iteratorepuntaalsuccessivoelementofinoaraggiungereilvalorerestituitodalmetodo.
Inquestocasovieneutilizzatacomeparametrodelmetodolaposizionerelativadell'elemento.
necessariochenella posizione specificata cisial'elemento. L'indice deveindicare unelemento
esistente.
Inconclusionesipusintetizzare:
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.44
l'iteratoresiusaquandositrattadieffettuareaccessosequenzialeaglielementidell'insieme
ilmetodoat()siusasesinecessitadiaccessodirettoasingolielementi.
Ilmetodo at prevedecomeparametrounnumerointero(laposizionedell'elemento)enonpu
essere quindi utilizzato un iteratore. possibile tuttavia ricavare la posizione relativa di un
elementoall'internodelvettore,conoscendoilvaloredell'iteratorechepuntaall'elemento:
vector<int> numeri;
vector<int>::iterator it;
int posRel;
...
for(it=numeri.begin();it!=numeri.end();it++){
posRel = it-numeri.begin();
cout << posizione elemento << posRel;
/*1*/
Laposizionedell'elementoricavata(1)sottraendodalvaloreattualedell'iteratore(laposizionein
memoriadell'elementoattuale)laposizionedelprimoelementodelvettore.Lasottrazionefradue
iteratoriproduceunnumerointeroperch,comesigifattonotare,gliiteratoriseguonoleregole
dell'aritmetica. Il risultato della differenza un numero che rappresenta di quante posizioni
spostatol'elementoattualerispettoallaposizionedelprimoelementodelvettore.
/*1*/
// Prossimo valore
cin >> temp;
}
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.45
/*1*/
/*2*/
/*1*/
/*2*/
/*3*/
/*4*/
}
// risultati ricerca
if(pos!=numeri.end())
cout << "elemento trovato in posizione "
<< pos-numeri.begin() << endl;
else
cout << "elemento non trovato" << endl;
/*5*/
/*6*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.46
Ricercadiunsottoinsieme(selezione).Laselezioneconsistenelricopiareinunnuovo
vettoretuttiglielementidelvettoreinizialechesoddisfanoadunadeterminatacondizione:
// Selezione numeri pari
vector<int> pari;
...
// Scansione lineare dell'insieme
for(it=numeri.begin();it!=numeri.end();it++){
// verifica se elemento da inserire in selezione
if(!(*it%2))
pari.push_back(*it);
/*1*/
}
// Verifica se insieme vuoto
if(pari.empty())
cout << Non ci sono numeri pari << endl;
/*2*/
Ilframmentodiprogrammadifferiscedaquellodellaricercasoloperilfattochequila
verifica della condizione (1) comporta l'inserimento dell'elemento nella selezione.
Utilizzandoilmetodo empty() delnuovovettore(2)sipustabilireseilsottoinsieme
vuoto.
Ilprossimoprogrammaunesempiodicomeiframmentipresentatipossonoesseremessiassieme
perrisolvereunproblemaconl'utilizzodivettori.Poichunvettoresostanzialmenteuninsiemesi
potrebbepensareallacostruzionedell'insiemeintersezionedidueinsiemiicuielementisono,per
esempio,interi.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <int> insiemeA, insiemeB, intersezione;
vector<int>::iterator it1;
cout << "Intersezione fra due insiemi di interi" << endl;
// Popolamento primo insieme
/*1*/
/*1*/
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.47
// Output intersezione
return 0;
}
Nelle 1 bastaadattareilframmentodicodicedell'inserimentodielementiinunvettore.Quisi
supponechel'utilizzatoredelprogrammastiaattento,poichsitrattadiinsiemi,adinserirevalori
distintiperglielementidiciascuninsieme.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <int> insiemeA, insiemeB, intersezione;
vector<int>::iterator it1;
int temp;
// valore temporaneo da inserire come elemento
/*1*/
/*1*/
/*1*/
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.48
/*2*/
/*3*/
}
// Output intersezione
return 0;
}
Dichiarata una nuova variabile per valore temporaneo si possono aggiungere i due cicli per
popolareidueinsiemi(1).
Perpopolarel'insiemeintersezionenecessariotrovareglielementiincomunefraidueinsiemi.Il
problema si pu risolvere (2) cercando ogni elemento del primo insieme (per mezzo di una
scansionechepermettediesaminare,insequenza,glielementiunopervolta)nelsecondoinsieme.
Sitrattadiadattareeinserireilframmentodicodicedellaricercaesaminatoinprecedenza.Se
l'elementositrovavuoldirecheunelementodell'insiemeintersezione(3).
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <int> insiemeA, insiemeB, intersezione;
vector<int>::iterator it1, it2, // iter. per scansione vettori
pos;
// puntatore elemento comune
int temp;
// valore temporaneo da inserire come elemento
cout << "Intersezione fra due insiemi di interi" << endl;
// Popolamento primo insieme
cout << "primo insieme" << endl;
cout << "Elemento (0 per finire) ";
cin >> temp;
while(temp){
// Inserimento nel vettore
insiemeA.push_back(temp);
// Prossimo valore
cout << "Elemento (0 per finire) ";
cin >> temp;
}
// Popolamento secondo insieme
cout << "secondo insieme" << endl;
cout << "Elemento (0 per finire) ";
cin >> temp;
while(temp){
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.49
/*2*/
if(intersezione.empty())
cout << "Insieme intersezione vuoto" << endl;
else {
cout << "Insieme intersezione" << endl;
for(it1=intersezione.begin();it1!=intersezione.end();it1++)
cout << *it1 << "\t";
cout << endl;
}
/*3*/
return 0;
}
Dalla1vieneinseritoilcodiceperlaricercanelsecondovettoredell'elementodelprimo(*it1).
Conl'inserimentodelframmentodell'outputdelvettorechecontienel'insiemeintersezione( 2)il
programma completo. L'insieme intersezione potrebbe essere vuoto ed quindi necessario
controllaretaleevenienza(3).
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.50
#include <vector>
using namespace std;
int main()
{
vector<int> numeri;
vector<int>::iterator it,
// iter per scansione vettore
pos; // iter posizione inserimento
const int qelem = 10; // quantit elementi contenuti nel vettore
int i,
// contatore ciclo
temp; // var. temporanea per inserimento in vettore
int cosa, // elemento da inserire
p;
// pos relativa elem da eliminare
cout << "Inserisce un numero in un vettore ordinato ed" << endl;
cout << "Elimina un elemento, conoscendone la posizione \n\n";
// Riempimento di un vettore contenete 10 elementi
cout << "Inserimento elementi ordinati" << endl;
for(i=0; i<qelem; i++){
cout << "elemento " << i << " -->";
cin >> temp;
// verifica ordinamento
if(!i || temp>numeri.at(i-1))
numeri.push_back(temp);
else{
cout << "La sequenza deve essere ordinata" << endl
<< "Ripetere l\'inserimento" << endl;
i--;
};
/*1*/
/*2*/
/*3*/
};
cout << "Elemento da inserire ";
cin >> cosa;
// Ricerca posizione
pos=numeri.end();
for(it=numeri.begin(); it!=numeri.end(); it++){
if(cosa<(*it)){
pos = it;
break;
}
}
/*4*/
/*5*/
/*6*/
/*7*/
http://ennebi.solira.org
/*8*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.51
/*9*/
/*10*/
// Nuova visualizzazione
cout << "\nNuovo vettore " << endl;
for(it=numeri.begin(); it!=numeri.end(); it++)
cout << *it << "\t";
cout << endl;
/*8*/
return 0;
}
ilcontrolloin1che,sostanzialmente,permettedistabilireselasequenzacrescente.Sesitratta
delprimoelemento(!iciosei0)ol'inputmaggioredell'elementoinseritoprecedentemente
(quelloconindicei-1),siinserisceincoda(2).L'ultimacondizionenonavrebbesensoperilprimo
elemento ma, per l'operatore OR (||), basta che la prima condizione sia verificata per non
procedereoltre.Vieneutilizzatoilmetodoatperaccedereall'elementoprecedente.
Seilvaloreinseritononmaggioredelprecedente,bastadecrementarel'indicedelciclo(3).Questa
operazione necessaria poich, in ogni caso, per effetto del costrutto for, l'indice verrebbe
incrementatoprimadipassarealcontrollodelciclo.Ingeneralenonunabuonaprassimodificare,
all'internodiunciclofor,lavariabilechecontrollailciclo(puesserefontedierroridifficilida
rintracciare) ma qui la variabile utilizzata solo per visualizzare l'ordine di inserimento
dell'elemento.Unasoluzionemigliorepotrebbeessereutilizzareunciclowhile.
Perl'inserimentodeglielementinelvettorequestavolta utilizzatounciclo for trattandosidi
inserire10elementi.Perilrestoilciclodiinputidenticoalciclowhiletrattatoinprecedenza.
Anchelaricercadellaposizionediinserimentoformalmenteidenticaaquellaesaminatainesempi
precedentisalvoilfatto(4)chequisicercailprimoelementodelvettorecheabbiavaloremaggiore
dell'elementodainserire.Ilposto,nelvettore,cheilnuovoelementoprendersarappuntoquesto.
Sestatotrovatounelementodelvettoremaggioredelvaloredainserire( 5)siinseriscel'elemento
intaleposizione(6).Ilmetodoinsertrichiedecomeprimoparametrouniteratoreallaposizionedi
inserimento che, in questo caso, sar la posizione del primo elemento del vettore con valore
maggiore.Senonesistealcunelementodelvettoremaggiore,ilnuovovaloreverraccodato( 7)a
quelligipresenti.
Ancheilmetodoeraseperl'eliminazionediunelementodalvettore,richiedeuniteratorechepunti
ataleelemento.Dall'input(9)siricevelaposizionerelativa(loscostamento):basta(10)sommare
talescostamentoalvaloredelpuntatorealprimoelementodelvettore.
Iciclidelle8sioccupanodivisualizzareglieffetti,nelvettore,delleoperazionisvolte.
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.52
Metodo(classestring)
Comportamento
length()
empty()
Restituiscevalorebooleanoindicanteselastringavuota(valore
true)ocontienealmenouncarattere(valorefalse)
begin()
end()
at()
insert()
Permettel'inserimentodiunastringainunaposizionequalsiasidi
un altra stringa. Fra parentesi vanno specificati due parametri
separatidallavirgola:laposizionediinserimento,lastringada
inserire
erase()
Permettel'eliminazionediunasottostringadaunastringa.Vanno
specificati come parametri la posizione a partire dalla quale
eliminarecaratterielaquantitdeicaratteridaeliminare
find()
Restituisceunnumerointerocheindicalaposizioneincuistato
trovatoilcaratterespecificato.Selaricercahaesitonegativoil
metodorestituisceilvalore1.Ilprimoparametro,obbligatorio,
indicailcaratteredacercareall'internodellastringa.Ilsecondo
parametro,opzionale,unnumerointerocheindicalaposizione
all'internodellastringaapartiredallaqualeiniziarelaricerca.Se
ilparametrononvienespecificato,vieneassuntaperdefaultla
posizioneinizialedellastringa(0)
substr()
Leposizioni cui sifariferimento nei metodi sonocontate apartire da0(posizione del primo
caratteredellastringa).
Per agevolare alcune elaborazioni presenti anche in esempi di questi appunti opportuno
aggiungere,fralefunzionalitdisponibiliperglioggettistring:
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.53
Funzioni introdotte nella revisione C++11 per convertire una
stringaecherestituiscono,rispettivamente,unintero,unfloato
undouble.Nonsonometodielastringadaconvertiresiinserisce
comeparametro.Siusanospecificandodirettamenteilnomedella
funzioneeilparametro.
stoi()
stof() stod()
Peroggettidellaclassestringdefinitoanchel'operatore+diconcatenamentostringhe.
...
string s1, s2, s3;
s1 = buon ;
s2 = giorno;
s3 = s1 + s2;
...
Dopoleoperazioniindicates3conterrlastringabuon giorno.
/*1*/
/*2*/
// carattere da cercare
// ricorrenze, posizione carattere nella stringa
/*3*/
/*4*/
http://ennebi.solira.org
/*5*/
/*6*/
/*7*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.54
volte++;
}
cout << "\n\nil carattere " << cosa << " si presenta "
<< volte << " volte" << endl;
return 0;
}
Perpoterdichiarareoggettiditipostring,comein2,necessarioincluderelarelativalibreria(1).
L'input di una stringa (3) poteva essere effettuato come per le variabili di tipo elementare
utilizzandol'operatorediestrazionedalcanale cin.Questopervabenesenellastringafornitain
inputnonsiinserisconocaratterispecialicomeilcarattere Spazio.Inquestocasoinfatti,come
notatoinprecedenza,leduepartidellastringaailatidello Spazio verrebberopercepiticomedue
inputdiversi.Utilizzandolafunzione getline puessereacquisitaunastringaconteneteanche
caratterispecialicomelospaziooicaratteridipunteggiaturafino(perdefault)alcarattereInvioche
chiudel'inputdellastringa.Lafunzionesiutilizzaspecificandofraparentesialmenodueparametri:
ilcanaledadoveleggereelavariabiledestinataacontenereicaratteriprovenientidalcanale.Il
terzoparametro,opzionaleenonutilizzatonegliesempi,permettedispecificareilcaratterechesi
intendecometerminatoredellastringa.SenonspecificatotalecarattereilcarattereInvio.
L'assegnazionediunvaloreadunastringavieneeffettuatapermezzodelsolitooperatore=,solo
necessario racchiudere la stringa fra doppi apici ( dove = stringa di prova;). Nelle
operazionidiconfrontofrastringhesiutilizzanoisolitioperatori(<,<=,>,>=,==,!=).
Lavariabilebooleanacontinua,inizializzatain4,controllailciclosuccessivo.
Ilmessaggiofind,inviatoin5allastringadove,comandadicercareilprimoparametro,immesso
fraparentesi,apartiredallaposizionespecificatacomesecondoparametro.Ilrisultatodiquesta
ricercavienefornitocomevaloreinterocheconservatoin pos.Laposizioneinizialediricerca0
(ilprimocaratteredellastringa:posinizializzatoa-1e,comeparametro,vienefornitopos+1).Le
ricerchesuccessivecomincerannodallaposizionesuccessivaaquellatrovatainprecedenza.
Senonsitrovanoulterioriricorrenze,lafunzionemembro findassociataadove,fornisceilvalore
-1(6)el'elaborazioneputerminare:la7fainmododirenderefalsalacondizionedicontrollodel
ciclo.
Ilprossimoprogrammaproposto,acquisitaunastringaformatadaalmenodueparoleeunaparola,
sostituiscelasecondaparoladellastringaconlaparolaacquisitadainput.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string dove,
metti;
int inizio,fine,
quanti;
//
//
//
//
stringa da elaborare
parola da inserire
posizioni spazi delimitanti parola da sostituire
quanti caratteri eliminare
cout << "Data una stringa e una parola in input" << endl
<< "la inserisce al posto della seconda parola della stringa";
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.55
/*1*/
/*2*/
/*3*/
/*4*/
/*5*/
cout << "Nuova stringa" << endl << dove << endl;
return 0;
}
http://ennebi.solira.org
// materia interessata
// valutazione ottenuta dall'allievo
// solo materia
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
int cont,pos;
float vot,somma;
float media;
C++:programmazioneedoggettipag.56
// conta voti
// voto numerico, somma voti
/*1*/
cont=0;
somma=0.0;
cout << "Materia e voto separati da virgola (invio per finire) ";
getline(cin,matvoto);
/*2*/
while(!(matvoto.empty())){
temp=matvoto;
pos=temp.find(',');
/*3*/
/*4*/
/*5*/
/*6*/
/*7*/
}
cout << "Materia e voto separati da virgola (invio per finire) ";
getline(cin,matvoto);
/*2*/
}
if(cont){
media = somma/cont;
cout << "media dei voti nella materia " << media << endl;
}
else
cout << "Non ci sono valutazioni per quella materia" << endl;
return 0;
}
Nella1siacquisiscelamateriadicuisivuolecalcolarelamediadellevalutazioni.
Nelle 2 siacquisisconolestringhedellevalutazionifinchlastringastessanonrisultivuota.La
stringavienericopiatainun'altra(3)perpoterlaelaboraresenzachelemodifichecomportinoun
mutamentodiquellochestatoacquisitoininput.Questaunapraticacomune:gliinputnonsi
modificanomaiperchrappresentano,aifinidiqualsiasitipodiesigenza,ilpuntodipartenzadella
elaborazione.Seserve,comenelcasoproposto,modificareilvalorediuninput,questosiricopiain
unanuovavariabile.
Perognivalutazioneinnanzituttosiricerca( 4)laposizionedellavirgolaseparatrice,siricopia( 5)
inunanuovastringatuttalasottostringacherappresentalamateria:laquantitdicaratterilo
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.57
stessonumerodellaposizionedellavirgola(leposizionisicontanoda0)esicancella( 6)laparte
estrattaoltrechelavirgolaseparatrice.Questascelta dettatadallamotivazionedirenderepi
semplicel'elaborazionedellasuddivisionedellepartilogichedellastringa,principalmentequando
lepartisonotante.
L'istruzioneprincipaledelprogrammala 7.Toltalapartedellamateria,conla 6,nellastringa
temp rimastosoloilvotomanon immediatamenteutilizzabileperchinformatostringa.
necessariotrasformarloneltipoopportuno.Seeranecessariaunaconversioneinvaloreditipo int
occorrevautilizzarestoialpostodistof.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.58
/*2*/
/*3*/
/*4*/
/*5*/
/*4*/
/*5*/
/*4*/
/*5*/
}
// presentazione dei risultati
cout << "\nGraffe = " << pargraf << endl;
cout << "Quadre = " << parquad << endl;
cout << "Tonde = " << partond << endl;
return 0;
}
Nella 1 sidichiarauniteratoreperlascansionesequenzialedellastringa.Ladichiarazioneeil
funzionamentoditaleiteratoreidenticoaquelloutilizzatoinprecedenzaperlascansionediun
vettore.
Il ciclo che comincia da 2 si occupa di effettuare la scansione lineare della stringa: verranno
esaminatituttiicaratterichelacompongono.Lastringatrattatacomeunvettoredicaratteri.
Nella riga con etichetta 3 viene specificata lespressione da valutare: *it cio il carattere
dellespressionealgebricachesiottienedeferenziandol'iteratore.
Nellerigheconetichetta 4siesaminanoicasiparentesiapertaoparentesichiusa.Isingolivalori
sonoseguitidallaistruzionenulla(ilsolocarattere ;)e,poichlelaborazionecontinuadaquel
puntoinpoi,siachesitrattidiparentesiapertachediparentesichiusasiarrivaallaggiornamento
delrispettivocontatore.
Nelle righe con etichetta 5 si blocca lesecuzione del programma altrimenti, per esempio, una
parentesi graffa oltre che come graffa verrebbe conteggiata anche come quadra e tonda, una
parentesiquadraverrebbeconteggiataanchecometonda.Sinotiche,anchesesonopresentidue
istruzioni,nonvengonoutilizzateparentesiperdelimitareilblocco:ilfunzionamentodella switchcase prevede infatti la continuazione dellelaborazione con listruzione successiva. Lultima
istruzione break inseritasolopercoerenzaconglialtricasi.Inoltreseinseguitosidovesse
aggiungere una istruzione default, il programma continuerebbe a dare risultati coerenti senza
necessitdiinterventisenonnellapartedainserire.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.59
/*2*/
if(!stinp.empty())
vocab.push_back(stinp);
else
continua=false;
/*3*/
/*4*/
/*5*/
// Cerca la parola
pos=vocab.end();
for (it=vocab.begin();it!=vocab.end();it++) {
if (*it==parcerc) {
pos=it;
break;
/*6*/
/*7*/
/*8*/
}
}
if (pos!=vocab.end())
cout << "\nParola trovata, posizione " << pos-vocab.begin();
else
cout << "\nParola non trovata";
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.60
Nella1sidichiaravocabcomevettoredistringhe.
Il ciclo di acquisizione delle parole contenute nel vocabolario, controllato dal valore della
variabilebooleanacontinua(2).Sel'inputvuoto(3),ilvalorevienepostoafalse(4)eilciclo
termina.
Ancheilcicloperl'inputdelleparoledacercare( 5)sicomportaallostessomodo:selastringa
vuota,l'elaborazionetermina.L'unicadifferenzaconilcicloprecedenteche,qui,nonsivisualizza
unconteggiodelleparole.
Nel ciclo 6 viene effettuata una scansione del vocabolario alla ricerca, se esiste, di una
corrispondenzaconlastringacercata(7).Selaparolapresentenelvocabolariola8sioccupadi
forzarel'uscitadalciclo.inutilecontinuarelascansionedelleparoledelvocabolario.
Ilsecondoprogrammapropostoestraedauntestotutteleparolechelocompongonoeleinserisce
inunvettore:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string testo,estratta; // testo da elaborare, parola estratta
vector<string> token;
// parole estratte
vector<string>::iterator it;
int inizio,fine,
// pos spazi delimitanti parola
lparola;
bool continua;
cout << "Estrae tutte le parole contenute in un testo" << endl;
cout << "\nTesto : ";
getline(cin,testo);
// Estrazione parole (parola racchiusa fra spazi)
// fra due parole c' un solo spazio
continua = true;
inizio = -1;
while(continua){
fine = testo.find(' ',inizio+1);
/*1*/
/*2*/
// ultima parola
if(fine==-1){
continua = false;
http://ennebi.solira.org
/*3*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.61
fine = testo.length();
/*4*/
}
// Estrazione parola
lparola = (fine-inizio)-1;
estratta = testo.substr(inizio+1,lparola);
token.push_back(estratta);
/*5*/
/*6*/
/*7*/
inizio = fine;
/*8*/
}
// Elenco parole
cout << "\nParole che compongono il testo" << endl;
for(it=token.begin();it!=token.end();it++)
cout << *it << endl;
return 0;
}
Sicomincial'elaborazioneinizializzandolavariabileinizio(1)chesarlaposizione,dellospazio
cheprecedelaparola,dacuiiniziarelaricercadellospaziochedelimitalafinedellaparolada
estrarre (2). La parola delimitata dagli spazi che si trovano nella posizione inizio e nella
posizione fine(sempre2).Lacoppiadivalori,contenutinellesuddettevariabili,vieneutilizzata
percalcolarelaquantitdicaratterichecompongonolaparola.
Se si arrivati alla fine del testo da elaborare (controllo della 3), oltre che rendere falsa la
condizione di controllo del ciclo al fine di chiudere l'elaborazione, viene assegnata a fine la
lunghezzadeltesto(4).comesesiposizionasse fine nello spaziodopol'ultimocarattere del
testo.
Lalunghezzadellaparola,equindilaquantitdicaratteridaestrarre,calcolatain5.L'estrazione
dei caratteri effettuata dal metodo substr richiamato per la stringa testo, passandogli la
posizionedacuiestrarre(quelladopolaposizionedellospaziocheprecedelaparola)elaquantit
dicaratteridaestrarre(6).Laparolavienesuccessivamente(7)inseritainunvettore.
L'assegnazionedella8haloscopodipassareavantinellaricercadellaprossimaparola,assegnando
comepuntodipartenzaperlaricerca,ilpuntofinaledell'elaborazioneprecedente.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.62
4 Il paradigma procedurale
4.1 Costruzione di un programma: lo sviluppo top-down
Unparadigmauninsiemediideescientifichecollettivamenteaccettatoperdareunsensoal
mondo dei fenomeni (T.S.Khun). Applicare un paradigma significa applicare una tecnica per
scriverebuoniprogrammi.Inquestoeneiseguentiparagrafiverrespostoilparadigmaprocedurale
chepuesserecossintetizzato:sidefiniscanoleproceduredesiderate;siutilizzinoglialgoritmi
migliori.
Accadespesso,specieneiproblemicomplessi,cheunastessasequenzadiistruzionicompaianella
stessaformainpipartidellostessoprogrammaochesiautilizzatainpiprogrammi.Glialgoritmi
riguardano elaborazioni astratte di dati che possono essere adattate a problemi di natura
apparentementediversi(dalpuntodivistainformaticodueproblemisonodiversisenecessitanodi
elaborazioni diverse e non se trattano di cose diverse). Per fare un esempio riguardante altre
disciplinebastapensare,peresempio,allaGeometria:ilcalcolodellareadiunasuperficievariain
relazioneallaformageometricadiversaenonallanaturadelloggetto.Lareadiunabanconotaodi
unalastradimarmosicalcolersempreallostessomodotrattandosiinambedueicasidirettangoli.
Lelaborazioneriguardanteilcalcolodellareadiunrettangoloricorrerneiproblemidicalcolodi
blocchidimarmocoscomeneiproblemidicalcolodifoglisucuistamparebanconote.
Per risparmiare un inutile lavoro di riscrittura di parti di codice gi esistenti, i linguaggi di
programmazioneprevedonolusodeisottoprogrammi.Sostanzialmenteunsottoprogrammauna
partedelprogrammachesvolgeunafunzioneelementare.
Luso di sottoprogrammi non solo limitato al risparmio di lavoro della riscrittura di parti di
codice,maancheunostrumentochepermettediaffrontareproblemicomplessiriconducendolia
uninsieme diproblemi didifficolt viavia inferiore. Tutto ci consente alprogrammatore un
controllo maggiore sul programma stesso nascondendo nella fase di risoluzione del singolo
sottoprogramma,lealtripartiinmodotaledaisolareisingoliaspettidelproblemadarisolvere.
Si tratta del procedimento di stesura per raffinamenti successivi (o topdown). Quando la
complessit del problema da risolvere cresce, diventa difficoltoso tenere conto
contemporaneamente di tutti gli aspetti coinvolti, fin nei minimi particolari, e prendere
contemporaneamente tutte le decisioni realizzative: in tal caso sar necessario procedere per
approssimazionisuccessive,ciodecomporreilproblemainizialeinsottoproblemipisemplici.In
tal modo si affronter la risoluzione del problema iniziale considerando in una prima
approssimazionerisolti,daaltriprogrammidilivellogerarchicoinferiore,gliaspettidimassimadel
problemastesso.Siaffronterquindiciascunodeisottoproblemiinmodoanalogo.
Indefinitivasicominciaspecificandolasequenzadeglistatidiavanzamentoperlasoluzionedel
problema proposto anche se, in questa prima fase, possono mancare i dettagli realizzativi: si
presupponeinfattichetalidettagliesistanogi.Il programma,inquestaprimastesura,conterr,
oltre alle solite strutture di controllo, anche operazioni complesse che dovranno poi essere
ulteriormentespecificate.Passandopoiallesamediunasingolafasedilavoro,questapotrancora
prevedere azioni complesse ma riguarder, per come stata derivata, una parte del problema
iniziale. Iterando il procedimento, mano a mano, si prenderanno in esame programmi che
riguardano parti sempre pi limitate del problema iniziale. In tal modo la risoluzione di un
problemacomplessostataricondottaallarisoluzionedipiproblemisemplici(tantiquantesono
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.63
lefunzioniprevistedallaelaborazioneoriginaria).
Ilprocessodiscomposizionesuccessivanonfissatoinmanieraunivoca:dipendefortementedalla
soggettivit delprogrammatore. Noncisonoregolesulla quantitdipezzi incuiscomporreil
programma.Cisonodelleindicazionidimassimachesuggerisconodilimitareilsingolosegmento
inmanierasufficienteacheilcodicenonsuperidimoltolaschermatadiunvideoinmododa
coprire,conlosguardo,l'interooquasilistatoelimitareilsingolosegmentoapocheazionidimodo
che sia pi semplice isolare eventuali errori. Inoltre il sottoprogramma deve essere isolato dal
contesto in cui opera, cio deve avere al suo interno tutto ci di cui ha bisogno e non fare
riferimento a dati particolari presenti nel programma principale. Ci porta ad alcuni indubbi
vantaggi:
Ilsottoprogrammafacilmenteesportabile.Sedallascomposizionedialtriprogrammisi
vede che si ha necessit di utilizzare elaborazioni uguali si pu riutilizzare il
sottoprogramma. evidente che affinch ci sia possibile necessario che il
sottoprogramma non faccia riferimento a contesti che in questo caso potrebbero essere
diversi. Se, inoltre, il sottoprogramma effettua una sola operazione si potr avere pi
opportunitdiinserirloinnuoveelaborazioni.
Lamanutenzionedelprogrammasemplificatadalfattoche,effettuandoilsottoprogramma
unasingolaelaborazionee,avendoalsuointernotuttocicheserve,secunerrorenella
elaborazione questo completamente isolato nel sottoprogramma stesso e, quindi, pi
facilmenterintracciabile.
Qualora si avesse necessit di modificare una parte del programma, ci pu avvenire
facilmente: basta sostituire solamente il sottoprogramma che esegue lelaborazione da
modificare.Ilrestodelprogrammanonvieneinteressatodallamodificaeffettuata.
Lutilizzodisottoprogrammigiprontiperlacostruzionediunnuovoprogrammaportaaduna
metodologia di sviluppo dei programmi che viene comunemente chiamata bottomup poich
rappresenta un modo di procedere opposto a quello descritto fino ad ora. Si parte da
sottoprogrammi gi esistenti che vengono assemblati assieme a nuovi per costruire la nuova
elaborazione.Indefinitiva sipuaffermareche,nellacostruzionediunnuovoalgoritmo,
dominanteilprocessotopdown,mentrenelladattamento(ascopidiversi)diunprogrammagi
scritto,assumeunamaggioreimportanzailmetodobottomup.(N.Wirth).
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.64
proprioutput(intesicomesommadelleinformazioniprodottealsuointerno).Questi,alorovolta,
potrebberocostituiregliinputperunulterioresottoprogramma.
Pergarantirequantopipossibilelaportabilitelindipendenzadeisottoprogrammi,ilinguaggi
strutturatidistinguonolevariabiliinbaseallavisibilit(ininglesescope).Inrelazioneallavisibilit
levariabilisidividonoinduefamiglieprincipali:
Variabili globali visibilicio datutti isottoprogrammi. Tutti isottoprogrammi possono
utilizzarleemodificarle.Sonopraticamentepatrimoniocomune.
Variabili locali visibilisolodalsottoprogrammachelidichiara.Glialtrisottoprogrammi,
anchesechiamati, nonhannoaccessoa tali variabili. La variabile locale definita nel
sottoprogrammaedquiutilizzabile.Sevienechiamatounsottoprogrammalevariabilidel
chiamantesonomascherate(nonaccessibili)eriprenderannoadesserevisibiliquandoil
chiamatotermineresitorneralchiamante.Lambientedelchiamante(linsiemedelle
variabiliconirispettivivalori)aquestopuntoverrripristinatoesattamentecomeeraprima
dellachiamata.
Per quanto ribadito pi volte sarebbe necessario utilizzare quanto meno possibile (al limite
eliminare) le variabili globali per ridurre al minimo la dipendenza dal contesto da parte del
sottoprogramma.
Riguardandoper,lelaborazione,daticomuni,necessariocheilprogrammachiamantesiain
condizionidipotercomunicareconilchiamato.Devonocioesisteredelleconvenzionidichiamata
cio delle convenzioni che permettono al chiamante di comunicare dei parametri che
rappresenterannogliinputsuiqualiopererilchiamato.Daltraparteilchiamatoavrnecessitdi
tornare al chiamante dei parametri che conterranno i risultati della propria elaborazione e che
potrannoesseregestitisuccessivamente.Questeconvenzionisonogeneralmenteconosciutecome
passaggiodiparametri.
Ilpassaggiodiparametripuavveniresecondoduemodalit:
Sidicecheunparametropassatopervalore(dalchiamantealchiamato)seilchiamante
comunicaalchiamatoilvalorechecontenuto,inquelmomento,inunasuavariabile.Il
chiamatopredisporrunapropriavariabilelocalenellaqualeverrricopiatotalevalore.Il
chiamatopuoperaresutalevalore,puanchemodificarlomatalimodificheriguarderanno
sololacopialocalesucuistalavorando.Terminatoilsottoprogrammalavariabilelocale
scompareassiemealvalorechecontieneevieneripristinatalavariabiledelchiamanteconil
valorecheessacontenevaprimadellachiamataalsottoprogramma.
Si dice che un parametro passato per riferimento o per indirizzo se il chiamante
comunicaalchiamatolindirizzodimemoriadiunadeterminatavariabile.Ilchiamatopu
utilizzare,perlavariabile,unnomediversomalelocazionidimemoriaacuicisiriferisce
sono sempre le stesse. Viene semplicemente stabilito un riferimento diverso alle stesse
posizioni di memoria: ogni modifica effettuata si ripercuoter sulla variabile originaria
ancheseilnuovonomecessadiesistereallaconclusionedelsottoprogramma.
Persintetizzarepraticamentesucosapassarepervaloreecosaperriferimento,sipuaffermareche
gli input di un sottoprogramma sono passati per valore mentre gli output sono passati per
riferimento. Gli input di un sottoprogramma sono utili allo stesso per compiere le proprie
elaborazionimentreglioutputsonoiprodottidellapropriaelaborazionechedevonoessereresi
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.65
disponibilialchiamante.
/*1*/
namespace prova1{
int a=5;
};
namespace prova2{
int a=10;
int b=8;
};
/*2*/
/*3*/
int main()
{
cout << prova1::a << endl;
cout << prova2::a << endl;
cout << prova2::b << endl;
/*4*/
/*5*/
/*6*/
return 0;
}
Ladichiarazionedi1rendeaccessibilituttiinomidelnamespacestd.LelibreriedisponibilinelC+
+(iostream,string,vector,ecc...)hannoinomi(cin,cout,ecc...)inclusiinquestonamespace.
Nella2vienedichiaratoprova1checontienealsuointernounavariabileacheassumeunvalore
diversodaquelloassuntodaunavariabile,conlostessonome,dichiaratanelnamespace prova2
(3).
Nella 4 si richiede la stampa della variabile a definita nel namespace prova1. L'operatore ::,
operatoredivisibilit,consentedispecificareinqualenamespacedeveesserecercatalavariabilea.
Senzaquestooperatore,ilcompilatoregenererebbeunerrore:noninfattidefinita,nel main,alcuna
variabilea.
Ilvalorestampatoinconseguenzadellaesecuzionedella 5diversodalprecedente,poichquicisi
riferisceallavariabileadefinitanelnamespaceprova2.
Sipotevaaggiungereunarigadeltipo:
using namespace prova1;
e,inquestocaso,noneranecessarioutilizzarel'operatoredivisibilitnella4.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.66
#include <iostream>
using namespace std;
namespace prova1{
int a=5;
};
namespace prova2{
int a=10;
int b=8;
};
using namespace prova1;
using namespace prova2;
/*1*/
/*1*/
int main()
{
cout << prova1::a << endl;
cout << prova2::a << endl;
cout << b << endl;
/*2*/
/*2*/
/*3*/
return 0;
}
Sipufareinmodo,comenelle 1,direndereaccessibiliinomideiduenamespace,e,quindi,avere
lapossibilitdiaccedereaquantocontenutosenzanecessitdispecificarel'operatoredivisibilit
::,ma,inquestocaso,talepossibilitpuesseresfruttatasolonelcasodella 3.Neglialtriduecasi
diuso(2)necessariospecificareilnamespaceperchilriferimentoambiguo.Talesarebbeanche
la natura dell'errore evidenziato dal compilatore, se non si usasse l'operatore di visibilit: la
variabiledefinitaintutteedueinamespaceeilcompilatorenonpudecidereaqualeriferirsi.In
lineageneralepuessereconvenienteutilizzareunaistruzione using namespace perlelibrerie
standarddellinguaggiomaspecificarel'operatoredivisibilitintuttiglialtricasi.
Selostessonamespacedefinitopivolte,ogninuovadefinizioneespandequellaprecedente:tutte
levariabilisonodefiniteall'internodiununiconamespaceanchesedichiarateintempidiversi.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.67
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.68
istruzionicoscomedalloschemaseguentedoveevidenziatoanchelostilediscrittura:
tipo-ritornato nome-funzione(dichiarazione parametri)
{
dichiarazioni ed istruzioni
}
Laprimarigadelladefinizionedifferiscedalprototipoperilfattoche,qui,sonopresentile
dichiarazionidellevariabililocalie,inoltre,lariganonterminaconilpuntoevirgolama
seguitadaunbloccocheracchiudeleistruzionicontenutenellafunzione.Ladichiarazione
deiparametrisegue,inlineadimassima,leregoledelladefinizionedellevariabiliutilizzata
neglialtriesempitrattatiinprecedenza,tranneper:
iparametrisonodistintidallavirgola
perognitiposipudichiarareunasolavariabile.Nonpossibileconununicotipo
dichiararepiparametri,necessarioripetereladichiarazioneditipo
Selafunzioneritornauntipovoidl'istruzionereturnmanca.
Nonimportantecheledefinizionidituttelefunzioniusateinunprogrammaseguano
lordineconcuisonochiamatesebbene,permotividichiarezzaeleggibilit,opportuno
chesiacosechesisegualordinespecificatoprima.Inognicasolafunzioneconilnome
main(cheunnomeriservato)eseguitaperprimaall'avviodelprogramma,inqualunque
postosiamessa,elefunzionisonoeseguitenellordineincuisonochiamate.
Diconseguenzaaquantorichiestodallasintassisipuosservare,inoltre,che main una
funzionecheritornaunvaloreintero.Tuttocifapartediunaconcezionedellefunzioni
ereditatadallinguaggioC:unafunzioneritornasempreunvalorecheindicalaconclusione
correttadell'elaborazione(valore0oaltrovaloresesisonoriscontratiproblemi).Equesto
ancheilmotivopercuiinCtuttiisottoprogrammisonofunzioni.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.69
/*1*/
/*1*/
// prototitpi
int main()
{
vector<int> numeri,
pari;
// insieme da elaborare
// sottoinsieme dei pari
/*2*/
Inquesta prima stesura,a partele inclusioni che servono(1)e ladichiarazione delle variabili
necessarieallarisoluzionedelproblema(2)cheinquestoesempiosonodueoggettidellaclasse
vector,sonopresentisoltantorighedicommentoutilizzateperstabilirequalicosefareeinquale
ordine.
Stabilita,pergrandilinee,lasequenzadellefunzionidasvolgere,sipassaachiariremegliolaprima
funzione: quella che si deve occupare dell'input dei numeri da elaborare. In questa sede
importantesolostabilirecosalafunzionedevefareecomesideveutilizzare.
Cosafalafunzione:la funzione,chepotr averenome inputNumeri,dovroccuparsi
dell'inputdatastieradeinumeridaelaborare.
Comesiutilizzalafunzione:lafunzionenonhabisognodiinput(nongliservenienteper
potereassolvereaipropricompiti). Fornisce,inoutput(daticherendedisponibilicome
risultatidellapropriaelaborazione),ilvettorecaricatoconidatiacquisitidatastiera.
Inconseguenza,aquantoosservato,sipotraggiungerealprogrammailprototipoelachiamataalla
funzione:
#include <iostream>
#include <vector>
using namespace std;
// prototitpi
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.70
namespace selez{
vector<int> inputNumeri();
};
int main()
{
vector<int> numeri,
pari;
/*1*/
// insieme da elaborare
// sottoinsieme dei pari
/*2*/
Nelprototipo(1)evidenziatoilfattochelafunzioneritornaunoggettoditipovector<int>.Il
prototipoinseritonelnamespaceselez.Nellachiamataallafunzione(2),mainassegnailvalore
diritornodellafunzioneanumeriequisiritroverannoivaloriacquisitidallafunzione.Lachiamata
effettuata applicando l'operatore di visibilit per specificare il namespace in cui valida la
definizionedellafunzione.
Con lo stesso procedimento si stabiliscono i compiti e le modalit d'uso delle rimanenti due
funzioni:
Lafunzionechesideveoccuparedell'estrazionedelsottoinsiemedipari,echepotravere
nomeestraiPari,hanecessitdiconoscereilvettoredacuiestrarreilsottoinsieme(perla
funzioneuninputequindisarunparametropassatopervalore)eprodurr(outputperla
funzionee,quindi,valorediritornodellafunzione)ilvettoresottoinsieme.
Lafunzionechedovroccuparsidell'outputsuvideodelsottoinsieme,echepotravere
nomeoutputPari,dovrconoscere(input,quindiparametropassatopervalore)ilvettore
davisualizzare.Nonproducedatidatornareamain.Fral'altrolachiamataaquestafunzione
purel'ultimaistruzionechevieneeseguita.Nonsarannonecessariparametriinuscita.
Ilprogramma,coniprototipielechiamateallefunzioni,sar:
#include <iostream>
#include <vector>
using namespace std;
// prototitpi
namespace selez{
vector<int> inputNumeri();
vector<int> estraiPari(vector<int>);
void outputPari(vector<int>);
};
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
int main()
{
vector<int> numeri,
pari;
C++:programmazioneedoggettipag.71
// insieme da elaborare
// sottoinsieme dei pari
/*1*/
/*2*/
/*3*/
return 0;
}
Il vettore numeri viene acquisito in conseguenza alla chiamata della prima funzione ( 1). La
funzioneacquisisceunvettoregenericodiinteriche,invirtdella1,diventanumeri.
La funzione estraiPari genera il sottoinsieme dei pari contenuti nel vettore passato come
parametro.Lachiamata 2 passailparametro numeri equinditalefunzioneestraeiparidaquel
vettore.Ilrisultatodepositatoinpari.
LafunzioneoutputPariinrealtstampasuvideotuttiglielementidelvettorediintericheviene
passatocomeparametro. Lachiamata 3 fainmodoche l'outputriguardiilvettore generatoin
seguitoallachiamata2cioilvettoredeinumeripari.
Ilprogrammaformalmentecompleto:sonospecificatelefunzionicheassolveelasequenzadelle
fasidielaborazione.Naturalmenteperpoterlocompilaree,successivamente,eseguirenecessario
aggiungereilcodicedellefunzioni.Finorasispecificatocosalefunzionifanno,oradovressere
specificatocomelofanno,ovverosidovraggiungereladefinizionedellefunzioni.
...
// prototitpi
namespace selez{
vector<int> inputNumeri();
vector<int> estraiPari(vector<int>);
void outputPari(vector<int>);
};
int main()
{
...
}
// input numeri da elaborare
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.72
vector<int> selez::inputNumeri()
{
vector<int> num;
int temp;
/*3*/
/*4*/
}
// estrazione sottoinsieme pari
vector<int> selez::estraiPari(vector<int> num)
{
vector<int> numpari;
vector<int>::iterator it;
for(it=num.begin();it!=num.end();it++){
if(!(*it%2))
numpari.push_back(*it);
}
/*3*/
/*3*/
/*1*/
/*2*/
return numpari;
}
// output sottoinsieme pari
void selez::outputPari(vector<int> numpari)
{
vector<int>::iterator it;
/*3*/
if(pari.empty())
cout << Non ci sono numeri pari << endl;
else{
cout << Numeri pari trovati << endl;
for(it=numpari.begin();it!=numpari.end();it++)
cout << *it << \t;
cout << endl;
}
}
Lafunzionechesioccupadell'inputdelvettoredichiara(nellaprimarigaconetichetta 3)una
variabile locale il cui valore verr ritornato al programma chiamante per mezzo della 4. La
variabile,alterminedellafunzione,cessalasuavisibiliteilchiamantenonpotrebbeconoscereil
suovalore.
La funzione che genera il sottoinsieme dei pari, esamina il vettore da elaborare e se trova un
elementopari(controlloin1),locaricanelvettoredeipari(2).
Ilfattoche,indiversefunzioni,venganodichiaratevariabiliconlostessonome( 3)volutoe
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.73
dovuto solo a motivi di chiarezza e leggibilit: in realt si tratta di variabili diverse (sono
dichiarazionilocaliallesingolefunzioni).Peresempiolafunzione estraiParigeneraunvettore
contenenteinumeriparipresentiinunvettorepassatoallafunzionecomeparametro,lafunzione
outputPari,inrealt,stampasuvideoilcontenutodiunvettorechericevecomeparametro:la
successionedellechiamateallefunzionistabilitanel main el'usocorrettodeiparametrichefain
modochelafunzionediestrazionedeipariliestraggadalvettoreacquisitoinprecedenzaechela
funzionedioutputmandiinstampailrisultatodelleoperazionidellafunzionediestrazionedeipari.
LafunzioneestraiParigenerailvettoredeiparichevienetornatoalchiamantefacendoinmodo
chequest'ultimosiaaconoscenzadeirisultatidell'elaborazioneeciilmodocorrettodirisolvere
ilproblematrattandosidiununicovaloredacalcolare,tuttaviaperevidenziarelediversitconil
casodelpassaggio diparametri perriferimento siproponeil confronto conlafunzione scritta
utilizzandoilpassaggioperriferimento:
Valoreritornato
vector<int> selez::estraiPari(vector<int>
num)
{
vector<int> numpari;
vector<int>::iterator it;
Passaggioperriferimento
void selez::estraiPari(vector<int> num,
vector<int>& numpari)
{
vector<int>::iterator it;
for(it=num.begin();it!=num.end();it++){
if(!(*it%2))
numpari.push_back(*it);
}
return numpari;
}
for(it=num.begin();it!=num.end();it++){
if(!(*it%2))
numpari.push_back(*it);
}
}
Nellafunzioneadestrastatoaggiuntounparametropassatoperriferimento(evidenziatoda &)che
conterrilvettoredeipari.Lafunzioneritornaun voideoperasunumparicheunnomelocale
ma fa riferimento alla stessa zona di memoria del parametro che viene passato all'atto della
chiamata.Nonesistelarigadicodicecon returnperchilvalorecalcolatoginelparametroe,
inoltre,lafunzionetornauntipoindefinito(void).
Anche se la funzione, dal punto di vista del risultato ottenuto, potrebbe essere scritta in uno
qualsiasideiduemodipresentati,ilformalismocorretto ilprimoessendociunsolovaloreda
comunicare con l'esterno(la funzione haunsolooutput). Ilsecondoformalismo (passaggi per
riferimentoetipotornatovoid)siadottersoloinpresenzadipioutputdafornireodinessuno.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.74
5 Strutture e tabelle
5.1 Le strutture
Unastrutturauninsiemedivariabilidiunoopitipi,raggruppatedaunnomeincomune.Anchei
vettorisonocollezionidivariabilicomelestrutture,solocheunvettorepuconteneresolovariabili
dellostessotipo,mentrelevariabilicontenuteinunastrutturanondevonoesserenecessariamente
dellostessotipo.
Le strutture del linguaggio C++ coincidono con quelli che in Informatica sono comunemente
definiti record.Ilraggruppamentosottounnomecomunepermettedirappresentare,tramite le
strutture,entitlogicheincuilevariabilicompresenellastrutturarappresentanogliattributiditali
entit.
Peresempioconunastrutturasipurappresentarelentit dipendente icuiattributipotrebbero
essere:reparto,cognome,nome,stipendio. Intalecasoladefinizionepotrebbeessere:
struct dipendente{
string reparto;
string cognome;
string nome;
float stipendio;
};
Lasintassidellinguaggioprevede,dopolaparolachiave struct,unnomecheidentificherla
struttura(il tag dellastruttura).Racchiusenelbloccosonodichiaratelevariabilichefannoparte
dellastruttura(imembridellastruttura).benechiarirecheinquestomodosidefiniscelastruttura
logicadipendente,chedescrivelaspettodellastruttura,enonunpostofisicodoveconservarei
dati.Inpraticasipuconsiderarecomesesifossedefinito,peresempio,comcompostoiltipo
int:cinecessarioperdichiararevariabiliditipoint.
Permostrarel'usoelementarediunastruttura,vienepropostounsempliceprogrammachericeveda
inputidatidiundipendenteemostraidatiricevuti:
#include <iostream>
#include <string>
using namespace std;
namespace azienda{
struct dipendente{
string reparto;
string cognome;
string nome;
float stipendio;
};
}
int main()
{
azienda::dipendente dip1;
/*1*/
/*2*/
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.75
/*3*/
/*3*/
/*3*/
/*3*/
<<
<<
<<
<<
<<
/*3*/
/*3*/
/*3*/
/*3*/
return 0;
}
Lastrutturavienedefinita,nella1,nellospaziodinomiazienda.
Nella 2 viene dichiarata una variabile del tipo dipendente definito nello spazio azienda. La
variabiledichiarataavrimembridefinitinellastruttura:cisar,peresempio,un cognome peril
dipendentedip1.
L'accessoaimembridellastruttura,comeevidenziatonelle 3,avvieneutilizzandol'operatoredi
appartenenza(ilpunto).Inquestomodosipudistinguerese,peresempio,ilcognomesiriferisce
al dipendente dip1 o al dipendente dip2, se fosse stata dichiarata un'altra variabile di tipo
dipendenteconquelnome.
Siagliinputcheglioutputvengonoeffettuatisuimembridellastrutturapoich glioperatoridi
inserimentoediestrazionesonodefiniti,perdefault,peritipielementari.Sivedrinseguitocome
ridefiniretalioperatoriinmododapotersiapplicare,peresempio,adunastrutturacomesefosseun
tipoelementare.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.76
#include <string>
#include <vector>
using namespace std;
namespace ditta{
struct dip{
string reparto;
string cognome;
string nome;
float stipendio;
};
/*1*/
vector<dip> insertDip();
void insertCogNom(string&, string&);
vector<dip>::iterator cerca(vector<dip>&, string, string);
/*2*/
}
int main()
{
vector<ditta::dip> libropaga; // elenco dipendenti
string cogncerca,nomcerca; // cognome e nome da cercare
vector<ditta::dip>::iterator pos; // iter dip
/*3*/
/*4*/
/*4*/
// Ricerca dip
pos = ditta::cerca(libropaga,cogncerca,nomcerca);
/*5*/
/*6*/
/*7*/
/*7*/
return 0;
}
In1definitounospaziodinomiincuidichiararelastrutturaconidatidiinteressedeldipendente
eiprototipidellefunzioni.
Nella3vienedichiaratounvettoreditipodip,tipoasuavoltadefinitoinditta.
Nelle 4sichiamanolefunzioniperl'inputdellatabelladeidipendentiedeidatidellapersonada
cercare.
Nella 5 sirichiamalafunzionediricercadeldipendente.Lafunzionerestituisceuniteratoreche
puntaalrecorddeldipendenteall'internodellatabella.Comesinotadalla 2,allafunzioneviene
passatounriferimentoallatabelladeidipendenti.Inrealtperlafunzionediricercalatabellaun
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.77
inputequindisarebbesufficientepassareilparametropervalore,maprevistoilritornodiun
iteratoreeselatabellafossericopiata inun'altraposizione(passaggiopervalore),ilpuntatore
indicherebbelaposizionenelvettorelocale:informazioneinutilizzabiledalchiamante.
Nelle 7 si stampano le informazioni richieste se il dipendente esiste ( 6). La deferenziazione
dell'iteratore(*pos)produrrebbeunoggettoditipodipchenonpuessereusatoconl'operatoredi
inserimento:necessariodeferenziareisingolicomponentiutilizzandol'operatorefreccia(->).
Percompletareilprogrammasiriportanoledefinizionidellefunzioni:
// Inserimento dipendenti
vector<ditta::dip> ditta::insertDip()
{
vector<ditta::dip> d;
ditta::dip tempdip;
int i;
cout << "Inserimento dati dei dipendenti" << endl;
for(i=0;;i++){
cout << "\nDip " << i << endl;
cout << "Reparto ";
getline(cin,tempdip.reparto);
/*1*/
if(tempdip.reparto.empty())
break;
/*2*/
/*3*/
/*3*/
/*3*/
/*4*/
/*5*/
}
return d;
}
// Cognome e nome dip da cercare
void ditta::insertCogNom(string& c,string& n)
{
cout << "Dipendente da cercare" << endl
<< "Cognome ";
getline(cin,c);
cout << "Nome ";
getline(cin,n);
}
// Ricerca
vector<ditta::dip>::iterator
ditta::cerca(vector<ditta::dip>& d,string c,string n)
{
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.78
vector<ditta::dip>::iterator it, p;
p=d.end();
/*6*/
for(it=d.begin();it!=d.end();it++){
if(it->cognome==c && it->nome==n){
p=it;
break;
}
}
/*7*/
/*8*/
/*9*/
return p;
}
http://ennebi.solira.org
/*1*/
/*1*/
/*2*/
/*3*/
/*4*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.79
return 0;
}
...
// Inserimento reparto da selezionare
string ditta::insertRep()
{
string r;
cout << "Reparto da selezionare" << endl;
getline(cin,r);
return r;
}
// Seleziona in base al reparto
vector<ditta::dip>
ditta::selezione(vector<ditta::dip> d1,string r)
{
vector<ditta::dip> d2;
vector<ditta::dip>::iterator it;
for(it=d1.begin();it!=d1.end();it++){
if(it->reparto==r)
d2.push_back(*it);
}
/*5*/
/*6*/
return d2;
}
// Stampa dipendenti del reparto cercato
void ditta::stampa(vector<ditta::dip> d2)
{
vector<ditta::dip>::iterator it;
if(!d2.empty()){
cout << "\nDipendenti che lavorano nel reparto" << endl;
for(it=d2.begin();it<d2.end();it++)
cout << it->cognome
<< " "
<< it->nome
<< " "
<< it->stipendio << endl;
}
else
cout << "Non risultano dipendenti nel reparto" << endl;
/*7*/
/*8*/
/*8*/
/*8*/
Nello spazio di nomi ditta la funzione insertCogNom sostituita dalla insertRep, cerca
sostituita da selezione e viene aggiunta la funzione stampa per la stampa della tabella dei
dipendenti delreparto.Nelledichiarazioni divariabili della 1 siaggiungono: unnuovovettore
dipRepelastringarepcerca.
Lachiamataallafunzionediinserimentodelreparto,della2,ritornaundatoditipostring.
La3,rispettoalprogrammaprecedentedoveusataunafunzionediricerca,modificatainmodo
dachiamarelanuovafunzione.In 4 sistampal'elencodeidipendentidelrepartoprodottodalla
funzionerichiamatainprecedenza(3).
Lafunzionediselezione,dopoaververificatonella 5 cheilreparto quellointeressato,invia
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.80
l'elementoalnuovovettore(6):unelementoditipodip.
Selaselezionenonvuota(7)le8stampano,perognielemento,isingolimembridellastruttura
nonpotendosiapplicare,comegiosservato,l'operatorediinserimentoaoggettiditipodip.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.81
6 Il paradigma ad oggetti
6.1 Estensione delle strutture: le classi
Imembri diunastruttura possonoancheesserefunzionioltre chedati.Perunabiblioteca che
effettuaoperazionidiprestitoaisoci,unlibro,peresempio,nonsolouninsiemediattributima
ancheunacosachepuessereprestata:
namespace biblioteca{
struct libro {
string titolo;
string autore;
string editore;
float prezzo;
bool presente;
bool prestitoOk()
{
bool esito=false;
if (presente){
presente
= false;
esito = true;
};
return esito;
};
/*1*/
/*2*/
};
}
Nella1vienedefinitalafunzionepereffettuareilprestitodiunlibro:talefunzionesettaa falseil
valoredelmembropresenteeritornaunvalorelogicosulrisultatodelloperazioneeffettuata(seil
librogistatoprestatoloperazionenonpuavereluogo).Lafunzioneinseritanellastrutturaper
intenderecheunaproprietdistintivadellibro,coscomeiltitoloolautore.L'accessoalmembro
presente,nella2,nonnecessitadell'operatore::perchsitrovanellastessonamespacecoscome
dell'operatorepunto,poichvieneeffettuatodentrolastrutturastessa.Lafunzione inseritaed
elaboradatidellastrutturaenonrichiede cheidati,seappartenentiallastessastruttura,siano
passaticomeparametri.
...
biblioteca::libro lib1;
...
cout << "Inserire titolo :";
getline(cin,lib1.titolo);
cout << "Titolo :" << lib1.titolo << endl;
if(!lib1.prestitoOk())
cout << "Libro gia\' prestato" << endl;
else
cout << "Prestito effettuato" << endl;
...
/*1*/
/*2*/
/*3*/
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.82
Leclassisonounodeglielementifondamentalidellaprogrammazioneorientataaglioggetti(OOP).
Unaclasseuntipodidatodefinitodallutentechehaunproprioinsiemedidatiedifunzioni
(AbstractDataType).
// esempio non funzionante !!
class libro {
string titolo;
string autore;
string editore;
float prezzo;
bool presente;
bool prestitoOk()
{
bool esito=false;
if (presente){
presente
= false;
esito = true;
};
return esito;
};
};
Inquestomodovienedefinitalaclasselibro.Untipoconattributiecomportamenti(lefunzioni
definitenellaclasse).
Ladefinizionedi libro,trannecheperlasostituzionedellaparolachiave struct conlaparola
chiaveclass,sembraidenticaaquellaadottataprecedentemente,solocheora,comedaltraparte
messoinevidenzadallarigadicommento,cunadifferenzasostanziale:ilcompilatoresesitenta
diaccedereadunattributodelloggetto,fornisceunerrorecheevidenzialanonvisibilitdello
stesso.Cidovutoalleregoledivisibilitdeivarielementinelleclassi:se,infatti,nonsispecifica
altrimenti,lavisibilitlimitatasoloallinternodellaclasse,peresempiolafunzione prestitoOk
puaccedereapresentemaadessanonsipuaccederecomecomponentediunavariabileditipo
libro.
Ingeneraleinunaclassepossonoesserespecificatitrelivellidivisibilit:
class libro {
public:
...
protected:
...
private:
...
};
Nellasezionepublicsispecificanoimembriaccessibiliaglialtrimembridellaclasse,alleistanze
dellaclasseealleclassidiscendenti(quellechesidefinisconoapartireda libroecheneereditano
lepropriet).
Nellasezioneprotectedsispecificanoimembriaccessibiliaglielementidellaclasse,alleclassi
discendentimanonalleistanzedellaclasse.ladefinizioneassuntaperdefaultedquindiquesto
ilmotivoperchnellesempiopropostononeranovisibiliivarimembri.Nellestruttureinvecela
definizionedidefault public edquestochehagarantitol'accessoaimembrinegliesempi
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.83
riportatiinprecedenza.
Nellasezione private sispecificanoimembrichedevonoessereaccessibili solamente aglialtri
membridellastessaclasse.
Lesezionipossonoesseredisposteinmodoqualsiasi,figurarepivoltenelladefinizione della
classeenonobbligatorioinserirletutte.
Lapossibilitdidefinirediversilivellidimascheramentodellinformazione(datahiding)una
delle caratteristiche fondamentali della programmazione ad oggetti. Aiuta, infatti, a creare una
interfacciadellaclasseche,nascondendolimplementazione,mostraloggettodefinitoinmaniera
daevidenziarneleproprieteicomportamenti.Mettereassiemeinunaclasselepropriet(attributi)
elefunzioni(metodi)unaltradellecaratteristichefondamentalidellaOOP:lincapsulamento.In
questo modo ogni oggetto della classe non ha solo caratteristiche ma anche comportamenti
esattamentecomenellarealt:sesigestisceunabiblioteca,unlibro,nonsolounoggettocheha,
peresempio,iltitoloPinocchiomaancheoggettodiprestitoerestituzione.Unaclassecontiene
idatietuttoilnecessarioperusareidati;ilprogrammacheusalaclassenonhabisognodisapere
comfattamasoltantohanecessitdisaperequalesonoleproceduredefinitenellaclasseecome
sirichiamano.
NellaOOP,inragionedelmascheramentodeidati,questinormalmentevengonodichiaratinella
sezioneprotected(sceltaeffettuatainquestiappuntiperilmotivodirenderedisponibiliidatialle
classidiscendenti),onellasezioneprivate,esiaccedeadessiutilizzandoimetodipresentinella
parte public.Questa,sipudire,unaregolagenerale:linterfacciadellaclassechemettea
disposizioneglistrumentiperaccedereaidati.Intalmodopuessere,pervarimotivi,modificatala
strutturainternadeidatidellaclassesenzachecambilusodeglioggettidellaclasse.
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.84
(Unified Modeling Language), progettato per usi diversi fra cui anche quello di
rappresentareleclassiechenerendeimmediatamentevisibililecaratteristiche:
Oltreallapartesovrastantedovehasedeilnomedellaclasse,ilboxrimanentesuddivisoin
dueparti:nellapartesuperioresonoriportatigliattributienellaparteinferioreimetodi.La
visibilit evidenziata con un segno che precede il nome (+ equivale a public, # a
protected, - a private).Inomidellevariabilisonoseguitidaltipo,imetodi(congli
eventualiparametriscrittiinmododaseguirelestesseconvenzionidegliattributi)daltipo
ritornato.
Ilcodicedellaclassefattura,inseritonelnamespaceelabfat,sar:
namespace elabfat{
class fattura{
public:
fattura(): totale(0.0) {};
void aggiorna(float t){totale +=t;};
friend ostream& operator<<(ostream&, const fattura&);
protected:
float totale;
};
ostream& operator<<(ostream& output, const fattura& f)
{
output << "Totale fattura: " << f.totale << endl;
return output;
};
};
/*1*/
/*2*/
/*3*/
/*4*/
/*5*/
Laclassehasolounavariabiledefinitanellaparteprotetta(4).
Ilprimometododefinitoin1particolare:ilcostruttore.Sitrattadiunmetodochehalo
stessonomedellaclasseechenonrestituiscealcunvalorenemmeno void.Ilmetodonon
puessererichiamatoesplicitamente,mavienerichiamatoinautomaticoquandosiistanzia
unoggettodellaclasse.Inpraticaquandosidefinisceunavariabileditipo fatturaviene
inizializzata la variabile privata: definire una nuova fattura vuol dire, in automatico,
azzerarneiltotale.Ilcostruttorenondeveessereperforzadefinito.Accantoalcostruttore
potrebbeesserenecessariodefinireancheun distruttore:metodochevienerichiamatoin
automaticoquandocessalavisibilitdell'oggetto.Ildistruttorequandoc'halostessonome
dellaclassecomeilcostruttoremaprecedutoda~.Secifosseperlaclasse fatturaavrebbe
nome ~fattura(). Il distruttore diventa necessario, per esempio, quando c' una
allocazionedinamicadellamemoriaebisognaliberareerecuperarelamemoriaoccupata.
Siaalcostruttorechealdistruttorepossonoesserepassatiparametri.
Nelcostruttoreusocomune,invecedellasolitasintassi,inizializzare,quandositrattadi
variabiliditipielementari,ivaloribaseutilizzandolasintassidella 1.Secifosserostatepi
variabili,sarebberostateseparatedallavirgola.
Ilmetodo 2 aggiornailtotaledellafatturaconilparametropassato.Ladefinizionedella
funzione, composta daununicaistruzione riportata direttamente (funzioni inline).La
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.85
differenzafralefunzioniinlineelealtreincuivienedistintoilprototipodalladefinizione
consistenelmodoconcuivengonotrattatedalcompilatore.Lefunzioniinlinevengono
tradottecome macroistruzioni:ilcodicevieneinseritotuttelevoltechelafunzioneviene
richiamata. La definizione codificata a parte comporta invece la presenza di un unico
codice:tuttelevoltechelafunzionerichiamatavieneeffettuatounsaltoall'unicocodice
esistente.Indefinitivalefunzioniinlinevengonoutilizzatesecomprendonopococodice
(sonopivelocimaoccupanospazio:trechiamate,peres.,equivalgonoatreduplicazionidi
codice),lefunzionicondefinizioneapartequandonefannoparteparecchierighedicodice.
La 3 ridefiniscel'operatore << peroggettidellaclasse fattura.L'operatore,coscome
definitonellalibreriaiostreamecomealtrevoltefattonotare,consentel'outputdistringhe
edivariabiliditipielementari.LaridefinizioneunacaratteristicaimportantedellaOOP
(overloading) che permette la personalizzazione, in questo caso, dell'operatore di
inserimentoinmodochepossaessereusatoperoggettideltipo fattura.Dalpuntodivista
sintatticonecessariopassareallafunzioneunparametroditipo ostream eunodeltipo
l'oggetto per il quale si scrive il codice per la ridefinizione. La parola chiave friend
permetteallafunzione,anchesenonunmetododellaclasse,l'accessoallaparteprivatao
protetta.
Ilcodicedellaridefinizionedell'operatorediinserimento( 5)istruiscesucomedeveessere
applicatotaleoperatoreaglioggettidellaclasse:tuttelevoltechevieneusatol'operatoredi
inserimentoverrannoeseguitequesteoperazioni.
Larigaindividuatadallaquantitvendutaedalprezzounitario.Operazioni:generazionedi
unanuovariga,calcolototaleriga.
Ilcodicesar:
namespace elabfat{
class riga{
public:
riga(): numriga(0) {};
bool nuovaRiga();
float totRiga();
protected:
int numriga;
int qv;
float pu;
};
/*1*/
/*2*/
http://ennebi.solira.org
/*3*/
/*4*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.86
/*5*/
return OK;
};
// metodo per il calcolo del totale della riga
float riga::totRiga()
{
float tr;
tr = qv*pu;
return tr;
};
};
Anche la definizione di questa classe contenuta (1) nello stesso namespace di quella
precedente:ilnamespacevieneespansoinmododacomprenderelenuovedefinizioni.
Il metodo 2 (costruttore) inizializza una variabile che conter le righe che verranno
consideratefacentipartedellafattura.
Ilmetodo 3 faesistereunanuovariga(4)se(5)entrambiivaloridiquantitvendutae
prezzounitariosonoaccettabili.
Ladefinizionedeimetodiutilizzal'operatoredivisibilit::perl'accessoaglielementidella
classe.
A questo punto la definizione delle classi, in conseguenza delle richieste del programma da
sviluppare,completa:ilcodicediogniclassesiregistrainunfile.Ilfilec_fatturacontienela
definizionedellaclassefattura,ilfilec_rigaquellodellaclasseriga.Ifilesarannoinclusinel
sorgentedelprogrammachedovrutilizzareleclassiinessedefinite.
Primadiprocedereoltreopportunorispondereadunaeventualeosservazionesullamancanza,
nelladefinizionedellaclasse,diimplementazionedieventualialtrimetodiperelaborazionidiverse
chepotrebberoesserenecessarioeffettuare.Inquesticasi,infatti,nonpossibileconoscereidati
inseritichesonoconservatiinvariabiliprivate.
Intantosipuosservareche,perlosviluppodelprogrammaproposto,nonnecessarioalcunaltro
metodo.Inoltreilnonprevederealcunmetodo,probabilmenteutileperunutilizzofuturo,einaltri
contesti,dellaclasse,nontogliegeneralit;sipossonoimplementarenuovimetodio,addirittura,
modificarequelliesistentiutilizzandol'ereditariet,coscomesitratterinseguito.
Ilmain,inpratica,sidovroccuparesoltantodifareinteragireoggettidellaclasserigaconoggetti
dellaclassefatturacomeancherisultaevidentedaldiagrammaUML:
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.87
Ilsimbolodelrombopienodallafatturaallarigasileggecome: compostoda.Nell'esempio
quindievidenziatocheunoggettodellaclassefatturacompostadaunoopioggettidellaclasse
riga.Lerighehannosensosefannopartediunafattura.
#include <iostream>
#include c_fattura
#include c_riga
using namespace std;
int main()
{
elabfat::riga r;
elabfat::fattura f;
/*1*/
/*1*/
/*2*/
/*2*/
/*3*/
/*4*/
// stampa fattura
cout << f;
/*5*/
return 0;
}
Le1permettonodiincludereledefinizionidelleclassi.Inomideifilechecontengonoledefinizioni
sonoracchiusifracaratteredoppioapicealtoadindicarecheifilesitrovanonellostessoposto
fisicodovesalvatoilmain.Leparentesiangolari(<>)racchiudonoinomideifilechesitrovano
nelledirectorydiincludeusatidalcompilatoreedefinitidurantel'installazionedellostesso.
Nelle2sidichiaranodueoggettiappartenenti,rispettivamente,alleclassirigaefattura.
L'interazione fra i due oggetti si riduce a: controllare se c' ancora una riga da elaborare ( 3),
aggiornareiltotaledellafatturaconiltotaledellariga(4).
lastampadeltotaledellafattura(5)terminailprogramma.
L'applicazionedelparadigmadellaOOPhaportato,oltreavantaggirelativialriutilizzodelcodice
o maggiore facilit di individuazione di errori, notevoli semplificazioni nella scrittura del
programma:primacisioccupa solamente delleelaborazionirelativeaisingolidaticoinvoltinel
problema(nelcasopropostolafatturaelariga).Definiteleclassiilprogrammacheutilizzaoggetti
delleclassisilimitasoloall'interazionefraglistessi:ognioggetto,inquantoistanzadiunaclasse,
sagicomecomportarsi.
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.88
/*1*/
/*1*/
#include <iostream>
#include <string>
using namespace std;
namespace biblioteca{
struct datilib{
string codice;
string argomento;
string titolo;
string autore;
};
class libro{
public:
libro(): disponibile(true){};
friend ostream& operator<<(ostream&, const libro&);
bool newLibro();
string getCodice() const {return lib.codice;};
http://ennebi.solira.org
/*2*/
/*3*/
/*4*/
/*5*/
/*6*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.89
/*6*/
/*7*/
/*7*/
/*2*/
/*2*/
/*8*/
/*9*/
/*10*/
/*10*/
/*10*/
return esito;
};
// Operazioni di prestito
bool libro::prestato()
{
bool prestatoOk=false;
if (disponibile){
disponibile = false;
prestatoOk = true;
};
/*11*/
/*12*/
return prestatoOk;
}
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.90
bool libro::restituito()
{
bool ritornatoOk=false;
if (!disponibile){
disponibile = true;
ritornatoOk = true;
};
/*13*/
/*14*/
return ritornatoOk;
}
};
#endif
/*1*/
Letrerighe1,dueall'iniziodelfiledidefinizionedellaclasse,unaallafine,sonodirettivealpre
compilatore.Capitaspessodiaverenecessitdiincluderepivolte,inpifiledicodice,leclassi
cheservono.Nell'esempiopropostoilfile c_librovieneinclusonelladefinizionedell'altraclasse
c_libreria, che appunto un aggregato di libri, ma anche nel programma di gestione della
bibliotecachenecessitadidefinireoggettidiquellaclasse.Ilcompilatoresitroverebbe,inquesto
caso,unaduplicazionedidefinizionienonpotrebbeassolvereallapropriafunzione.Perevitareil
rischio di duplicati, nei file di intestazioni delle classi, si aggiungono direttive che dicono al
compilatorechesenondefinitaunacertavariabile,nelcasoinesame C_LIBRO,allorasidefinisce
lavariabile(secondariga)esiprosegue.Seinvecelavariabileesiste(ilfilegistatoincluso),si
passaallafinedellacondizione(ultimariga),evitandounadefinizioneduplicata.
Idatidellibrosonodefinitinellastruttura2.Unavariabilediquestotipo,identificanteillibroda
gestire, definita nella sezione protected della classe assieme alla variabile booleana che
indicherladisponibilitdellibroalprestito.
Laclassehauncostruttore(3)cheinizializzailvaloredidisponibilitdellibro.Unnuovolibro
registratosubitodisponibileperoperazionidiprestito.Vieneinoltre( 4)ridefinitol'operatoredi
inserimentoperunoggettodellaclasse.
Ilmetodo5restituisceinformazionisull'avvenutagenerazionediunnuovooggettodellaclasse:se
ilcodiceidentificativononvieneimmesso(8)ilnuovooggettononvienegenerato(9),incaso
contrarioillibropuesistere(10).
Iduemetodi 6,codificaticomefunzioniinline,restituisconoidatinecessariperleelaborazioni
richieste(siricordachenecessarioutilizzaredeimetodipubbliciperchglioggettinonhanno
accessoallevariabiliprotected).Ilqualificatoreconstallafinedelladichiarazioneindicailfatto
cheiduemetodinonmodificanoidatidellaclasse.Idatisonoinfattiaccessibiliinmodoimplicito,
senzanecessitdipassaggiodiparametri,aimetodidellaclassemasesivuoleesseresicuricheun
metodo, che non debba modificare gli attributi della classe, non lo faccia anche per errore,
opportunoaggiungereilqualificatore.Inquestocasountentativoerratodimodificadegliattributi
comporterunmessaggiodierroredapartedelcompilatore.
Imetodi7effettuanoleduepossibilioperazionirichiedibilisullibro.Formalmentelacodificadei
duemetodiidentica:siinterrogaladisponibilitdellibroperl'operazionedaeffettuare(11e13)
e,sepossibile,siprocede(12 e 14).L'unicadifferenzafraiduemetodiconsistenelfattoche
l'operazionediprestitorichiedeladisponibilitdellibro(11),larestituzionechesitrattidiunlibro
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.91
prestato(13).
Dalladefinizionedelproblemasideduceunaclasse libreriailcuicodicesarcontenutonelfile
c_libreria.Adifferenza della precedente sitratta diuna classeaggregato:uncontenitore di
oggettiditipolibroacuisirichiedonodeterminatefunzionalit.Leoperazioniprevisteriguardano
lapossibilitdiaggiungereunnuovolibro,rintracciareillibroassociatoaduncodicespecificato,
aggiornareidatidellibroinseguitoadunaoperazionediprestitoorestituzione,ottenerel'elenco
deilibriindotazione,selezionareilibriperargomento:
#ifndef C_LIBRERIA
#define C_LIBRERIA
#include <string>
#include <vector>
using namespace std;
#include "c_libro"
namespace biblioteca{
class libreria{
public:
libreria() {it=elenco.end();};
bool FindCodice(string);
bool AddLibro(libro);
libro getLibro() const {return *it;};
bool aggiorna(libro);
bool IsElenco() const {return (!elenco.empty());};
void IniziaElenco(){it=elenco.begin();};
bool getNextLibro(libro&);
libreria SelezArg(string) const;
protected:
vector<libro> elenco;
vector<libro>::iterator it;
};
/*0*/
/*1*/
/*2*/
/*3*/
/*4*/
/*5*/
/*6*/
/*7*/
/*8*/
/*9*/
/*9*/
http://ennebi.solira.org
/*10*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.92
/*11*/
/*12*/
/*13*/
return trovato;
};
// aggiunge un libro alla libreria
bool libreria::AddLibro (libro l)
{
bool aggiunto=true;
/*14*/
if(FindCodice(l.getCodice()))
aggiunto = false;
else
elenco.push_back(l);
/*15*/
return aggiunto;
};
// aggiorna i dati del libro attuale
bool libreria::aggiorna(libro l)
{
bool aggOK=true;
if(it!=elenco.end())
*it=l;
else
aggOK=false;
/*16*/
/*17*/
return aggOK;
};
// passa al prossimo libro
bool libreria::getNextLibro(libro& l)
{
bool esiste=false;
if(it!=elenco.end()){
l = *it;
esiste = true;
it++;
}
/*18*/
/*19*/
/*20*/
return esiste;
};
// seleziona libri per argomento
libreria libreria::SelezArg (string a) const
{
libreria sel;
http://ennebi.solira.org
/*21*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.93
vector<libro>::const_iterator its;
for(its=elenco.begin();its!=elenco.end();its++)
if(its->getArgomento()==a)
sel.AddLibro(*its);
/*22*/
return sel;
};
};
#endif
Ilcontenitoredilibri,comesideducedalle9implementatoutilizzandounvettore.Fraidatidella
classedefinitopureuniteratoreperpuntarealsingololibrocheinteresserleelaborazioni.Il
contenitorenonunsemplicevettoremaprevedeimetodiperlagestionedellalibreria.Laclasse
hauncostruttore(0)cheinizializzal'iteratore.
IlmetodoFindCodice(1)sioccupadifornireinformazionisull'esistenza,nellalibreria,delcodice
diunlibro.Questainformazione utileperl'inserimentodiunnuovolibro( 2):seilcodice
univocononpossonoesserciduecodiciugualiequindi,primadiaccettare unnuovocodice
necessarioverificarechenonesistagi.Inoltrelabibliotecadevefornirelafunzionalitdiricercadi
unlibropercodice.La(3)restituisceillibroassociatoalvaloreattualedell'iteratore.
ilmetodo aggiorna (4)registraleoperazioni effettuate suunlibro(prestito/restituzione) nella
libreria.
Imetodi5,6,e7sonofunzionalitutiliperlascansionedellalibreria.Rispettivamente:saperese
esisteunelenco(5),iniziarel'elenco(6),accederealprossimolibrodell'elenco( 7).Internamente
allaclassevieneutilizzatounvettoreequindiparecchimetodidiquestogrupposisonopotuti
scriverecomefunzioniinlineperchcisiappoggiaaimetodidellaclassevector.
Il metodo SelezArg (8) costruisce un nuovo elenco con i libri dell'argomento passato come
parametro.Ilvalorediritornounoggettodellastessaclasseequindidotatodeimetodidella
classe:peresempioperscorrerel'elenco.Ilmetodoavrebbepotutoaverecomevalorediritornoun
vectorditipolibroma,inquestocaso,sisarebbetrattatodiuninsiemedidatienondilibridella
bibliotecadotatideimetodiappenadescritti.
Tuttiimetodichenonmodificanoinalcunmodoidatidellaclassesonodichiaraticonst.
L'implementazionedelmetodoFindCodice(10)effettuaunascansionesequenzialedelvettore(11)
eseilcodicedellibrohalostessovaloredelcodicepassatocomeparametro( 12)simodificail
valorelogicodiritorno(13),siesceforzatamentedalcicloe,intalmodo,ilvaloredell'iteratore
permettel'accessoall'elementoconquelcodice.
ilmetodoperl'inserimentodiunlibroinelenco( 14)neverificalapossibilit:seilcodiceassociato
allibroesiste(15)nonsiprocede.
Ilmetodoperl'aggiornamentodeidatidiunlibro( 16)sostituisceillibropuntatodalvaloreattuale
dell'iteratore definito nella classe. Il controllo in 17 serve solo nel caso il metodo sia stato
richiamatoerroneamente.
IlmetodogetNextLibro(18)restituisce,nelparametro,illibropuntatoattualmenteseesiste( 19)e
aggiornasuccessivamente(20)l'iteratorealprossimolibroinmododarenderlodisponibileperla
prossimalettura.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.94
Ilmetodo21,dalpuntodivistadell'algoritmo,unaoperazionediselezionecommentataanchein
altri esempi e non necessita di ulteriori commenti. necessario aggiungere invece qualcosa
riguardante la dichiarazione const_iterator. Il metodo di tipo const perch non deve
modificareidatidellaclasse,mal'usodegliiteratoripermetterebbetalimodificheeilcompilatore,
incasodidichiarazionedivariabileditipo iterator,segnalerebbeerrorenellariga 22 perch
l'iteratorescorreilvettorepermettendolamodificadeisingolielementi.Uniteratoredefinitocome
const_iteratornonconsentelamodificadell'elemento.
Ilrombovuotodallapartedellaclasse libreriasileggecome:uninsiemedi.Unoggettodella
classe libreria un insieme di uno o pi oggetti della classe libro. A differenza
dell'aggregazione fattura-riga diunesempioprecedenteindicataconilrombopieno,quigli
oggettidellaclasse libro possonoesistereanchesenzafarpartediunalibreria,lerigheinvece
esistevanoinquantofacentipartidiunafatturaelacancellazionediunafatturaavrebbecomportato
lacancellazionedellerighechelacomponevano.
#include <iostream>
using namespace std;
#include "c_libro"
#include "c_libreria"
// prototipi
void
void
void
void
void
void
InsertLibri(biblioteca::libreria&);
VisLibri(biblioteca::libreria);
VisLibroCod(biblioteca::libreria);
SelezPerArg(biblioteca::libreria);
Prestito(biblioteca::libreria&);
Restituzione(biblioteca::libreria&);
int main()
{
biblioteca::libreria biblio;
int tipoOp;
http://ennebi.solira.org
/*1*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.95
for(;;){
cout << "Gestione Biblioteca" << endl;
cout << "1 - Inserisci Libri" << endl;
cout << "2 - Visualizza Libri" << endl;
cout << "3 - Cerca Libro per Codice" << endl;
cout << "4 - Seleziona per Argomento" << endl;
cout << "5 - Prestito" << endl;
cout << "6 - Restituzione" << endl;
cout << "0 - Fine" << endl;
cout << "Operazione? ";
cin >> tipoOp;
cin.ignore();
/*2*/
if(!tipoOp) break;
/*3*/
switch(tipoOp){
case 1:
InsertLibri(biblio);
break;
case 2:
VisLibri(biblio);
break;
case 3:
VisLibroCod(biblio);
break;
case 4:
SelezPerArg(biblio);
break;
case 5:
Prestito(biblio);
break;
case 6:
Restituzione(biblio);
break;
default:
cout << "Scelta non ammessa" << endl;
};
/*4*/
/*4*/
/*4*/
/*4*/
};
return 0;
}
Ilmainpucomprendereladichiarazionedellalibreria(1)chevienepassatacomeparametroalle
variefunzionidigestioneassociateallasceltadell'operatore( 4)erichiamateall'internodiunciclo
(2)chetermina(3)conl'immissionedelvalorenullonellascelta.
// (1) Inserimento libri
void InsertLibri(biblioteca::libreria& el)
{
biblioteca::libro libTemp;
cout << "Inserimento libri Codice vuoto per finire" << endl;
while(libTemp.newLibro()){
if(!el.AddLibro(libTemp))
cout << "Codice duplicato ripetere inserimento" << endl;
http://ennebi.solira.org
/*1*/
/*2*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.96
};
};
Lafunzionediinserimentomentrecisonolibri(1)liinseriscenellalibreria(2).Lasceltadiinviare
allafunzionelalibreriacomeparametroenontornareuntipolibreriadovutaalfattoche,cos,si
possonoinserirenuovilibriinqualsiasimomento.Nelcasosifosseadottatalasoluzioneditornare
untipolibrerialalibreriasarebbestatareinizializzataadognirichiamodellafunzione.
// (2) Visualizza libri
void VisLibri(biblioteca::libreria el)
{
biblioteca::libro temp;
if(el.IsElenco()){
el.IniziaElenco();
cout << "Elenco libri" << endl;
/*1*/
/*2*/
while(el.getNextLibro(temp))
cout << temp;
/*3*/
/*4*/
}
else
cout << "Non ci sono libri che soddisfano criterio" << endl;
};
Lafunzionesioccupadellastampasuvideodell'elencodeilibricontenutinellalibreriapassata
comeparametro:possonoesseretuttiilibri(scelta2)oquellichesoddisfanoadeterminatirequisiti
(scelta4).Sec'unelenco(1),losiinizializza(2)e,mentrecisonolibriinelenco(3),sistampano
leinformazionidellibro(4).
// (3) cerca libro per codice
void VisLibroCod(biblioteca::libreria el)
{
string cod;
cout << "Ricerca libro per codice" << endl;
cout << "Codice (vuoto per finire) ";
getline(cin,cod);
while(!cod.empty()){
if(el.FindCodice(cod))
cout << el.getLibro();
else
cout << "Codice inesistente" << endl;
/*1*/
/*2*/
/*3*/
Finchl'utilizzatoredellafunzionenonintroduceunvalorevuoto( 1),siricercailcodiceeseesiste
unlibroadessoassociato(2)losivisualizza(3).
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.97
/*1*/
/*2*/
};
La selezione per argomento si limita a richiamare il metodo opportuno ( 1) della classe cui
appartienel'oggetto el (libreria)earichiamarelafunzionedivisualizzazione(2)passandogli
comeparametrol'elenco.
// (5) prestito di un libro
void Prestito(biblioteca::libreria& el)
{
string cod;
biblioteca::libro l;
cout << "Codice libro per prestito ";
getline(cin,cod);
if(!el.FindCodice(cod))
cout << "Codice inesistente" << endl;
else{
l=el.getLibro();
cout << l;
/*1*/
/*2*/
/*3*/
};
};
// (6) restituzione di un libro
void Restituzione(biblioteca::libreria& el)
{
string cod;
biblioteca::libro l;
cout << "Codice libro per restituzione ";
getline(cin,cod);
if(!el.FindCodice(cod))
cout << "Codice inesistente" << endl;
else{
http://ennebi.solira.org
/*1*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
l=el.getLibro();
cout << l;
C++:programmazioneedoggettipag.98
/*2*/
/*3*/
};
};
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.99
NeldiagrammaUMLevidenziatodaunafrecciachelaclasselibSociodiscendentedalibro:
dotatadeimetodipubblicidefinitinellaclasseantenatapiquellidefinitioridefinitiinessa.
Ilfilec_libSociocontieneladefinizionedellaclasse:
#ifndef C_LIBSOCIO
#define C_LIBSOCIO
#include <iostream>
#include <string>
using namespace std;
#include "c_libro"
namespace biblioteca{
struct datisoc{
string nome;
string cognome;
string via;
};
/*1*/
/*2*/
/*3*/
/*4*/
/*5*/
/*6*/
/*6*/
/*7*/
http://ennebi.solira.org
/*8*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.100
};
// overloading operatore inserimento
ostream& operator<<(ostream& output, const libSocio& l1)
{
output << static_cast<libro> (l1);
/*9*/
if(!(l1.disponibile)){
/*10*/
output << "Prestato a:" << endl
<< l1.socbib.nome << " | " << l1.socbib.cognome << " | "
<< l1.socbib.via << endl;
}
return output;
};
// Inizializzazione dati socio
libSocio::libSocio()
{
socbib.nome=" ", socbib.cognome=" ", socbib.via=" ";
}
/*5*/
/*11*/
if(libro::prestato()){
cin >> socbib;
prestitoOK=true;
}
return prestitoOK;
/*12*/
/*13*/
}
// Restituzione libro dal socio
bool libSocio::restituito()
{
bool ritornatoOK=false;
if(libro::restituito()){
socbib.nome=" ", socbib.cognome=" ", socbib.via=" ";
ritornatoOK=true;
}
return ritornatoOK;
/*11*/
/*12*/
/*13*/
}
}
#endif
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.101
socio.Ilformalismosintatticoquasiidenticoaquelloutilizzatoperl'overloadingdell'operatoredi
inserimento.Sinotichequi,nelpassaggiodelparametrodell'elementopercuisistaridefinendo
l'operatore,mancaconste,d'altraparte,bisognamodificarneilvalore.Lavariabileditipo istream
(input)prendeilpostodelflussocincoscomeutilizzatosolitamente.
Nella3sievidenzial'iniziodiunagerarchiadiclassi:lanuovaclasse libSocioundiscendentedi
libro eneereditatuttiimetodi.LasintassidelC++prevedel'usodell'operatore : frailnome
attribuito alla classe discendente e quello della classe genitore. Lo specificatore di accesso, il
qualificatore public associatoa libro,assicuracheimetodipubblicidi librosarannopubblici
anche per libSocio. I qualificatori ammessi sono: public, protected, private. Se si fosse
specificatoprivateimetodiereditatisarebberostatipubbliciperlibromanonperlibSocio.
Nellapartepubblicavengonodefinitiimetodispecificidellaclasse( 4),inaggiuntaaquelliereditati
da libro. Una propriet notevole dell'ereditariet quella evidenziata nelle righe 6.La classe
discendente ha la possibilit di ridefinire i metodi ereditati dalla classe base (overloading dei
metodi) per poterli adattare alla propria specificit. Per gli oggetti della classe ridefinito
l'operatorediinserimento(7).
Nellaparteprotecteddellaclassevengonodefinitiinuovidatimembridellanuovaclasse(8)in
aggiuntaaquelliereditatidallaclassegenitrice.
Fra i metodi presente (5) il costruttore che si occupa dell'inizializzazione dei dati del socio.
Nell'esempiopropostoilcostruttoresirendenecessarioperinizializzareidatidelsocioacuistato
effettuatoilprestitoeche,quandosiinserisceunlibronellabiblioteca,ancoranonesiste.
Nellaridefinizionedell'operatorediinserimentoperglioggettidellaclasse,oltreafareriferimento
(10)avariabiliereditatedalibro,presentelariga9cheinpraticafariferimentoall'overloading
dell'operatore peroggetti della classe libro.Ilcastinginpratica sipotrebbetradurreinmodo
discorsivocome: perlaparte libro di libSocio stampacomeginoto,perlapartenuovasi
specificadiseguito(10eseguenti).
Le 11 ridefinisconoduemetodigidefinitinellaclasse libro,inmododaadattarsiallanuova
classe. Tutte le volte che si richiamer uno dei metodi applicati ad un oggetto della classe
libSocio,verrfattoriferimentoatalifunzioni:lenuovedefinizionimascheranoledefinizionedi
prestato()erestituito()ereditatedalibro.Leistruzionidellerighe12ordinanodieseguireil
metodorelativopercomeerastatodefinitoinlibro:questoquelloacuisifariferimentoquando
si dice che una classe discendente una specializzazione della classe base. In aggiunta alle
istruzionichesieseguivanoprima(righe 12)inuovimetodisioccupanodiconservare( 13)gli
opportunivalorinellevariabiliprivatedelsocio.Agliaggiornamentideidatidellibro,cipensail
metodorichiamatonelle12.
LeregoleadottateperladerivazionedilibSociodalibropossonoessereestesealcasogenerale:
LaclasseC2ereditadallaclasseC1quandolaclassefigliaC2unaspecializzazionedella
classepadreC1.librounlibrogenericodellabiblioteca,libSociounlibroalquale
collegatounsocio.
LaclasseC2ereditadallaclasseC1seC2ISA C1(C2unC1).libSociounlibrocon
ulterioriattributi,metodiaggiuntieridefiniti.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.102
esistonosoloduepostidovesifariferimentoadoggettidellaclasse libro:leoperazionidi
prestitoerestituzione.Basta,anchequi,modificarelibroinlibSocio.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.103
InUMLitemplatesiindividuanospecificandosulladestrainaltoilparametro,conilrelativotipo,
utilizzatocomesegnaposto.
// Definizione di una classe modello: libreria
#ifndef C_LIBRERIA3
#define C_LIBRERIA3
#include <string>
#include <vector>
using namespace std;
namespace biblioteca{
template <class T>
class libreria{
public:
libreria() {it=elenco.end();};
bool FindCodice(string);
bool AddLibro(T);
T getLibro() const {return *it;};
bool aggiorna(T);
bool IsElenco() const {return (!elenco.empty());};
void IniziaElenco(){it=elenco.begin();};
bool getNextLibro(T&);
libreria SelezArg(string) const;
protected:
vector<T> elenco;
typename vector<T>::iterator it;
};
/*1*/
/*2*/
/*3*/
/*1*/
/*4*/
/*5*/
return trovato;
};
// aggiunge un libro alla libreria
template <class T>
http://ennebi.solira.org
/*1*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.104
bool libreria<T>::AddLibro (T l)
{
bool aggiunto=true;
if(FindCodice(l.getCodice()))
aggiunto = false;
else
elenco.push_back(l);
/*4*/
/*5*/
return aggiunto;
};
// aggiorna i dati del libro attuale
template <class T>
bool libreria<T>::aggiorna(T l)
{
bool aggOK=true;
/*1*/
/*4*/
if(it!=elenco.end())
*it=l;
else
aggOK=false;
return aggOK;
};
// passa al prossimo libro
template <class T>
bool libreria<T>::getNextLibro(T& l)
{
bool esiste=false;
/*1*/
/*4*/
if(it!=elenco.end()){
l = *it;
esiste = true;
it++;
}
return esiste;
};
// seleziona libri per argomento
template <class T>
libreria<T> libreria<T>::SelezArg (string a) const
{
libreria<T> sel;
typename vector<T>::const_iterator its;
for(its=elenco.begin();its!=elenco.end();its++)
if(its->getArgomento()==a)
sel.AddLibro(*its);
/*1*/
/*4*/
/*3*/
/*5*/
return sel;
};
};
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.105
#endif
Le righe 1 che precedono tutte le definizioni, specificano, appunto, che si tratta di una classe
modello.Fraparentesiangolari(<>)contenutalaparolachiave class e T ilnome,sceltodal
programmatore,peridentificareiltipodiclassetrattato.Sitratta,sostanzialmente,diunsegnaposto
cheverrsostituitodaltipoeffettivoquandolaclassesarutilizzataechepermette,allaclasse
stessa,lapossibilitdiriferirsiadoggettidiversi.La 2definisceunvettorecheconterrelementidi
tipoT.lasintassidelladichiarazionediuniteratoreperunaclassetemplateprevedelospecificatore
typename(3).
Nella definizione dei metodi (4),il nome della classe seguito dalle parentesi angolari con il
segnaposto.
Laclassecontenitorelibreria,percomedefinita,valeperqualsiasitipodioggettipurchdotati
deimetodigetCodiceegetArgomento(5).
/*1*/
// prototipi
void
void
void
void
void
void
InsertLibri(biblioteca::libreria<biblioteca::libSocio>&);
VisLibri(biblioteca::libreria<biblioteca::libSocio>);
VisLibroCod(biblioteca::libreria<biblioteca::libSocio>);
SelezPerArg(biblioteca::libreria<biblioteca::libSocio>);
Prestito(biblioteca::libreria<biblioteca::libSocio>&);
Restituzione(biblioteca::libreria<biblioteca::libSocio>&);
int main()
{
biblioteca::libreria<biblioteca::libSocio> biblio;
...
}
/*2*/
/*2*/
/*2*/
/*2*/
/*2*/
/*2*/
/*2*/
Oltreall'inclusionedeltemplate(1),l'usodellaclassemodellorichiedeiltipodaspecificarenel
segnaposto(2).NelcasoinesamelalibreriagestiroggettiditipolibSocio.
Come sicuramente si sar notato l'inclusione, in molti esempi, della vector, ha permesso di
utilizzarelastrutturavettore.Ognivolta,specificandoiltiponelsegnaposto,sigestitounvettore
distringhe,dilibriecc...Indefinitiva,comeoradovrebbeesserestatochiarito,laclasse vector
definitacomeclassetemplate.
Selabibliotecavolessegestire,utilizzandolestessefunzionalit,leriviste,basterebbeaggiungere
ladefinizionedellanuovaclasseeutilizzareiltemplateinmodocorretto:
#include <iostream>
#include <string>
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.106
/*1*/
/*2*/
/*3*/
Ammessocheilfilec_rivistacontengaladefinizionedellanuovaclasse,la1permettel'usodella
classe.
Nella2sidefinisceunoggettolib1cheuncontenitoredioggettiditipolibSocio,laddovenella
3, invece, gli oggetti sono di tipo rivista. Per il resto i metodi definiti in libreria si
applicherannoaglioggettidiuntipooaquellidiunaltro,asecondasesiinvierilmessaggioa
lib1oalib2.
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.107
/*1*/
struct libro {
string titolo;
string autore;
string editore;
float prezzo;
};
int main()
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.108
{
ofstream datiLib;
libro libtemp;
bool continua=true;
/*2*/
datiLib.open("libri.txt",ios::app);
/*3*/
while(continua){
// disponibilit dati da registrare nel file
// nell'esempio lettura da tastiera
cout << "Titolo :";
getline(cin,libtemp.titolo);
if(libtemp.titolo=="")
break;
cout << "Autore :";
getline(cin,libtemp.autore);
cout << "Editore :";
getline(cin,libtemp.editore);
cout << "Prezzo :";
cin >> libtemp.prezzo;
cin.ignore();
/*4*/
/*5*/
/*4*/
/*4*/
/*4*/
}
datiLib.close();
/*6*/
/*6*/
/*6*/
/*6*/
/*7*/
return 0;
}
L'inclusione 1 rendedisponibileglioggettichepermettonolagestionedeiflussisumemoriedi
massa.
Nella 2 si dichiara una variabile (il nome, ovviamente, a scelta del programmatore) di tipo
ofstream(flussodioutput),laddove,perla3,siassociaadettavariabileilfilesudisco libri.txt.
Ilflussoapertoinmodalit append (ios::app):seilfileesiste,inuoviinserimentivengono
aggiunti in coda, se non esiste, viene creato. Se invece il flusso aperto in modalit output
(ios::out),ilfile,ancheseesistente,vienerigeneratoeidatieventualmentepresentisonopersi.
Le 4 permettonodiinserireidatidatastiera.L'inserimentotermina(5)quandosipreme Invio a
vuoto,inrispostaallarichiestadiinputdeltitolodellibro.
Conle6idativengonoinviatialfileattraversoilflussodatiLib.L'utilizzoidenticoaquellodel
flussocoutchepermettel'invioalvideo.Ladifferenzadatasostanzialmentedalla 3:ilconcetto
astrattodiflussopermetteditrattare,allostessomodo,entitdiverse(tastiera,video,filesudisco).I
singolidatisonomandatialflusso,ognunoracchiusodaunacoppiadicaratteri doppioapice e
separatidavirgole.L'ultimo(ilprezzo)conclusodalcaratteredifinelinea(endl).
Nella 7 siinterromponoicollegamenticonilfileesterno.Ilmetodo close() chiudelostream
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.109
datiLib.Ilmetodoilsimmetricodiopen().
Ancheilprogrammaperlaletturadeidatidalfilenonsidifferenziainmanierasostanzialedaun
qualsiasiprogrammacheleggedatidaunflussolegatoallatastiera:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct libro {
string titolo;
string autore;
string editore;
float prezzo;
};
libro estraeCampi(string);
/*1*/
int main()
{
ifstream datiLib;
libro temp;
string riga;
/*2*/
/*3*/
/*4*/
// estrae campi
temp = estraeCampi(riga);
/*5*/
// utilizzo dati
// nell'esempio stampa su video
cout << temp.titolo << " - " << temp.autore << " - "
<< temp.editore << " - " << temp.prezzo << endl;
/*6*/
};
datiLib.close();
return 0;
}
// Estrae i campi da una riga letta dal file CSV
libro estraeCampi(string r)
{
libro temp;
int pos;
// estrazione campi di tipo stringa
pos = r.find(',');
temp.titolo = r.substr(1,pos-2);
r = r.erase(0,pos+1);
http://ennebi.solira.org
/*7*/
/*8*/
/*9*/
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.110
pos = r.find(',');
temp.autore = r.substr(1,pos-2);
r = r.erase(0,pos+1);
/*7*/
/*8*/
/*9*/
pos = r.find(',');
temp.editore = r.substr(1,pos-2);
r = r.erase(0,pos+1);
/*7*/
/*8*/
/*9*/
// estrazione prezzo
temp.prezzo = stof(r);
/*10*/
return temp;
}
Ilprogrammautilizzaunafunzione(1)perseparareivaricampidallarigalettadalfile.
Nella 2 vienedichiarataunavariabileditipo ifstream (streamdiinput)acuisiassociailfile
libri.txt (3).Inquestocaso,adifferenzadelflussodioutput,nonnecessariospecificarela
modalitdiapertura:inoutputidatisipossonoscrivereinunnuovofileoaccodareadunfile
esistente,ininputsileggonoidatiunodiseguitoall'altroenonesistealtraalternativa.possibile
tuttavia,anchesesuperfluo,specificarelamodalitios::in.
Ilprogramma,sostanzialmente,leggelerigheesistentinelfileCSVfinchpossibile(4),separai
componentidellariga(5)estampaidatidellibro(6).
Lafunzioneperl'estrazionedeisingolidatidellibrodallariga,cercalaposizionedellavirgola( 7),
estraelaquantitdicaratteri,ripulitadaidoppiapiciinizialiefinali,dicuicompostoilsingolo
dato(8)e,persemplificarelaprossimaestrazione,elimina( 9)icaratteriestratticompresidoppi
apicievirgolaseparatrice.
Il dato di tipo numerico ottenuto richiamando la funzione (C++11) stof sulla stringa e
convertendolainfloat(10).
http://ennebi.solira.org
brugaletta.nunzio@gmail.com
prof.NunzioBrugaletta
C++:programmazioneedoggettipag.111
8 Riferimenti bibliografici
Perl'elaborazionediquestiappuntisonostaticonsultatiilibri:
LinguaggioCdiB.KernighaneD.Ritchie.Iltestobasedacuipartireperlaconoscenzadel
linguaggioC.Testodalcuistudioderivalaprimaversionediquestiappunti.
IllinguaggioC++diB.Stroustrup.Iltestobase,operadellosviluppatoredellinguaggio.
C++byDissectiondiI.Pohl.Validissimotestoperl'apprendimentodellinguaggiobasatosu
esempidissezionatielargamentecommentati.Iltestostatoanchepuntodiriferimentoper
leregolediscritturaadottateancheinquestiappunti.
C++ the Complete Reference di H.Schildt e http://www.cplusplus.com. Fonti
inesauribiliacuiattingereperlaconoscenzadituttelecaratteristichedellinguaggiocon
esempiesplicatividiuso.
DataStructuresUsingC++diD.S.MaliksoprattuttoperisuggerimentisuOOD
IlprogrammaStructorizer(rilasciatoconlicenzaGPLesviluppatoinJava,quindi,utilizzabilesotto
qualsiasipiattaformapercuiesisteunaJVM) diaiutonellafaseiniziale della scritturadegli
algoritmi. Permette di inserire facilmente i blocchi del diagramma di NassiSchneiderman e,
principalmente, ne consente la verifica eseguendone le istruzioni passopasso e mostrando, in
seguitoall'esecuzione,l'effettoprodotto:
http://structorizer.fisch.lu/
http://ennebi.solira.org
brugaletta.nunzio@gmail.com