Che materia stai cercando?

Riassunto esame Fondamenti di Informatica, prof. Dragoni, libro consigliato Fondamenti di Programmazione in C++ di Aguilar Appunti scolastici Premium

Riassunto per l'esame di Fondamenti di Informatica, basato su appunti personali e studio autonomo del libro consigliato dal docente Fondamenti di Programmazione in C++ di Luis Joyanes Aguilar, 2a edizione, McGraw-Hill.
Vengono trattati:
- Digitalizzazione dell'informazione (Audio, Video, Testi),
- Basi decimale, Binaria ed Esadecimale,
- Vari tipi di codifica e loro storia,
- Unicode... Vedi di più

Esame di Fondamenti di informatica docente Prof. A. Dragoni

Anteprima

ESTRATTO DOCUMENTO

L'operatore  di  assegnamento  (=)  assegna  il  valore  dell'espressione  alla  sua  destra  a  alla  

variabile  posta  alla  sua  sinistra.  Permette  anche  di  eseguire  assegnamenti  multipli.  

L'operatore  assegnamento  si  può  comporre  anche  con  altri  operatori:  

+=  a+=b  equivale  a  scrivere  a=a+b  

-­=  a-­=b  equivale  a  scrivere  a=a-­b  

*=  a*=b  equivale  a  scrivere  a=a*b  

/=  a/=b  equivale  a  scrivere  a=a/b  

%=  a%=b  equivale  a  scrivere  a=a%b  (resto  della  divisione,  solo  se  variabili  intere)  

 

Operatori  aritmetici  

+  -­  *  /  %  

Operatori  di  incremento  e  decremento  

++  incremento  e  -­-­  decremento,  che  rispettivamente  sommano  e  sottraggono  1  alla  variabile  che  

hanno  come  argomento.  È  corretto  scrivere  ++(++x),  ma  dato  che  l'operatore  di  post  

incremento  restituisce  il  valore  della  variabile,  esso  non  può  essere  scritto  come  (x++)++,  dato  

che  non  si  può  applicare  un  operatore  ad  un  valore  ma  solo  ad  una  variabile.  Se  gli  operatori  ++  

e  -­-­  si  usano  come  prefissi,  l'operazione  di  incremento  o  decremento  si  effettua  prima  

dell'operazione  di  assegnamento,  se  si  usano  come  suffissi  l'assegnamento  si  effettua  prima  

dell'incremento  o  decremento.  

Preincremento  ++x  equivale  a  x+=1  o  x=x+1  restituisce  la  variabile  x  

Postincremento  x++  equivale  a  x+=1  o  x=x+1  restituisce  il  valore  della  variabile  x  

Stessa  cosa  per  il  decremento  -­-­  

 

Operatori  relazionali  

Gli  operatori  relazionali  si  usano  in  espressioni  della  forma  espressione1  operatore_relazionale  

espressione2  dove  espressione1  e  2  sono  espressioni  compatibili  C++.  L'operatore  relazionale  

produce  0  o  1  a  seconda  del  risultato  del  confronto.  

==  (uguale)  

!=  (diverso)  

>  (maggiore)  (o  >=)  

<  (minore)  (o  <=)  

Per  valutare  una  successione  di  disuguaglianze  come  s<z<e  si  deve  utilizzare  la  seguente  

espressione  (s<z)  &&  (z<e)  

 

Operatori  logici  

Detti  anche  booleani  sono:  !  (not),  &&  (and),  ||  (or).  Vale  la  tabella  di  verità  

a    b    a&&b    a||b    !a  

V    V        V              V          F  

V    F        F              V          F  

F    V        F              V          V  

F    F        F                F          V  

Gli  operatori  matematici  hanno  precedenza  sugli  operatori  relazionali  e  gli  operatori  relazionali  

hanno  precedenza  sugli  operatori  logici.  

Gli  operandi  a  sinistra  degli  operatori  logici  vengono  sempre  valutati  per  primi,  se  il  loro  valore  è  

già  sufficiente  a  determinare  il  risultato  l'operando  destro  non  viene  valutato  per  riparmiare  tempo  

della  CPU.  Questa  proprietà  si  dice  valutazione  in  cortocircuito.  

 

Operatori  di  manipolazione  dei  bit  

O  bitwise,  eseguono  operazioni  logiche  sui  bit  degli  operandi.  Si  applicano  soltanto  a  char  e  int.  

&  bit  a  bit  

|  or  inclusivo  bit  a  bit  

^  or  esclusivo  bit  a  bit  (XOR)  (aut-­aut)  

~  complemento  a  1  (inversione  di  tutti  i  bit)  

<<  spostamento  di  tutti  i  bit  verso  sinistra  

>>  spostamento  di  tutti  i  bit  verso  destra  

0&0==0;;  0&1==0;;  1&0==0;;  1&1==1;;  

0|0==0;;  0|1==1;;  1|0==1;;  1|1==1;;  

0^0==0;;  0^1==1;;  1^0==1;;  1^1==0;;  

Gli  operatori  di  traslazione  si  scrivono  nella  forma  valore  <<  numero_di_bit  o  viceversa!  dove  il  

valore  può  essere  di  tipo  int  o  char,  il  numero  di  bit  determina  di  quanti  bit  si  sposterà  il  valore.  

Gli  operatori  bitwise  si  possono  anche  comporre  con  =.  

 

Operatore  condizionale  

 È  un  operatore  ternario  che  restituisce  un  valore  che  dipende  dal  valore  dell'espressione  

booleana  al  primo  membro.  Il  formato  è:  espressione_booleana  ?  se_vera  :  se_falsa  

Si  valuta  un  espressione  booleana,  se  è  true  viene  restituito  il  valore  in  se_vera,  se  false  il  valore  

in  se_falsa.  

 

Operatore  virgola  

Permette  di  combinare  due  o  più  espressioni  che  saranno  valutate  da  sinistra  verso  destra.  

 

Operatore  sizeof()  

Serve  per  conoscere  le  dimensioni  in  byte  di  un  tipo  di  dato  o  variabile.  Facilità  la  portabilità  e  la  

leggibilità  del  codice,  dato  che  tale  operatore  viene  valutato  in  fase  di  compilazione  e  può  variare  

da  macchina  a  macchina.  

 

Conversioni  di  tipo  

Si  può  convertire  un  valore  di  tipo  in  un  valore  di  un  altro  tipo.  Tale  azione  si  dice  casting.  C++  

realizza  molte  conversioni  automaticamente  (conversioni  implicite)  ma  ha  anche  operatori  che  

permettono  al  programmatore  di  impostarle  esplicitamente  (conversioni  esplicite).  

C++  convert  i  valori  quando  si  assegna  un  valore  di  un  tipo  aritmetico  a  una  variabile  di  un  altro  

tipo  aritmetico,  converte  i  valori  quando  si  combinano  tipi  misti  nelle  espressioni,  converte  i  valori  

quando  si  passano  argomenti  alle  funzioni.  

Conversione  implicita  

I  tipo  fondamentali  possono  essere  usati  liberamente  nelle  espressioni  perché  le  conversioni  si  

eseguono  automaticamente.  Gli  operatori  con  tipo  a  precisione  più  bassa  si  convertono  nei  tipi  a  

precisione  più  alta  (promozione  di  tipo).  

Conversioni  aritmetiche  

Assicurano  che  gli  operandi  di  un  operatore  binario  aritmetico  o  logico  si  convertano  ad  un  tipo  

comune  prima  che  si  valuti  l'operatore;;  tale  tipo  sarà  quello  dell  risultato  dell'operazione.  Anche  

qui  avviene  la  promozione  di  tipo  per  gerarchia.  Ad  esempio  i  tipi  più  piccoli  di  int  (char,  unsigned  

int,...)  si  convertono  ad  int,  bool  si  converte  ad  int.  Si  effettuano  tali  conversioni  per  mantenere  le  

informazioni.  

Conversioni  esplicite  

Il  C++  offre  diverse  forme  di  casting.  

tipo  (espr)  

(tipo)  espr  

const_cast  <tipo>  (espr)  

dinamic_cast  <tipo>  (espr)  

reinterpret_cast  <tipo>  (espr)  

static_cast  <tipo>  (espr)  

 

Input/Output  da  console  

Per  gestire  l'I/O  in  C++  è  necessario  includere  la  libreria  iostream  che  contiene  quattro  oggetti:  

cin,  cout,  cerr,  clog.  

Un  flusso  (stream)  è  una  sequenza  di  caratteri  preparati  per  leggere  o  scrivere  da/su  qualsiasi  

dispositivo  di  I/O.  

I  sistemi  operativi  hanno  3  flussi  standard  predefiniti.  Standard  input,  standard  error,  standard  

output.  Sia  in  lettura  che  in  scrittura  i  bytes  vengono  interpretati  come  caratteri.  

Input  (cin)  

cin  rappresenta  il  flusso  di  input  e  utilizza  l'operatore  di  estrazione  >>  per  estrarre  caratteri  da  

esso  e  metterli  in  qualche  variabile.  Se  non  si  redirige,  cin  legge  da  tastiera.  

Lettura:  viene  prelevata  dallo  stram  un'opportuna  sequenza  di  caratteri,  viene  convertita  nella  

sequenza  interna  del  dato,  secondo  quanto  specificato  dal  tipo  di  dato  della  variabile  

destinazione.  

Output  (cout)  

Rappresenta  il  flusso  di  output  e  utilizza  l'operatore  di  inserzione  <<  che  inserisce  i  dati  che  si  

trovano  alla  sua  destra  nel'oggetto  alla  sua  sinistra.  

Per  andare  a  capo  si  può  usare  o  la  sequenza  di  escape  \n  o  endl.  

Redirezione  dei  flussi  

Sia  in  lettura  che  in  scrittura  i  tra  flussi  possono  essere  rediretti  dal  sistema  operativo  verso  la  

memoria  di  massa:  

programma  <  file  (legge  l'input  da  un  file)  

programma  >  file  (scrive  l'output  su  file,  riscrivendolo)  

programma  >>  file  (scrive  l'output  su  file,  prolungandolo)  

Flussi  di  file  (file  stream)  

#include  <fstream>  

Definisco  un  oggetto  fstream.  Ad  es  fstream  tubo;;  

Definisco  una  variabile.  Ad  es  char  x;;  

Per  leggere:  tubo.open("miofile",  ios::in);;  

                                         tubo  >>  x;;  

                                         tubo.close();;  

Per  scrivere  (sostituire):  tubo.open("miofile",  ios::out);;  

                                                                             tubo  <<  x;;  

                                                                             tubo.close();;  

Per  continuare  a  scrivere  (append):  tubo.open("miofile",  ios::app)  

                                                                                                                   tubo  <<  x;;  

                                                                                                                   tubo.close();;  

 

Blocchi  e  visibilità  degli  identificatori  

Blocco:  sequenza  di  istruzioni  racchiuse  fra  parentesi  graffe  

Blocco  innestato:  inizia  e  finisce  dentro  un  altro  blocco  

Campo  di  visibilità  di  un  identificatore  (scope):  parte  del  programma  in  cui  l'oggetto  può  essere  

usato  

Se  un  oggetto  è  dichiarato  dentro  un  blocco  il  suo  campo  di  visibilità  ca  dal  punto  in  cui  è  

dichiarato  fino  alla  fine  del  blocco  stesso.  Un  oggetto  globale  è  dichiarato  fuori  dal  main.  

Un  oggetto  locale  ad  un  blocco:  non  può  essere  modificato  da  istruzioni  esterne  a  quel  blocco,  

maschera  eventuali  altri  oggetti  dichiarati  col  suo  stesso  identificatore  nei  blocchi  più  esterni,  non  

esiste  in  memoria  fino  a  che  non  viene  eseguito  il  blocco  di  istruzioni  in  cui  è  definito,  termina  di  

esistere  quando  viene  eseguita  l'ultima  istruzione  del  blocco.  

 

Spazio  dei  nomi  (namespace)  

È  una  caratteristica  del  C++.  È  una  regione  di  codice  definita  e  nominata  dal  programmatore  che  

contiene  definizioni  di  oggetti,  funzioni,  variabili,  ..  Ecc.  Si  può  accedere  a  questi  elementi  al  di  

fuori  dello  spazio  anteponendo  al  loro  nome  quello  dello  spazio  stesso.  Per  accedere  agli  

elementi  di  uno  spazio  dei  nomi  si  deve  anteporre  il  nome  dello  stesso  al  nome  degli  elementi  

ponendo  fra  i  due  ::  .  Per  semplificare  si  può  usare  la  direttiva  using  namespace.  

I  namespace  si  possono  annidare  uno  dentro  l'altro.  

La  definizione  di  uno  namespace  si  può  anche  spezzare  in  più  parti.  

 

Programmazione  strutturata  

Le  strutture  di  controllo  determinano  il  flusso  di  esecuzione  di  un  programma.  Vi  sono  tre  tipi  di  

strutture  di  controllo:  sequenza,  selezione,  ripetizione.  

L'istruzione  if  

if(espressione  booleana)  istruzione;;  

L'istruzione  if  analizza  l'espressione  booleana  al  suo  interno,  se  vera  procede  con  l'istruzione,  

se  falsa  non  fa  niente.  In  tutti  e  due  i  casi  successivamente  passa  all'istruzione  successiva  al'if.  

Istruzione  condizionale  doppia  if  else  

If(espressione  booleana)  istruzione1  else  istruzione2  

L'istruzione  if  valuta  l'espressione  booleana,  se  vera  esegue  istruzione1,  altrimenti  esegue  

istruzione2.  

Se  abbiamo  più  di  due  alternative  si  possono  "annidare"  più  istruzioni  if  una  dentro  l'altra.  Se  il  

codice  di  istruzioni  non  viene  posto  in  blocco,  l'else  si  riferisce  sempre  all'if  più  vicino!  

Al  posto  di  if  else  posso  anche  usare  l'operatore  condizionale  ?:  che  corrisponde  proprio  ad  if  

else.  

L'istruzione  switch  

Si  utilizza  per  selezionare  una  tra  molteplici  alternative  

switch(selettore)  

{  

     case  etichetta1:  istruzioni1;;  break;;  

     case  etichetta2:  istruzioni2;;  break;;  

       ....  

     default:  istruzioni;;  

}  

Il  selettore  è  un'espressione  semplice  che  può  essere  int,  char,  bool  ma  non  float,  double  o  

string.  Ogni  etichetta  ha  un  valore  costante  diverso  dalle  altre  etichette.  Se  il  valore  del  selettore  

è  uguale  a  una  delle  etichette  case,  allora  si  eseguirà  la  corrispondente  sequenza  di  istruzioni  e  

si  continueranno  ad  eseguire  le  successive  sequenze  di  istruzioni  fino  ad  incontrare  break.  Se  il  

valore  del  selettore  non  è  uguale  a  nessuna  etichetta  case  non  si  esegue  nulla,  a  me  no  che  non  

sia  inserita  l'etichetta  default.  

Se  non  inserisco  il  break  a  fine  istruzione,  il  programma  continuerà  a  fare  le  istruzioni  anche  

degli  altri  rami.  

 

Le  strutture  cicliche  

Un  ciclo  è  la  ripetizione  controllata  di  una  sequenza  di  istruzioni.  La  sequenza  si  dice  corpo  del  

ciclo  ed  ogni  ripetizione  si  chiama  iterazione  del  ciclo.  L'iterazione  è  controllata  da  una  

condizione,  un'espressione  booleana  che  prima  o  poi  dovrà  diventare  falsa  per  terminare  il  ciclo.  

Il  corpo  può  essere  un'istruzione  singola  o  un  blocco  di  istruzioni.  

-­  ciclo:  gruppo  di  istruzioni  eseguite  ripetutamente  fino  a  che  una  condizione  rimane  true  

-­  ripetizione  controllata  da  un  contatore:  è  definita  (è  noto  quante  volte  il  ciclo  sarà  eseguito)  e  si  

utilizza  una  variabile  di  controllo  usata  per  contare  le  ripetizioni.  

-­  ripetizione  controllata  da  una  sentinella:  è  indefinita  (usata  quando  il  numero  di  ripetizioni  non  è  

noto  a  priori),  il  termine  del  ciclo  è  indicato  dal  valore  della  sentinella.  

L'istruzione  while  

while  (condizione)  istruzione  

Si  valuta  la  prima  condizione  e  si  esegue  eventualmente  il  corpo  del  ciclo.  Se  la  condizione  è  

falsa  in  partenza  non  si  esegue  nulla,  altrimenti  il  ciclo  continuerà  fino  a  che  la  condizione  non  

risulta  falsa.  Si  può  usare  anche  l'istruzione  break  per  uscire  eventualmente  da  un  ciclo  infinito.  

Ciclo  for  

for  (inizializzazione;;  condizione;;  passo)  

         corpo  del  ciclo  

Il  passo  solitamente  è  l'incremento  di  una  variabile,  il  contatore  del  while  ad  esempio.  Le  variabili  

dichiarate  nell'inizializzazione  del  ciclo  for,  sono  locali  al  blocco  ma  possono  non  essere  di  tipo  

int  e  possono  essere  modificate  nel  passo,  possono  essere  più  di  una.  

È  meglio  evitare  che  il  col  del  for  modifichi  le  variabili  di  controllo  per  garantire  l'uscita  dal  ciclo.  

Si  può  non  inizializzare  un  for:  for  (;;;;)  istruzione.  In  questo  caso  si  può  uscire  dal  ciclo  inserendo  

in  break.  

Ciclo  do  while  

do  istruzione  while  condizione  

Comincia  eseguendo  istruzione  e  solo  dopo  valuta  condizione.  Se  questa  è  vera  istruzione  viene  

ripetuta  e  così  via  fino  a  quando  condizione  non  diventa  falsa.  

 

I  cicli  si  possono  annidare  uno  dentro  l'altro.  Ogni  volta  che  si  ripete  il  ciclo  esterno  vengono  

ripetuti  anche  quelli  interni  

 

Differenze  

while  è  particolarmente  usato  quando  l'iterazione  non  è  controllata  da  contatore.  Si  utilizza  

quando  si  vuole  saltare  il  ciclo  se  la  condizione  è  falsa.  

do  while  è  usato  quando  si  deve  eseguire  almeno  un'iterazione.  La  condizione  di  controllo  segue  

l'esecuzione  del  corpo  del  ciclo  

for  è  usato  quando  il  numero  di  iterazioni  si  conosce  in  anticipo  e  quindi  l'iterazione  può  essere  

controllata  da  un  contatore.  La  condizione  di  controllo  precede  l'esecuzione  del  corpo  del  ciclo.  

 

Istruzioni  di  salto  

-­  continue:  termina  solo  l’iterazione  corrente  del  ciclo;;  

-­  break:  termina  il  ciclo  e  passa  all’istruzione  successiva;;  

-­  goto:  termina  il  ciclo  e  salta  ad  una  certa  istruzione;;  

 

Programmazione  strutturata  

Ignora  le  istruzioni  di  salto:  permette  raffinamenti  top-­down  in  cui  gli  interventi  sono  indipendenti  

dai  precedenti  e  dai  successivi,  genera  algoritmi  più  leggibili,  semplifica  il  debugging  e  la  

mantainance.  E’  possibile  implementare  qualsiasi  algoritmo  prescindendo  dalle  istruzioni  di  

salto?  

Teorema  di  Böhm-­Jacopini  (1966)  

Ogni  funzione  computabile  può  essere  implementata  in  un  linguaggio  di  programmazione  che  

combina  sottoprogrammi  in  tre  maniere:  

-­  sequenza  (prima  un  sottoprogramma  poi  il  successivo);;  

-­  selezione  (eseguire  uno  dei  sottoprogrammi  in  base  alla  variabile  booleana);;  

-­  ripetizione  (eseguire  un  sottoprogramma  fino  a  che  la  variabile  booleana  è  vera).  

 

 

 

Funzioni  

Sottoprogrammi  che  mettono  in  corrispondenza  funzionale  certi  dati  in  input  con  altri  prodotti  in  

output.  Possono  essere  mandate  in  esecuzione  da  altri  programmi  e  soprattutto  servono  ad  

evitare  ripetizioni  nel  codice.  Rende  la  programmazione  modulare,  ovvero  il  programma  si  divide  

in  vari  moduli,  le  funzioni,  ciascuno  dei  quali  risolve  un  compito  specifico.  Raggruppando  funzioni  

in  una  libreria  si  creano  librerie  tematiche,  che  possono  essere  utilizzate  in  altri  programmi.  

Struttura  di  una  funzione:  

tipo_di_output  nomeFunzione  (parametri)  

{   corpo  della  funzione;;  

return  espressione;;  

}  

Il  tipo  di  ritorno  è  il  tipo  del  valore  restituito  dalla  funzione  (void  se  non  restituisce  alcun  valore).  Il  

nome  della  funzione  è  il  suo  identificatore.  I  parametri  sono  i  valori  che  la  funzione  prenderà  in  

input.  L’espressione  è  il  valore  che  restituirà  la  funzione.  

Non  si  possono  dichiarare  funzioni  annidate,  ma  si  possono  richiamare  tra  loro.  Tutte  le  variabili  

e  costanti  definite  in  una  funzione  sono  locali  ad  essa.  Mediante  la  parola  return  si  può  ritornare  il  

valore  restituito  al  programma  chiamante.  

Se  non  si  specifica  il  tipo  di  dato  di  ritorno,  si  sottintende  int.  Molte  funzioni  non  restituiscono  

nulla  e  si  usano  solo  come  subroutines;;  tali  funzioni  prendono  il  nome  di  procedure  (void).  

Chiamata  ad  una  funzione  

Una  funzione  (funzione  chiamata)  va  in  esecuzione  quando  viene  chiamata  dal  programma  

principale  main()  o  da  un’altra  funzione  (funzione  chiamante).  La  funzione  chiamata  inizia  con  la  

prima  istruzione  dopo  la  parentesi  graffa  e  termina  con  la  prima  istruzione  return  o  l’ultima  

istruzione  prima  della  parentesi  graffa  chiusa.  

Per  definire  una  funzione  senza  argomenti  è  possibili  inserire  void  tra  le  parentesi  

voi  nome(void)  

Prototipi  delle  funzioni  

La  dichiarazione  (prototipo)  di  una  funzione  è  simile  alla  definizione  ma:  non  ha  il  corpo  (che  

verrà  definito  altrove),  deve  specificare  il  tipo  dei  parametri  fondamentali  (ma  non  

necessariamente  il  nome)  e  l’intestazione  deve  terminare  con  il  ;;  .  Ciò  è  utile  quando  la  funzione  

si  trova  ad  esempio  in  un  altro  programma  che  viene  poi  collegato  a  questo.  Il  prototipo  fornisce  

quindi  sufficienti  informazioni  al  compilatore  per  verificare  che  la  funzione  venga  chiamata  

correttamente  rispetto  al  numero  e  al  tipo  di  parametri  che  utilizza.  E’  obbligatorio  mettere  il  

punto  e  virgola  al  termine  perchè  il  prototipo  è  un’istruzione.  Il  C++  distingue  tra  dichiarazione  e  

definizione,  infatti  quando  una  funzione  viene  definita,  oltre  ad  elencarne  le  caratteristiche,  viene  

anche  riservato  spazio  in  memoria.  Rispetto  alla  dichiarazione  che  informa  solo  dell’esistenza  di  

una  certa  funzione,  la  definizione  specifica  anche  il  luogo  dove  essa  esiste.  

Un  prototipo  con  un  numero  non  specificato  si  rappresenta  con  punti  sospensivi  …    

Ad  es:  int  esempi(int  a,  …);;  

 

Passaggio  di  parametri  ad  una  funzione  

Un  parametro  attuale  può  essere  un  valore  costante,  una  variabile  o  un’espressione  generica.  

per  passare  variabili  come  argomenti  attuali  alle  funzioni  ci  sono  due  modi:  per  valore  o  per  

riferimento.  

Passaggio  per  valore  

Nell’atto  della  chiamata  la  funzione  riceve  i  valori  delle  variabili,  non  le  variabili  stesse.  Se  la  

funzione  modificherà  il  valore  del  suo  argomento  formale,  queste  modifiche  non  interesseranno  

la  variabile  passata.  In  altre  parole:  la  funziona  modifica  il  valore  della  variabile,  ma  al  di  fuori  

della  funzione  stessa  tali  modifiche  non  hanno  effetto.  

Passaggio  per  riferimento  

Quando  una  funzione  deve  modificare  il  valore  della  variabile  che  le  è  stata  passata  come  

argomento,  si  deve  utilizzare  il  metodo  del  passaggio  per  riferimento.  In  questo  caso  non  viene  

passata  la  variabile,  ma  il  valore  del  suo  indirizzo  in  memoria,  cioè  il  suo  riferimento.  Esso  sarà  

quindi  usato  all’interno  della  funzione  per  indirizzare  la  variabile  esterna  da  modificare.  

Tale  metodo  può  essere  implementato  attraverso  i  puntatori  (C)  o  i  riferimenti  (C++).  

Metodo  dei  puntatori  

I  puntatori  sono  variabili  destinate  a  contenere  indirizzi  di  memoria.  

Ad  es  

void  scambia(int*  a,  int*  b)  

{   int  ausiliare  =  *a;;  

*a=*b;;  

*b=ausiliare;;  

}  

La  funzione  ha  come  argomenti  due  puntatori  ad  interi  a  e  b.  Il  corpo  della  funzione  usa  poi  le  

espressioni  *a  e  *b  per  deferenziare  i  puntatori,  cioè  per  leggere  gli  indirizzi  lì  contenuti  e  risalire  

quindi  alle  variabili  di  tipo  int  da  loro  referenziate.  Alla  chiamata  non  verranno  passate  le  variabili  

ma  i  loro  indirizzi  di  memoria  che  si  indica  anteponendo  &  (ampersand)  al  nome  della  variabile:  

scambia(&i,  &j);;  

Metodo  dei  riferimenti  

Un  riferimento  ad  una  variabile  è  semplicemente  un  (altro)  nome  della  variabile  stessa.  

Ad  es  

void  scambia(int&  m,  int&  n)  

{   int  ausiliare  =  m;;  

m  =  n;;  

n  =  ausiliare;;  

}  

La  funzione  ha  come  argomenti  formali  due  riferimenti  ad  interi  m  e  n.  Se  chiamiamo  la  funzione  

con  due  variabili,  ad  esempio  i  e  j,  la  funzione  userà  m  e  n  come  alias  di  i  e  j;;  qualunque  modifica  

effettuata  dalla  funzione  su  m  ed  n  non  avrà  alcun  effetto  su  i  e  j:  scambia(i,  j);;  

Se  antepongo  const  alla  dichiarazione  degli  argomenti  di  una  funzione,  questi  saranno  di  sola  

lettura  e  qualsiasi  modifica  di  essi  all’interno  della  funzione  produrrà  errore  di  compilazione.  

 

Argomenti  di  default  

In  C++  è  possibile  definire  funzioni  in  cui  alcuni  argomenti  assumono  un  valore  di  default.  Se  

all’atto  di  chiamata  non  viene  passato  alcun  valore,  la  funzione  assegnerà  il  valore  di  default.  

Ad  es  

char  funzdef(int  arg1=1,  char  c=’A’,  float  f_val=45.7f)  

Se  all’atto  della  chiamata  non  vengono  forniti  valori  la  funzione  assegnerà  i  valori  definiti.  I  valori  

si  possono  cambiare  semplicemente  cambiando  la  variabile  con  i  nuovi  valori  (si  possono  anche  

cambiare  alcuni  dei  valori,  gli  altri  assumeranno  il  valore  di  default;;  tuttavia,  il  vincolo  è  che  se  si  

omette  un  argomento  bisogna  anche  omettere  tutti  quelli  alla  sua  destra).  

Gli  argomenti  di  default  devono  passare  per  valore  (no  per  riferimento),  devono  essere  costanti.  

 

Visibilità  

La  visibilità  di  una  variabile  è  la  zona  del  programma  in  cui  essa  è  accessibile.  Questa  è  visibile  

quando  la  funzione  può  accedere  ad  essa.  Esistono  4  tipi  di  visibilità:  programma,  file  sorgente,  

funzione  e  blocco.  Normalmente  la  visibilità  è  data  da  dova  le  variabile  viene  definita,  ma  si  può  

modificare  con  gli  specificatori  static,  extern,  auto  e  register.  

-­  visibilità  di  programma:  sono  variabili  globali  e  possono  essere  referenziate  da  qualunque  

funzione  del  programma.  Per  rendere  globale  una  variabile  basta  dichiararla  all’inizio  del  

programma  fuori  da  qualunque  funzione;;  

-­  visibilità  di  file:  una  variabile  definita  fuori  da  qualsiasi  funzione  la  cui  dichiarazione  contiene  la  

parola  riservata  static  ha  visibilità  di  file.  Tali  variabili  possono  essere  referenziate  dal  punto  in  cui  

sono  dichiarate  fino  alla  fine  del  sorgente;;  

-­  visibilità  di  funzione:  le  variabili  dichiarate  dentro  il  corpo  di  una  funzione  sono  locali  e  possono  

essere  utilizzate  solo  al  suo  interno;;  

-­  visibilità  di  blocco:  una  variabile  dichiarata  dentro  un  blocco  può  essere  referenziata  in  

qualunque  parte  del  blocco;;  

Le  variabili  locali  oltre  ad  avere  visibilità  ristretta  non  occupano  memoria  fino  a  che  la  funzione  in  

cui  sono  dichiarate  viene  eseguita.  Quando  la  funzione  non  è  attiva,  tali  variabili  non  esistono  in  

memoria.  DI  conseguenza  un’istruzione  esterna  alla  funzione  non  può  modificare  il  valore  di  una  

variabile  locale  alla  funzione  e  due  o  più  funzioni  possono  dare  lo  stesso  nome  a  una  propria  

variabile  locale.  

Classi  di  immagazzinamento  (auto,  extern,  register,  static  e  typedef)  

Possono  modificare  la  visibilità  di  una  variabile.    

-­  variabili  automatiche  

Le  variabili  locali  a  una  funzione  si  dicono  automatiche  (auto)  perchè  si  assegna  loro  spazio  in  

memoria  automaticamente  alla  chiamata  della  funzione  e  si  rimuovono  automaticamente  

all’uscita.  La  parola  riservata  auto  è  opzionale.  

-­  variabili  esterne  

In  C++  si  può  utilizzare  una  variabile  globale  definita  in  un  altro  file  sorgente  dichiarandola  

localmente  con  la  parola  riservata  extern.  In  questo  modo  si  dice  al  compilatore  che  la  variabile  è  

definita  in  un  altro  file  sorgente  che  sarà  linkato  insieme.  Se  una  definizione  inizia  con  la  parola  

extern  non  è  una  e  vera  e  propria  definizione  ma  una  dichiarazione:  una  definizione  è  anche  

dichiarazione  ma  non  viceversa  (una  variabile  si  definisce  una  volta  sola  ma  si  può  dichiarare  

quante  volte  si  vuole).  

-­  variabili  di  registro  

Con  la  parola  riservata  register  si  dice  al  compilatore  di  porre  la  variabile  in  uno  dei  registri  

hardware  del  microprocessore.  Tuttavia  il  compilatore  non  è  detto  che  lo  faccia,  visto  che  i  

registri  hardware  non  sono  molti  e  quindi  può  decidere  di  ignorare  la  richiesta.  Una  variabile  di  

registro  deve  essere  locale  a  una  funzione,  ovvero  non  può  essere  globale  a  un  programma.  

Può  essere  utile  da  utilizzare  come  variabile  di  controllo  di  un  ciclo,  in  modo  che  la  CPU  non  

perde  tempo  a  cercare  tale  variabile  in  memoria.  

-­  variabili  statiche  

Al  contrario  delle  variabili  automatiche,  quelle  statiche  non  si  cancellano  quando  la  funzione  

termina.  Una  variabile  statica  si  inizializza  una  volta  per  tutte.  Si  dichiara  anteponendo  la  parola  

static  alla  dichiarazione.  La  parola  riservata  static  può  essere  utilizzata  per  occultare  variabili  

globali  da  altri  file  sorgenti.  

Visibilità  delle  funzioni  

Di  default  tutte  le  funzioni  sono  extern  e  quindi  visibili  da  altri  moduli  di  programma.  Si  possono  

dichiarare  funzioni  anche  con  static  e  non  sarà  così  possibile  utilizzarla  in  altri  moduli  di  

programma.  

 

Funzioni  inline  

Sono  convenienti  per  aumentare  la  velocità  del  programma  quando  devono  essere  chiamate  

spesso  e  il  loro  codice  è  breve.  Una  funzione  normale  è  un  blocco  di  codice  mandato  in  

esecuzione  da  un’altra  funzione.  L’indirizzo  dell’istruzione  successiva  alla  chiamata  della  

funzione  viene  memorizzato  nello  stack  in  maniera  da  potervi  accedere  una  volta  che  

l’esecuzione  della  funzione  sarà  conclusa.  Il  blocco  di  codice  termina  con  un’istruzione  speciale  

che  recupera  dallo  stack  l’indirizzo  di  ritorno  e  manderà  in  esecuzione  l’istruzione  successiva.  

Per  una  funzione  inline  il  compilatore  ricopia  realmente  il  codice  delle  funzione  in  ogni  punto  in  

cui  essa  viene  invocata.  Il  programma  sarà  così  più  veloce  perchè  non  si  dovrà  eseguire  il  

codice  associato  alla  chiamata  della  funzione.  Tuttavia,  il  programma  aumenta  la  sua  

dimensione.  Per  creare  una  funzione  inline  bisogna  inserire  la  parola  riservata  inline  all’inizio  

dell’intestazione:  inline  tipo  nome(argomenti)  (return  (codice);;)  

 

Concetto  e  uso  di  funzioni  di  libreria  

Sono  raccolte  di  funzioni  per  operazioni  comuni.  Le  funzioni  che  appartengono  allo  stesso  

gruppo  si  dichiarano  nello  stesso  header  file.  

-­  Funzioni  di  carattere  

<ctype.h>  definisce  un  gruppo  di  funzioni  per  la  manipolazione  dei  caratteri.  Tutte  le  funzioni  

restituiscono  un  tipo  booleano.  Esistono  diverse  funzioni  per  le  verifiche  alfanumeriche:  

isalpha(c)  (ritorna  true  se  c  è  maiuscola  o  minuscola),  islower(c)  (true  se  c  è  minuscola),  

isupper(c)  (true  se  c  è  maiuscola),  isdigit(c)  (true  se  c  è  cifra),  isxdigit(c)  (true  se  c  è  

esadecimale),  isalnum(c)  (true  se  c  è  una  cifra  o  un  carattere  alfabetico).  Alcune  funzioni  

verificano  la  leggibilità  di  caratteri  speciali:  iscntrl(c)  (true  se  c  è  carattere  di  controllo),  isgraph(c)  

(true  se  c  è  un  carattere  stampabile,  non  di  controllo),  isprint(c)  (true  se  c  è  stampabile  incluso  

lo  spazio),  ispunct(c)  (true  se  c  è  interpunzione),  isspace(c)  (true  se  c  è  spazio).  Esistono  

funzioni  non  booleane  che  servono  a  trasformare  lettere  maiuscole  in  minuscole  o  viceversa:  

tolower(c)  (converte  c  in  minuscola),  toupper(c)  (converte  c  in  maiuscola).  

-­  Funzioni  numeriche  

La  maggior  parte  si  trovano  in  <math.h>,  alcune  in  <stdlib.h>.  Le  funzioni  matematiche  più  

comuni  sono:  ceil(x)  (arrotonda  all’intero  vicino  più  comune),  fabs(x)  (restituisce  il  valore  

assoluto  di  x),  floor(x)  (arrotonda  per  difetto  all’intero  più  vicino),  pow(x,  y)  (calcola  x  elevato  a  y),  

sqrt(x)  (restituisce  la  radice  quadrata  di  x).  <math.h>  include  anche  funzioni  trigonometriche  

(richiedono  i  radianti!  1rad=gradi*(π/180)):  acos(x)  (calcola  l’arcoseno  di  x),  asin(x)  (calcola  

l’arcoseno  di  x),  atan(x)  (calcola  l’arcotangente  di  x),  atan2(x,  y)  (calcola  l’arcotangente  di  x  

diviso  y),  cos(x)  (calcola  il  coseno  di  x),  sin(x)  (calcola  il  seno  di  x),  tan(x)  (calcola  la  tangente  di  

x).  La  libreria  cmath  include  anche  funzioni  logaritmiche  ed  esponenziali:  exp(x)  (calcola  

l’esponenziale  di  x),  log(x)  (calcola  il  logaritmo  naturale  di  x),  log10(x)  (calcola  il  logaritmo  

decimale  di  x).  

-­  Funzioni  aleatorie  

rand()  (genera  un  numero  casuale  fra  0  e  RAND_MAX),  randomize()  (inizializza  il  generatore  di  

numeri  aleatori  con  un  seme  aleatorio  ottenuto  a  partire  da  una  chiamata  alla  funzione  time),  

srand(seme)  (inizializza  il  generatore  di  numeri  aleatori  in  base  al  valore  dell’argomento  seme),  

random(num)  (restituisce  un  valore  casuale  tra  0  e  num-­1).  

-­  Funzioni  di  data  e  ora  

Definite  nell’header  file  time.h:  clock(void)  (restituisce  il  tempo  di  CPU  in  secondi  dall’esecuzione  

del  programma),  time(ora)  (restituisce  il  numero  di  secondi  trascorsi  dalla  mezzanotte  del  1  

gennaio  1970,  questo  valore  di  tempo  di  mette  in  ora).  

 

Compilazione  modulare  

I  programmi  più  grandi  sono  più  facili  da  gestire  se  si  dividono  in  vari  file  sorgente,  moduli,  

ognuno  dei  quali  può  contenere  una  o  più  funzioni.  Questi  moduli  verranno  poi  compilati  

separatamente  ma  linkati  insieme,  a  ogni  ricompilazione  verranno  ricompilati  solo  i  moduli  

modificati.  Le  funzioni  possono  essere  referenziate  tra  i  vari  moduli;;  l’uso  della  parola  static  è  

utile  per  evitare  conflitti  di  nomi  (sono  preferibili  variabili  locali  a  globali).  

 

Sovraccaricamento  delle  funzioni  

Il  sovraccaricamento  delle  funzioni  (overheading)  permette  di  utilizzare  più  funzioni  con  lo  stesso  

nome,  ma  con  almeno  un  argomento  di  tipo  diverso  e/o  con  un  diverso  numero  di  argoementi.  Il  

compilatore  C++  verifica  il  tipo  di  parametro  inviato  per  determinare  qual’è  la  funzione  da  

chiamare.  C++  determina  tra  le  funzioni  sovraccaricate  quale  deve  chiamare  in  base  al  numero  

di  parametri  passati  o  dal  tipo  (un  tipo  deve  essere  diverso  da  funzione  a  funzione).  Regole  di  

selezione:  se  esiste  si  seleziona  la  funzione  che  mostra  la  corrispondenza  esatta  tra  il  numero  e  

i  tipi  dei  parametri  formali  e  attuali;;  se  tale  funzione  non  esiste,  si  seleziona  una  funzione  in  cui  il  

matching  dei  parametri  formali  e  attuali  avviene  tramite  una  conversione  automatica  di  tipo;;  la  

corrispondenza  dei  tipi  può  essere  forzata  attraverso  casting;;  se  una  funzione  sovraccaricata  ha  

un  numero  indeterminato  di  argomenti  (...)  è  selezionata  in  mancanza  di  matching  più  precisi.  

 

Ricorsione  

Una  funzione  ricorsiva  è  una  funzione  che  chiama  sé  stessa,  direttamente  o  indiritamente.  La  

ricorsione  diretta  è  il  processo  per  il  quale  una  funzione  invoca  sé  stessa,  indiretta  se  sono  

implicate  due  o  più  funzioni.  Una  funzione  ricorsiva  deve  avere  una  condizione  di  terminazione  o  

risulterà  infinita.  

 

Template  di  funzioni  

I  template  forniscono  un  meccanismo  per  creare  funzioni  generiche.  Una  funzione  generica  è  

una  funzione  che  può  supportare  simultaneamente  differenti  tipi  di  dato  per  i  suoi  parametri.  I  

template  sono  utili  quando  occorre  utilizzare  la  stessa  funzione  con  differenti  tipi  di  argomenti.  

Un  template  ha  il  seguente  formato:  

template  <class  tipo>  

dichiarazione  delle  funzione  

Il  simbolo  tipo  indica  al  compilatore  che  può  essere  sotituito  dal  tipo  di  dato  appropriato.  

Ad  es  

template  <class  T>  

T  max(T  a,  T  b)  

il  template  funzione  max  si  dichiara  con  un  unico  tipo  generico  T  e  con  due  argomenti.  

 

Array  

Un  array  (o  vettore)  è  una  sequenza  di  oggetti  dello  stesso  tipo.  Gli  oggetti  si  chiamano  elementi  

dell’array  e  si  numerano  consecutivamente  0,  1,  2,  3,  ...  

Il  tipo  degli  elementi  è  definito  dall’utente.  

I  numeri  che  indicano  gli  elementi  dell’array  si  dicono  indici  dell’arra  e  il  loro  compito  è  quello  di  

localizzare  l’elemento  dentro  l’array  e  di  fornire  accesso  diretto  ad  esso.  

Un  array  viene  immagazzinato  in  memoria  sequenzialmente  su  posizioni  di  memoria  contigue.  

Un  array  si  definisce  in  modo  simile  agli  altri  tipi  di  dato  m  si  deve  indicare  tra  parentesi  quadre  la  

sua  dimensione  (o  lunghezza).  

tipo  nomeArray[numeroElementi]  

Si  può  accedere  a  ogni  elemento  dell’array  medianto  uno  stesso  nome  e  un  indice  scorrevole:  

nomeArray[0]  indica  il  primo  elemento.  C++  non  verifica  che  gli  indici  dell’array  stiano  dentro  la  

dimensione  definita,  accedendo  quindi  ad  un  elemento  al  di  fuori  dell’array  il  compilatore  non  

segnala  errore.  Si  possono  referenziare  elementi  anche  utilizzando  espressioni  per  gli  indici,  ad  

esempio:  vendite[totale  +  5].  

Allocamento  in  memoria  degli  array  

Gli  elementi  dell’array  si  posizionano  in  blocchi  contigui  di  memoria.  

La  funzione  sizeof()  restituisce  il  numero  di  byte  necessari  per  contenere  il  dato  o  il  tipo  di  dato  

che  le  è  stato  passato  come  argomento.  Se  si  usa  per  un  array  restituisce  il  numero  di  byte  

occupato  da  tutto  l’array.  

A  differenza  di  altri  linguaggi,  il  C++  non  verifica  che  il  valore  dell’indice  sia  inferiore  alla  

lunghezza  dell’array.  

Inizializzazione  di  un  array  

Si  può  usare  l’operatore  di  assegnamento  per  assegnare  valori  ad  ogni  elemento  dell’array.  

Questo  metodo  non  è  pratico  quando  l’array  contiene  parecchi  elementi.  Un  metodo  più  

efficiente  è  tale  formato:  int  nomArray[dim]  =  {el1,  el2,  el3,  …  ,  eldim};;  

Quando  si  inizializza  un  array  in  questo  modo  la  dimensione  è  falcoltativa,  visto  che  il  

compilatore  conterà  il  numero  di  valori  dentro  le  parentesi.  

In  altri  casi  si  potrebbe  usare  l’istruzione  for  per  inizializzare  tutti  gli  elementi:  

for  (i=0;;  i<=5;;  i++)  

numeri[i]=0;;  

Ogni  elemento  da  1  a  5  prenderà  valore  0.  

Se  si  inizializza  un  array  static  o  globale  il  compilatore  assegnerà  tutti  valori  0  a  meno  che  non  si  

definiscano  manualmente.  

Array  di  caratteri  o  stringhe  di  testo  

C++  rappresenta  le  stringhe  (sequenze  di  caratteri)  utilizzando  array  di  caratteri.  

char  miaStringa[]  =  “ABCDEF”;;  

con  la  convenzione  che  le  stringhe  terminano  con  un  carattere  nullo.  Le  stringhe  sono  array  di  

caratteri  ma  non  tutti  gli  array  di  caratteri  sono  stringhe.  Le  stringhe  hanno  come  ultimo  carattere  

‘\0’  ma  non  è  detto  che  questo  sia  l’ultimo  elemento  del  vettore:  il  compilatore  aggiunge  il  

carattere  nullo  subito  dopo  l’ultimo  elemento  della  stringa.  

Non  si  può  assegnare  una  stringa  a  un  array  al  di  fuori  della  definizione.  Per  fare  ciò  si  può  usare  

la  funzione  di  libreria  strcpy(nome,  “Stringa”).  

Se  l’array  non  ha  sufficienti  spazi  per  contenere  la  stringa  si  va  in  buffer  overflow  e  il  compilatore  

scriverà  in  altri  spazi  di  memoria.  

 

Array  multidimensionali  

Gli  array  oltre  che  di  una  dimensione,  possono  essere  di  più  dimensioni.  Un  array  di  due  

dimensioni  prende  il  nome  di  tabella  o  matrice:  

tipo  nome  [numRighe]  [numCol];;  

Un  array  di  due  dimensioni  è  in  realtà  un  array  di  array,  cioè  un  array  unidimensionale  i  cui  

elementi  sono  array.  

int  tabella  [2]  [3]  =  {{51,  52,  53},  {54,  55,  56}}  

Per  accedere  agli  elementi  di  un  array  bidimensionale  bisogna  specificare  l’indice  di  riga  e  quello  

di  colonna:  nome  [indiceRiga]  [indiceColonna]  =  valore  elemento;;  

Array  di  più  di  tre  dimensioni  sono  difficilmente  usati.  Un  esempio  per  un  array  di  tre  dimensioni  è  

un  libro:  char  libro  [pagine]  [righe]  [colonne];;  ogni  pagine  è  un  array  bidimensionale.  Per  

accedere  ai  singoli  elementi  del  libro  è  possile  utilizzare  cilci  annidati.  

 

 

Passaggio  di  vettori  come  parametri  

In  C++  gli  array  si  passano  per  riferimento.  Ovvero  quando  s’invoca  una  funzione  le  si  passa  un  

array  come  parametro,  C++  tratta  la  chiamata  come  se  vi  fosse  l’operatore  &  davanti  al  nome  

della  variabile.  

Si  possono  definire  funzioni  che  accettano  array  di  valore  double  come  parametri.  Se  la  funzione  

deve  conoscere  la  dimensione  dell’array  si  deve  aggiungere  un  secondo  parametro  per  questo:  

double  SommaDiDati(double  dati[],  int  n);;  

Quando  si  passa  un  array  ad  una  funzione  si  passa  in  realtà  solo  l’indirizzo  del  suo  primo  

elemento,  che  è  proprio  il  nome  dell’array,  ma  la  funzione  accede  direttamente  alle  celle  di  

memoria  dell’array.  Passare  il  nome  dell’array  per  valore  significa  passare  l’array  per  riferimento.  

Poichè  le  stringhe  sono  vettori  di  caratteri,  passare  una  stringa  a  una  funzione  significa  passare  

un  vettore.  Per  far  conoscere  la  loro  dimensione  le  stringhe  usano  il  metodo  della  sentinella  che  

risulta  il  carattere  nullo.  Funzioni  che  hannno  argomenti  formali  di  tipo  array  possono  modificare  

gli  array  passati  come  argomenti  attuali!  (Passaggio  per  riferimento).  

 

Limiti  dei  vettori  in  C++  

-­  non  si  possono  eseguire  operazioni  di  confronto;;  

-­  non  si  può  assegnare  sull’intero  array;;  

-­  non  si  possono  eseguire  operazioni  aritmetiche;;  

-­  funzioni  non  possono  restituire  array;;  

 

Ordinamento  di  vettori  

E’  la  procedura  tramite  la  quale  si  dispongono  gli  elementi  dell’array  in  un  ordine  specifico.  

Algoritmi  di  ordinamento  sono:  per  inserzione,  a  bolle  (bubble-­sort),  per  selezione  

(selection-­sort),  rapido  (quick-­sort),  per  fusione  (merge-­soft).  

Quick-­sort  

E’  il  più  efficiente,  si  basa  sulla  divisione  del  vettore  in  tre  partizione,  sinistra,  centrale  (pivot)  e  

destra.  Supponendo  l’ordine  crescente,  gli  elementi  di  sinistra  dovranno  essere  più  piccoli  del  

primo  elemento  di  destra  e  ciò  è  possibile  confrontando  con  il  pivot  al  centro.  L’elemento  pivot  

può  essere  scelto  a  caso  all’interno  del  vettore.  

 

void  QuickSort(QS_TYPE  list[],  int  beg,  int  end)  

{  

       QS_TYPE  piv;;  QS_TYPE  tmp;;  

       int    l,r,p;;  

       while  (beg<end)        //  This  while  loop  will  substitude  the  second  recursive  call  

       {  

               l  =  beg;;  p  =  (beg+end)/2;;  r  =  end;;  

               piv  =  list[p];;  

               while  (1)  

               {  

                       while  (  (l<=r)  &&  (  QS_COMPARE(list[l],piv)  <=  0  )  )  l++;;  

                       while  (  (l<=r)  &&  (  QS_COMPARE(list[r],piv)    >  0  )  )  r-­-­;;  

                       if  (l>r)  break;;  

                       tmp=list[l];;  list[l]=list[r];;  list[r]=tmp;;  

                       if  (p==r)  p=l;;  

                       l++;;  r-­-­;;  

               }  

               list[p]=list[r];;  list[r]=piv;;  

               r-­-­;;  

               //  Select  the  shorter  side  &  call  recursion.  Modify  input  param.  for  loop  

               if  ((r-­beg)<(end-­l))    

               {  

                       QuickSort(list,  beg,  r);;  

                       beg=l;;  

               }  

               else  

               {  

                       QuickSort(list,  l,  end);;  

                       end=r;;  

               }  

       }    

}  

 

Strutture  

Un  struttura  è  una  collezione  di  elementi  denominati  campi,  ognuno  dei  quali  può  contenere  un  

dato  di  tipo  diverso.  

Una  struttura  può  contenere  qualunque  numero  di  campi.  

Formato  della  dichiarazione:  

struct  nome_della_struttura  

{   tipocampo1  nomecampo1;;  

tipocampo2  nomecampo2;;  

…  

tipocampon  nomecampon;;  

}  

Dopo  aver  dichiarato  il  tipo  di  dato  si  possono  definire  variabili  di  quel  tipo.  Le  variabili  di  tipo  

struct  si  possono  definire  in  due  modi:  elencandole  dopo  la  parentesi  graffa  di  chiusura  dello  

struct  o  scrivendo  il  nome  della  struttura  seguito  dalle  variabili.  

Le  strutture,  al  contrario  dei  vettori,  possono  essere  assegnate.  

Ad  es:  libro  libro4  =  libro5;;  

Una  variabile  di  tipo  struttura  si  può  inizializzare  in  qualunque  punto  del  programma,  anche  nella  

definizione.  I  valori  si  devono  dare  nell’ordine  in  cui  sono  definiti  i  corrispondenti  campi  nella  

struttura.  Se  vi  sono  più  valori  di  inizializzazione  che  campi  della  struttura  il  compilatore  segnala  

errore;;  viceversa  i  campi  non  inizializzati  prendono  i  valori  di  default.  

L’operatore  sizeof,  utilizzato  per  una  struttura,  darò  come  output  la  somma  dei  byte  occupati  da  

ciascun  campo.  

Per  accedere  in  lettura  o  scrittura  a  un  singolo  campo  della  struttura  si  utilizza  l’operatore  (  .  ).  

Ad  esempio  per  assegnare  un  valore  al  campo  di  una  variabile  struct:  

variabile.campo  =  valore;;  

 

Strutture  annidate  

Un  campo  di  una  struttura  può  essere  a  sua  volta  di  tipo  struttura.  Se  strutture    diverse  

possiedono  parti  identiche,  definire  queste  ultime  come  sottostrutture  fa  risparmiare  tempo  e  

riduce  la  possibilità  di  errore.  

Ad  es  

struct  info  

{   char  nome[30];;  

char  indirizzo[25];;  

char  città[20];;  

…  

}  

struct  impiegato  

{   struct  info  anagrafica;;  

…  

}  

Quindi  se  voglio  inizializzare  un  dato  dovrò  scrivere  impiegato.anagrafica.nome  =  …  

L’accesso  a  campi  dato  di  strutture  annidate  richiede  l’uso  di  operatori  punto  in  cascata.  

 

Array  di  strutture  

Si  può  creare  un  array  di  struttre  così  come  un  qualunque  altro  tipo.  Gli  array  di  strutture  sono  

utili  per  rappresentare  basi  di  dati  (database),  cioè  collezioni  di  record  da  gestire  in  maniera  

efficiente.  La  dichiarazione  di  un  array  di  strutture  è  simile  a  qualunque  array:    

tipoStruct  Struct[dim];;  

Per  accedere  ai  campi  di  ognuno  degli  elementi  struttura  si  utilizzano  l’indice  dell’array  e  

l’operatore  punto.  

Array  come  campi  

I  campi  delle  strutture  possono  essere  vettori  

Strutture  come  parametri  

C++  permette  di  passare  strutture  come  parametri  attuali  alle  funzioni,  sia  per  valore  che  per  

riferimento.  Nel  primo  caso  se  la  struttura  è  grande  si  può  avere  una  notevole  perdita  di  

efficienza.  

 

Funzioni  membri  di  strutture  

In  C++  le  strutture  possono  anche  contenere  funzioni.  

 

Unioni  

Le  unioni  somigliano  alle  strutture,  ma  anzichè  allocare  i  campi  in  maniera  contigua  esse  li  

sovrappongono  nella  stessa  posizione  di  memoria.  

union  nome  {  

tipo1  campo1;;  

tipo2  campo2;;  

}  

La  quantità  di  memoria  riservata  per  una  unione  è  data  dal  campo  più  grande,  perchè  i  campi  

condividono  la  stessa  zona  di  memoria.  Le  unioni  servono  per  risparmiare  memoria,  

specialmente  quando  servono  diverse  variabili  ma  non  tutte  nello  stesso  momento.  

Per  riferirsi  ai  campi  di  un’unione  si  utilizza  l’operatore  punto  (.).  

 

Enumerazioni  

Una  enumerazione  è  un  tipo  definito  dall’utente  costituito  da  un  insieme  di  costanti.  

enum  nome  {  

enumeratore1  =  espressione_costante1,  

enumeratore2  =  espressione_costante2,  

enumeratore3  =  espressione_costante3,  

…  

}  

 

Typedef  

La  parola  riservata  typedef  serve  per  creare  un  sinonimo  di  un  tipo  di  dato,  fondamentale  o  

definito  dall’utente.  

Ad  es  chiamo  double  come  lunghezza:  typedef  double  lunghezza;;  

 

Riferimenti  

Definendo  una  variabile  se  ne  determinano  il  nome,  il  tipo  e  l’indirizzo  di  memoria.  All’indirizzo  

della  variabile  si  accede  mediante  l’operatore  di  indirizzo  &,  che  va  applicato  al  nome  della  

variabile.  

Un  riferimento  a  una  variabile  è  un  ulteriore  nome  per  essa.  Il  C++  introduce  il  riferimento  al  tipo  

che  si  dichiara  utilizzando  l’operatore  &  come  suffisso  al  tipo  di  dato  riferito.  Il  riferimento  al  tipo  

viene  usato  come  tipo  normale  in  una  definizione  di  variabile;;  tuttavia,  tale  variabile  deve  essere  

inizializzata  contestualmente  alla  definizione,  deve  quindi  essere  seguita  dall’operatore  

assegnamento  e  dal  nome  di  una  variabile  già  definita  dello  stesso  tipo  del  tipo  riferito.  

Il  carattere  &  ha  tre  usi  in  C++:  

1.  Se  si  utilizza  come  prefisso  al  nome  di  una  variabile  ne  restituisce  l’indirizzo;;  

2.  Se  si  utilizza  come  suffisso  a  un  tipo  nella  definizione  di  un  riferimento,  quest’ultimo  è  

dichiarato  sinonimo  della  variabile  utilizzata  per  la  sua  inizializzazione;;  

3.  Se  si  utilizza  come  suffisso  a  un  tipo  nella  dichiarazione  dei  parametri  formali  di  una  funzione,  

questi  ultimi  sono  dichiarati  riferimenti  delle  corrispondenti  variabili  passate  alla  funzione.  

 

Puntatori  

Quando  si  nomina  (o  si  fa  riferimento  a)  una  variabile,  il  compilatore  accede  automaticamente  al  

suo  indirizzo  di  memoria,  risalendovi  dal  nome.  

Il  C  e  il  C++  utilizzano  il  tipo  di  dato  “puntatore  al  tipo”.  Si  dichiara  utilizzando  l’operatore  *  come  

suffisso  al  tipo  di  dato  puntato.  Un  puntatore  è  una  variabile  che  contiene  l’indirizzo  di  memoria  di  

un’altra  variabile,  che  punta.  Il  valore  della  variabile  è  contenuto  dentro  la  variabile  stessa,  mentre  

il  suo  indirizzo  è  contenuto  nella  variabile  puntatore.  

Quindi:  

-­  Un  puntatore  è  una  variabile;;  

-­  Un  puntatore  contiene  un  indirizzo  di  memoria;;  

-­  All’indirizzo  di  memoria  contenuto  nel  puntatore  c’è  una  variabile,  si  dice  che  un  puntatore  

punta  ad  una  variabile;;  

Dopo  aver  definito  e  inizializzato  un  puntatore,  il  passo  successivo  è  quello  di  utilizzarlo  per  

riferire  la  variabile  puntata,  sia  in  scrittura  che  in  lettura.  Arrivare  alla  variabile  puntata  partendo  

da  un  suo  puntatore  significa  deferenziare  il  puntatore.  L’operazione  si  fa  con  l’operatore  

indirezione  *  che  si  antepone  alla  variabile  puntatore.  

Ad  es  *p  restituisce  il  nome  della  variabile  puntata  da  p.  A  questo  punto  il  nome  della  variabile  

può  essere  usata  sia  a  destra  dell'operatore  di  assegnamento  (in  lettura)  che  a  sinistra  (in  

scrittura).  

Ad  es  

int  q=*p  (q  prende  lo  stesso  valore  che  c'è  dentro  la  variabile  puntata  da  p,  supponiamo  n)  

*p=75  (n  prende  il  valore  di  75)  

cin  >>  *p  (mette  il  valore  di  input  dentro  n)  

cout  <<  *p  (stampa  il  valore  di  n)  

Si  può  dichiarare  un  puntatore  void*  a  qualunque  tipo  di  dato.  

Se  un  puntatore  non  viene  inizializzato,  prende  un  valore  aleatorio  dato  dallo  stato  dei  bit  delle  

celle  di  memoria  che  occupa  al  momento  della  sua  definizione.  Per  questo  è  necessario  

assegnare  sempre  un  valore  al  puntatore,  al  massimo  NULL.  

Un  puntatore  inizializzato  a  0  o  NULL  non  punta  a  niente  cioè  non  indirizza  alcun  dato  valido  in  

memoria.  0  o  NULL  sono  equivalenti.  

 

Puntatore  a  puntatore  

Un  tipo  puntatore  può  puntare  anche  ad  un  altro  puntatore.  Per  dichiarare  tale  puntatore  si  usano  

due  asterischi.  

Ad  es  

int  i=100;;  

int*  ptr1=&i;;  

int**  ptr2=&ptr1;;  

ptr1  e  ptr2  sono  due  puntatori  diversi,  ma  il  primo  è  puntatore  a  interi  e  punta  i,  il  secondo  è  

puntatore  a  puntatore  di  interi  e  punta  ptr1.  Per  deferenzare  il  puntatore  di  puntatori  si  possono  

usare  i  due  asterischi:  **ptr2=95  (assegna  95  a  i)  

 

Puntatori  e  array  

In  C++  gli  array  sono  implementati  mediante  puntatori.  Il  nome  di  un  vettore  è  esattamente  un  

puntatore  al  primo  elemento  dell'array.  Prendendo  ad  esempio  il  vettore  gradi[3],    

cout  <<  gradi[0]  visualizzerà  il  primo  elemento  dell'array,  ma  lo  farà  anche  cout  <<  *gradi,  

perché  il  nome  gradi  è  un  puntatore  al  primo  elemento.  In  più  se  incrementiamo  il  puntatore  a  un  

valore  pari  a  un  indice  del  vettore  e  poi  lo  referenziamo,  andiamo  a  prendere  l'elemento  del  

vettore  corrispondente  a  quell'indice.  

Pertanto  per  leggere  o  scrivere  un  elemento  di  un  array  si  possono  utilizzare  indifferentemente  

entrambe  le  notazioni,  quella  vettoriale  e  quella  basata  sui  puntatori.  Il  nome  di  un  array  è  però  

una  costante  puntatore,  non  una  variabile,  non  si  può  cambiarne  il  valore.  Tuttavia,  è  possibile  

cambiare  i  valori  delle  variabili  di  tipo  puntatore  per  farle  puntare  valori  differenti  in  memoria.  

 

Array  di  puntatori  

Se  bisogna  definire  parecchi  puntatori  a  uno  stesso  tipo  si  può  utilizzare  un  array  di  puntatori.  Un  

array  di  puntatori  è  un  vettore  i  cui  elementi  sono  puntatori  dello  stesso  tipo:  int*  ptr[10]  definisce  

10  puntatori  ad  interi.  Ogni  elemento  contiene  un  indirizzo  che  punta  ad  altre  variabili  di  tipo  

intero  in  memoria  e  può  essere  riassegnato.  

Queste  due  definizioni  sono  equivalenti:  

char  stringa[]  =  “Ciao  vecchio  mondo”;;  

char*  stringa  =  “Ciao  vecchio  mondo”;;  

 

Puntatori  a  stringhe  

Definisco  una  stringa  di  caratteri:  char  alfabeto[27]=”ABCD…..”;;  

Dichiaro  p  puntatore  a  chiar:  char*  p;;  

Faccio  puntare  p  al  primo  carattere  di  alfabeto  scrivendo:  p=alfabeto;;  o  p=&alfabeto[0];;  

Posso  anche  assegnare:  p=alfabeto+15;;  o  p=&alfabeto[15];;  

Non  posso  assegnare:  p=&alfabeto;;  perchè  p  e  alfabeto  sono  puntatori  al  tipo  char  e  l’istruzione  

tenterebbe  di  assegnare  a  p  l’indirizzo  di  un  puntatore  a  char  e  non  l’indirizzo  di  una  variabile  di  

tipo  char.  

 

Aritmetica  dei  puntatori  

Se  un  puntatore  a  un  tipo  T  viene  incrementato  (o  decrementato)  di  1,  il  suo  valore  viene  in  realtà  

incrementato  (o  decrementato)  di  un  numero  pari  alla  dimensione  del  tipo  T  espressa  in  byte.  In  

generale,  incrementare  o  decrementare  di  un  intero  n  un  puntatore  significa  incrementarlo  o  

decrementarlo    di  un  numero  di  byte  pari  a  n  moltiplicato  per  la  dimensione  del  tipo  puntato.  

Ad  es:  int  gradi[5]  =  (10,  20,  30,  40,  50);;  

p=gradi;;  

p  punta  al  primo  intero  10  in  gradi;;  ma  dopo    l’istruzione  p++  p  punterà  al  secondo  intero  20.  

Poichè  ogni  elemento  occupa  4  byte,  p  è  stato  incrementato  di  4  e  non  di  1.  

Si  può  quindi  usare  tale  tecnica  per  attraversare  un  vettore  senza  usare  una  variabile  di  indice.  

Se  il  vettore  da  attraversare  è  una  stringa,  si  può  semplificare  il  ciclo  considerando  il  fatto  che  

essa  termina  con  il  carattere  nullo:  

char  messaggio[]  =  “Ciao  vecchio  mondo”;;    

p  =  messaggio;;  

while  (*p)  cout  <<  p++  <<  endl;;  

Il  ciclo  while  si  ripete  finchè  *p  ha  un  valore  diverso  da  zero;;  si  stampa  il  carattere  e  si  

incrementa  p  per  puntare  al  successivo  carattere.  

I  puntatori  possono  anche  essere  sottratti,  ma  non  sommati,  moltiplicati  o  divisi.  

 

Puntatori  costanti  e  puntatori  a  costanti  

Il  nome  di  un  array  è  un  puntatore  costante:  il  suo  valore  non  può  cambiare,  ma  possono  essere  

cambiati  i  valori  della  variabile  puntata.  

Un  puntatore  a  costante  potrà  cambiare  il  suo  valore  ma  non  quello  della  variabile  a  cui  punta.  

Per  creare  un  puntatore  costante  si  utilizza  il  formato:    

tipo_di_dato*  const  nome_punt  =  indirizzo_variabile  

Si  può  scrivere:  *p1=e  ma  non  p1=&e  

Per  definire  un  puntatore  a  costante  si  usa  il  formato:  

const  tipo_di_dato*  nome_puntatore  =  indirizzo_const_o_stringa;;  

Si  può  scrivere:  p1=&e  ma  non  *p1=15,  qualunque  tentativo  di  modificare  il  contenuto  della  

posizione  di  memoria  puntata  da  p1  provocherà  errore.  

Nota:  La  definizione  di  un  puntatore  costante  ha  la  parola  riservata  const  davanti  al  nome  del  

puntatore,  mentre  il  puntatore  a  una  costante  ha  la  parola  riservata  const  davanti  al  tipo  di  dato.  

Per  definire  puntatori  costanti  a  costanti  si  usa  il  seguente  formato:  

const  tipo_di_dato  *const  nome_puntatore  =  indirizzo_const_o_stringa  

Se  si  sa  che  un  puntatore  punterà  sempre  la  stessa  posizione  e  non  dovrà  mai  essere  riallocato  

lo  si  definisce  come  puntatore  costante.  Se  si  sa  che  il  dato  puntato  dal  puntatore  non  dovrà  mai  

essere  modificato  si  definisce  come  puntatore  a  costante.  

Lo  spazio  non  è  significativo  nella  dichiarazione  di  puntatori.  Le  dichiarazioni  seguenti  sono  

equivalenti:  

int*  p;;  

int  *  p;;  

int  *p;;  

 

 

 

Puntatori  come  argomenti  di  funzioni  

Spesso  si  vuole  che  una  funzione  restituisca  più  di  un  valore  oppure  modifichi  variabili  passate  

come  argomenti.  Si  possono  ottenere  questi  risultati  passando  puntatori,  magari  nomi  di  vettori,  

come  argomenti  attuali.  

Il  passaggio  per  riferimento  è  più  efficiente  del  passaggio  per  indirizzo  

 

Puntatori  a  funzioni  

E’  possibile  creare  anche  puntatori  a  funzioni;;  anzichè  indirizzare  dati,  i  puntatori  di  funzioni  

indirizzano  codice  eseguibile,  dato  che  anche  le  istruzioni  stanno  in  memoria  in  certi  indirizzi.  In  

C++  si  possono  quindi  assegnare  gli  indirizzi  iniziali  di  funzioni  a  puntatori.  Tali  funzioni  si  

possono  chiamare  in  modo  indiretto  tramite  un  puntatore  il  cui  valore  è  uguale  all’indirizzo  iniziale  

della  funzione  in  questione.  La  sintassi  generale  per  la  dichiarazione  di  un  puntatore  a  funzione  

è:  

tipo_di_ritorno  (*puntatore_funzione)  (argomenti);;  

Questo  formato  dice  al  compilatore  che  puntatore_funzione  è  un  puntatore  a  una  funzione  che  

restituisce  il  tipo_di_ritorno  e  una  lista  di  parametri.  

Un  puntatore  a  una  funzione  è  semplicemente  un  puntatore  il  cui  valore  è  l’indirizzo  del  nome  

della  funzione.  Dato  che  il  nome  di  una  funzione  è  un  puntatore,  come  il  nome  di  un  vettore,  un  

puntatore  a  una  funzione  è  un  puntatore  a  un  puntatore  costante.  

La  sintassi  generale  per  inizializzare  un  puntatore  a  funzione  è:    

puntatore_funzione  =  nome_di_una_funzione  

La  funzione  assegnate  deve  avere  il  tipo  del  ritorno  e  dei  parametri  appropriati  al  tipo  del  

puntatore  a  funzione;;  in  caso  contrario,  si  produrrà  un  errore  di  compilazione.  

I  puntatori  a  funzioni  permettono  anche  di  passare  una  funzione  come  argomento  a  un’altra  

funzione,  specificandone  il  nome.  

 

Funzione  qsort()  (Quicksort  per  ordinare  vettori)  

Presente  nella  libreria  search.  Ha  come  parametri:  

(void*)  vettore  →  Array  da  ordinare;;  

(size_t)  10  →  Numero  di  elementi  dell’array  

sizeof(int)  →  Dimensione  in  byte  di  ciascun  elemento  dell’array  

 

Array  di  puntatori  di  funzioni  

Certe  applicazioni  richiedono  di  scegliere  una  funzione  fra  tante,  in  base  alla  valutazione  a  

run-­time  di  determinare  condizioni.  Un  metodo  è  quello  di  usare  un’istruzione  switch  con  

parecchi  case.  Un’altra  soluzione  è  quella  di  utilizzare  un  array  di  puntatori  di  funzione.  Si  può  

selezionare  una  funzione  della  lista  e  chiamarla.  

Sintassi  generale:  

tipoRitorno(*PuntatoreFunz[LunghezzaArray])  (argomenti);;  

Si  può  assegnare  l’indirizzo  delle  funzioni  all’array,  fornendo  le  funzioni  che  sono  già  state  

dichiarate.  

 

 

Puntatori  a  strutture  

Un  puntatore  può  anche  puntare  una  strutture.  Dati  un  tipo  struct  e  una  variabile  di  questo  tipo,  si  

può  definire  un  puntatore  a  questo  tipo  struct  e  inizializzarlo  in  maniera  che  punti  alla  variabile.  

Per  riferirsi  a  una  variabile  della  struct  tramite  un  puntatore  è  necessario  mettere  le  parentesi  

tonde  del  tipo  (*p).nome;;  Per  non  utilizzare  tale  notazione  è  stata  introdotta  la  notazione  freccia  a  

destra;;  l’istruzione  precedente  è  equivalente  a  p-­>nome;;  

 

Gestione  dinamica  della  memoria  

Con  il  termine  heap  si  denota  la  parte  della  memoria  principale  che  può  essere  allocata  

dinamicamente  durante  l'esecuzione  del  programma.  Per  poter  essere  riallocara  può  essere  

deallocata  automaticamente  mediante  un  garbage  recollector  oppure  rimanere  occupata  fino  a  

che  il  programmatore  la  libera  esplicitamente  mediante  opportune  istruzioni.  In  C  la  gestione  

della  memoria  dinamica  avviene  tramite  le  funzioni  malloc,  calloc  e  free.  In  C++  esistono  gli  

operatori  new  e  delete.  

Il  sistema  operativo  assegna  al  programma  specifici  segmenti  della  memoria  principale:  il  code  

segment  (ospita  il  codice),  il  data  segment  (ospita  costanti  e  variabili  globali),  lo  stack  (contiene  

le  variabili  locali,  i  parametri  delle  funzioni  e  le  copie  dei  registri  per  restituire  il  controllo  alle  

funzioni  chiamanti  al  termine  delle  funzioni  chiamate).  La  memoria  rimasta  nello  stack,  lo  heap,  

viene  usata  per  allocare  dinamicamente  le  variabili.  

Gli  operatori  new  e  delete  sono  più  affidabili  di  quelli  del  C  perché  allocano  memoria  in  funzione  

del  tipo  di  dato  da  memorizzare  ed  effettuano  ogni  volta  i  relativi  controlli.  

 

L'operatore  new  

Genera  dinamicamente  una  variabile  di  un  certo  tipo,  assegnando  un  blocco  di  memoria  della  

dimensione  di  quel  tipo.  L'operatore  restituisce  un  puntatore  che  contiene  l'indirizzo  del  blocco  di  

memoria  allocato,  cioè  della  variabile.  La  variabile  sarà  accessibile  deferenziando  il  puntatore.  

La  sintassi  è:  

tipo*  puntatore  =  new  tipo  

tipo*  puntatore  =  new  tipo[dimensione]  (se  array)  

Dove  puntatore  sta  per  il  nome  a  cui  si  assegna  l'indirizzo  dell'oggetto  generato.  Nel  secondo  

fattore  al  puntatore  si  assegna  l'indirizzo  di  memoria  di  un  blocco  sufficientemente  grande  per  

contenere  un  array  con  dimensione  elementi  di  tipo.    

Se  il  puntatore  è  già  stato  definito  si  può  semplicemente  usare  new  per  assegnargli  la  variabile  

dinamica:  

int*  pi;;  

pi  =  new  int;;  

L'effetto  è  sempre  quello  di  creare  una  variabile  intera  senza  nome,  accessibile  deferenziando  il  

puntatore  pi.  

Se  nell'heap  esiste  un  blocco  della  dimensione  richiesta,  new  restituisce  un  puntatore  al  primo  

byte  del  blocco,  altrimenti  restituisce  0  o  NULL.  

La  dimensione  del  blocco  può  anche  essere  allocata  in  runtime,  richiedendola  all'input.  

L'heap  non  è  infinito  e  se  lo  spazio  finisce,  new  restituisce  0  o  NULL  e  quindi  non  dà  errore!    

 

L'operatore  delete  

L'operatore  delete  libera  la  memoria  allocata  dinamicamente  perché  possa  essere  

eventualmente  riallocata  mediante  successive  chiamate  all'operatore  new.  delete  rende  

riutilizzabile  la  memoria  puntata  ma  non  cancella  il  puntatore  che  può  essere  riutilizzato.  È  

sempre  utile  cancellare  lo  spazio  con  delete  una  volta  terminato  l'utilizzo  della  variabile.  Non  si  

può  utilizzare  delete  per  liberare  la  memoria  occupata  da  variabili  ordinarie.  

 

Gestione  dell'overflow  di  memoria  

Per  far  fronte  alla  alla  mancanza  di  spazio  nell'heap  si  può  utilizzare  le  funzione  C  

set_new_handler()  che  serve  per  gestire  gli  errori.  Questa  funzione  è  definita  nell'header  new.h  e  

ha  come  argomento  un  puntatore  a  funzione.  


ACQUISTATO

2 volte

PAGINE

51

PESO

2.60 MB

PUBBLICATO

+1 anno fa


DESCRIZIONE APPUNTO

Riassunto per l'esame di Fondamenti di Informatica, basato su appunti personali e studio autonomo del libro consigliato dal docente Fondamenti di Programmazione in C++ di Luis Joyanes Aguilar, 2a edizione, McGraw-Hill.
Vengono trattati:
- Digitalizzazione dell'informazione (Audio, Video, Testi),
- Basi decimale, Binaria ed Esadecimale,
- Vari tipi di codifica e loro storia,
- Unicode e UTF-8,
- HW/SW,
- Archittettura,
- Assembly,
- C/C++


DETTAGLI
Corso di laurea: Corso di laurea in ingegneria informatica e dell'automazione
SSD:

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher henry0894 di informazioni apprese con la frequenza delle lezioni di Fondamenti di informatica e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Politecnico delle Marche - Univpm o del prof Dragoni Aldo Franco.

Acquista con carta o conto PayPal

Scarica il file tutte le volte che vuoi

Paga con un conto PayPal per usufruire della garanzia Soddisfatto o rimborsato

Recensioni
Ti è piaciuto questo appunto? Valutalo!

Altri appunti di Fondamenti di informatica

Informatica - Introduzione
Appunto
Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni
Appunto
Informatica - Digitalizzazione dei numeri
Appunto
Fondamenti di informatica -archittettura di Von Neumann e Assembly
Appunto