Vous êtes sur la page 1sur 94

Settimana n.

Obiettivi Contenuti
12BHDxx Informatica Problem solving Cenni storici
Diagrammi di flusso e Concetto di programma
Programmazione in C
pseudo codice Diagrammi di flusso
Pseudo codice
Alcuni problemi di esempio

Le tecnologie come fattore abilitante dei


Definizione
cambiamenti industriali e sociali
Linformatica e` la scienza che rappresenta e manipola
le informazioni
1900

1800

3
2000 4

La pervasivit Un po di storia: Abacus

5 6
J.M. Jacquard
B. Pascal (1642)
(punched card loom- 1801)

Il software per la
computazione meccanica

7 8

C. Babbage
Hollerith (punched card -1890)
(analyical engine 1833)

9 10

ENIAC (Eckert-Mauchly 1943-1945) Il computer moderno

1942-57, 1a gen. = tubi a vuoto


1958-63, 2a gen. = transistori
1964-80, 3a gen. = circuiti integrati
1980-oggi, 4a gen. = circuiti VLSI
(futuro) 5a gen. = ?

Penso che nel mondo ci sia mercato


per quattro o cinque computer
Thomas Watson (Presidente IBM,
1943)

11 12
Il computer moderno (Cont.) La storia recente

2005
1942-47 : tubi a vuoto
2000
1990
1958-63 : transistor 1980

1963-80 : circuiti Web 2.0


integrati (MSI) Low cost local Multimedia
storage over the network
Low cost
1981-oggi : circuiti computing
integrati (VLSI)
13 14

I dati digitali: tutto diventa bit Le grandi convergenze

Testi

Dati

Voce
01101100
Musica

Immagini
Filmati
15 16

Il telefono via Internet (VOIP) TV digitale

Satellitare
DTT (digitale terrestre)

17 18
Special - purpose (embedded, dedicated)
I tipi di computer
computer
Esistono due grandi classi di elaboratori: Un elaboratore dedicato (embedded system) un
- Elaboratori di uso generale (general-purpose computer) elaboratore programmato per svolgere funzioni specifiche
- Elaboratori dedicati definite a priori in fase di progetto/produzione
(special-purpose computer) Esempi sono: telefoni cellulari, lettori MP3, computer che
controllano aerei, auto, elettrodomestici...

19 20

Le razze degli elaboratori (general purpose) Server

Un server un elaboratore che fornisce dei servizi a


altri elaboratori (chiamati clients) attraverso una rete
(computer network)

Personal (client) Workstation

Mainframe (host)

Server
21 22

Server Farm Mainframe

Con il termine server farm si fa riferimento allinsieme di Mainframes (colloquialmente indicati anche come Big
elaboratori server collocati in un apposito locale (centro di Iron) sono elaboratori di grandi prestazioni usati
calcolo) presso una media o grande azienda principalmente da grandi imprese per rilevanti
applicazioni software
(mission critical application)

IBM z890
mainframe

23 24
Supercomputer (novembre 2011) Cosa impariamo in questo corso?
Dalla specifica di un problema alla sua realizzazione come
K computer programma da eseguire su un elaboratore
RIKEN Advanced
Institute for
Computational
Science (AICS) Costruzione di
un programma

Potenza: 11 PFLOPS (PETA FLOPS)


11 280 384 000 000 000 moltiplicazioni secondo

25 26

Progettare Difficolt

Problema I punti critici nello sviluppo di un progetto risiedono


essenzialmente in:
- Sviluppo di una soluzione informale
- Formalizzazione di una soluzione
Soluzione Permette una pi semplice traduzione nelle regole di realizzazione

La soluzione di un problema passa generalmente


Soluzione attraverso lo sviluppo di un algoritmo
formale ???????

Realizzazione

27 28

Algoritmo Algoritmo
Con il termine di algoritmo si intende la descrizione precisa Il termine deriva dal tardo latino algorismus che a sua
(formale) di una sequenza finita di azioni che devono volta deriva dal nome del matematico persiano Muhammad
essere eseguite per giungere alla soluzione di un problema ibn Msa 'l-Khwrizm (780-850), che scrisse un noto
trattato di algebra

29 30
Algoritmi e vita quotidiana Algoritmo

Algoritmo: Sequenza di operazioni atte a risolvere un


dato problema
1. metti lacqua - Esempi:
2. accendi il fuoco Una ricetta di cucina
3. aspetta
Istruzioni di installazione di un elettrodomestico
4. se lacqua non
bolle torna a 3
5. butta la pasta Spesso non banale!
6. aspetta un po
- Esempio:
7. assaggia
8. se cruda MCD?
torna a 6 Quale algoritmo seguiamo per ordinare un mazzo di carte?
9. scola la pasta

31 32

Esempio di flusso Altro esempio di flusso

Problema: Calcolo del massimo Problema: Calcolo del massimo


Problema Problema
tra due valori A e B comun divisore (MCD) fra due
valori A e B
Soluzione: Il massimo il pi
grande tra A e B... Soluzione Soluzione: Usiamo la definizione di Soluzione
MCD: il numero naturale pi
Soluzione formale: grande per il quale possono
Soluzione entrambi essere divisi.
1. inizialmente: max = 0
formale
2. se A >B allora max = A; stop
3. altrimenti max = B; stop Soluzione formale: ??? Soluzione
formale

33 34

Stadi di sviluppo di un programma Stadi di sviluppo di un programma

1. Scrittura di un programma Problema


- File sorgente Scrittura
del programma Idea
- Scritto utilizzando un linguaggio
di programmazione - Soluzione

Algoritmo
2. Traduzione di un programma in un Traduzione
- Soluzione formale
formato comprensibile al calcolatore del programma
Articolato in pi fasi
Programma
Gestito automaticamente da un - Traduzione dellalgoritmo in una forma comprensibile ad un elaboratore
programma chiamato traduttore elettronico

In questo corso ci occuperemo del Test


primo punto
Ma importante sapere cosa succede Documentazione
nella fase successiva!
35 36
Formalizzazione della soluzione Formalizzazione della soluzione (Cont.)

La differenza tra una soluzione informale ed una formale Pseudo-codice


sta nel modo di rappresentare un algoritmo: - Vantaggi
- Informale: Descrizione a parole Immediato
- Formale: Descrizione in termini di sequenza di operazioni - Svantaggi
elementari Descrizione dellalgoritmo poco astratta
Interpretazione pi complicata

Esistono vari strumenti per rappresentare una soluzione


in modo formale Diagrammi di flusso
- Pi usati: - Vantaggi
Pseudo-codice Pi intuitivi perch utilizzano un formalismo grafico
Diagrammi di flusso Descrizione dellalgoritmo pi astratta
- Svantaggi
Richiedono lapprendimento della funzione dei vari tipi di blocco

37 38

Traduzione di un programma Cosa vuol dire programmare?

La programmazione consiste nella scrittura di un


File documento (file sorgente) che descrive la soluzione del
Compilatore problema in oggetto
sorgente
- Esempio: Massimo comun divisore tra due numeri

Librerie
Linker Librerie
Librerie In generale non esiste la soluzione ad un certo
File
oggetto problema
- La programmazione consiste nel trovare la soluzione pi
efficiente, secondo una certa metrica, al problema di interesse
Questo file pu essere File
direttamente caricato eseguibile
in memoria ed eseguito

39 40

Cosa vuol dire programmare? (Cont.) Stadi di sviluppo di un programma (Cont.)

Programmare unoperazione creativa!


Problema
- Ogni problema diverso da ogni altro
- Non esistono soluzioni analitiche o universali! Esperienza

Programmare unoperazione complessa Soluzione


- Impensabile un approccio diretto (dal problema al Strumenti automatici e
programma sorgente definitivo) metodi formali
- Tipicamente organizzata per stadi successivi Soluzione
formale
Tecniche di programmazione
automatica

Programma

41 42
Stadi di sviluppo di un programma (Cont.) Stadi di sviluppo di un programma (Cont.)

La costruzione di un programma generalmente Una volta scritto e collaudato il programma, possono


unoperazione iterativa verificarsi le seguenti situazioni:
- Il programma stato scritto non correttamente:
Torno indietro di un livello
Sono previsti passi a ritroso che rappresentano le reazioni
- Il programma descritto male in termini formali, ma corretto
a risultati non rispondenti alle esigenze nelle diverse fasi concettualmente:
Torno indietro di due livelli
La suddivisione in pi fasi permette di mantenere i passi - Il programma errato concettualmente, e necessita di una
differente soluzione:
a ritroso pi brevi possibile (e quindi meno dispendiosi) Torno all'inizio

E' necessario quindi effettuare dei test tra una fase e la


successiva affinch i ricicli siano i pi corti possibili

43 44

Diagrammi di flusso (flow-chart)

Sono strumenti grafici che rappresentano levoluzione


logica della risoluzione del problema

Sono composti da:


Blocchi elementari per descrivere azioni e decisioni
Diagrammi di flusso
-
(esclusivamente di tipo binario)
- Archi orientati per collegare i vari blocchi e per descrivere la
sequenza di svolgimento delle azioni

46

Diagrammi di flusso: Blocchi di inizio/fine Diagrammi di flusso: Blocchi di azione

Start
azione azione
Stop generica di I/O

47 48
Diagrammi di flusso: Blocco di decisione Diagrammi di flusso: Blocco di connessione

V condizione F

49 50

Diagramma di flusso : Esempio Diagramma di flusso : Esempio

Start

Start
1

F
2 5

3 Stop

Stop
4

51 52

Costruzione di diagrammi di flusso Diagrammi di flusso strutturati

Per mezzo dei diagrammi di flusso si possono Definizione formale:


rappresentare flussi logici complicati a piacere - Diagrammi di flusso strutturati: Composti da strutture elementari
indipendenti tra loro
- Struttura elementare = Composizione particolare di blocchi
E per preferibile scrivere diagrammi di flusso strutturati, elementari
che seguano cio le regole della programmazione - Sempre riducibili ad un diagramma di flusso elementare costituito
strutturata da un'unica azione

Cos facendo si ottiene: Rispetto a diagrammi di flusso non strutturati questo


- Maggiore formalizzazione dei problemi implica lassenza di salti incondizionati all'interno del flusso
- Riusabilit del codice logico del diagramma
- Maggiore leggibilit

53 54
Diagrammi di flusso strutturati (Cont.) Sequenza

Un diagramma di flusso detto strutturato se contiene


solo un insieme predefinito di strutture elementari:
- Uno ed uno solo blocco Start
- Uno ed uno solo blocco Stop struttura-1
- Sequenza di blocchi (di azione e/o di input-output)
- If - Then - ( Else )
..
- While - Do
. struttura
- Repeat - Until

struttura-2

55 56

If-Then-Else If-Then

V condizione F V F
condizione

struttura-1 struttura-2 struttura

57 58

While-Do do - while

F struttura
condizione

V
condizione
struttura F
V
59 60
Teorema di Bhm - Jacopini Settimana n.2

Qualunque diagramma di flusso sempre


Obiettivi Contenuti
trasformabile in un diagramma di flusso
Utilizzo del compilatore e Linguaggi di programmazione
strutturato equivalente a quello dato ciclo scrittura- Dati e istruzioni
compilazione-esecuzione. Architettura di un elaboratore
Il linguaggio C
Quindi, qualunque flusso logico pu essere realizzato Uso del compilatore
utilizzando solamente due strutture di controllo: Variabili (tipo int, float)
- Meccanismo di decisione Rappresentazione dei dati
- Meccanismo di ripetizione (loop) numerici e non numerici

61 62

Dalla soluzione al programma Quali linguaggi?

La scrittura del programma vero e proprio praticamente Diversi livelli (di astrazione)
immediata a partire dalla soluzione formale - Linguaggi ad alto livello
Elementi del linguaggio hanno complessit equivalente ai blocchi
dei diagrammi di flusso strutturati (condizionali, cicli,)
I linguaggi di programmazione forniscono infatti costrutti - Esempio: C, C++, Basic, Pascal, Fortran, Java, etc.
di diversa complessit a seconda del tipo di linguaggio - Indipendenti dallhardware
- Linguaggi assembler
Elementi del linguaggio sono istruzioni microarchitetturali
- Dipendenti dallhardware
- Esempio: Assembler del microprocessore Intel Pentium

63 64

Quali linguaggi? (Cont.) Elementi del linguaggio

Esempi: Essendo il linguaggio unastrazione, esistono alcuni


- Linguaggi ad alto livello fondamentali elementi sintattici essenziali per luso del
linguaggio stesso:
if (x > 3) then x = x+1;
- Parole chiave (keyword)
- Dati
- Identificatori
- Linguaggi assembler
- Istruzioni
LOAD Reg1, Mem[1000] Specifico per una specifica
ADD Reg1, 10 architettura (microprocessore)
Gli elementi sintattici definiscono la struttura formale di
tutti i linguaggi di programmazione

65 66
Parole chiave (keyword) Dati

Vocaboli riservati al traduttore per riconoscere altri Vista calcolatore:


elementi del linguaggio - Dato = Insieme di bit memorizzato in memoria centrale
- Le istruzioni sono tutte identificate da una keyword
- Esempio: La keyword PRINT in alcuni linguaggi identifica il
Vista utente:
comando di visualizzazione su schermo
- Dato = Quantit associata ad un certo significato

Non possono essere usate per altri scopi


Il linguaggio di programmazione supporta la vista utente

Costituiscono i mattoni della sintassi del linguaggio


Dato individuato da:
- Un nome (identificatore)
- Una interpretazione (tipo)
- Una modalit di accesso (costante o variabile)

67 68

Identificatore Tipo

Indica il nome di un dato (e di altre entit) in un Indica lintepretazione dei dati in memoria
programma
Legato allo spazio occupato da un dato
Permette di dare nomi intuitivi ai dati
Permette di definire tipi primitivi (numeri, simboli)
Esempio: indipendentemente dal tipo di memorizzazione del
- X, raggio, dimensione, sistema

Nome unico allinterno di un preciso ambiente di


visibilit
- Dati diversi = Nomi diversi!

69 70

Tipo di accesso Astrazione dei dati

Indica la modalit di accesso ai dati:


- Variabili 100
Dati modificabili 101
Valore modificabile in qualunque punto del programma X; intero; 3 102
- Costanti valore=3 103
Dati a sola lettura
a 104 Indirizzi
Valore assegnato una volta per tutte c; carattere;
valore=a 105
106
t; reale;
valore=-11.564 -11.564 107
108

Memoria

71 72
Istruzioni Esempio di programma

Indicano le operazioni che il linguaggio permette di PROGRAM prova; Identificatori


eseguire (traducendole) a livello macchina: // programma di prova Pseudo-istruzione PAROLE CHIAVE
- Pseudo-istruzioni CONSTANTS
Direttive non eseguibili pi = 3.14159
- Istruzioni elementari coeff = 0.19 Specifica di celle di memoria
Operazioni direttamente corrispondenti ad operazioni hardware VARIABLES
Esempio: Interazione con i dispositivi di I/O, modifica/accesso a dati x: INTEGER Specifica di tipo Istruzione
- Istruzioni di controllo del flusso y: REAL di controllo
Permettono di eseguire delle combinazioni di operazioni complesse c: CHARACTER del flusso
BEGIN PROGRAM
x = 2; Istruzioni
elementari Parte
IF (y > 2) THEN y = x * pi;
operativa
PRINT x, y;
END PROGRAM
73 74

Linguaggio di programmazione

Imparare un linguaggio significa conoscere:


- Le parole chiave Architettura
- I tipi predefiniti degli elaboratori
- Le istruzioni e la loro sintassi

In questo corso:
- Linguaggio C

Estensione dei concetti a linguaggi analoghi immediata

75

I blocchi fondamentali dellelaboratore I blocchi fondamentali dellelaboratore

Memoria Memoria Memoria Memoria


centrale di massa
(RAM) (dischi)

Unit Unit Unit Unit


ingresso uscita ingresso uscita

Unit Unit
elaborazione elaborazione
77 78
I chip fondamentali Microprocessore

Un microprocessore (sovente abbreviato come P) un


Microprocessore chip che realizza le funzioni di una central processing
unit (CPU) in un computer o in un sistema digitale

Memoria centrale - RAM


79 80

CPU (Central Processing Unit) Microprocessore

Unit di Unit di Unit di ABUS


decodifica gestione gestione Unit di
istruzioni indirizzi BUS gestione
DBUS
BUS CBUS

ALU Registro
Unit di
controllo

81 82

I Bus (sistema circolatorio del PC) Dispositivi periferici

Dati
Interfaccia
(controller)

Controll
o

83 84
Unit di input/output CPU

Trasformano informazioni dal mondo umano a quello del


computer e viceversa:
- umano = diversi tipi di segnali fisici, analogici, asincroni Registri
- computer = segnali solo elettronici, digitali, sincroni (Memoria locale)

Unit aritmetica
(ALU)

Unit
di controllo

85 86

Registri Unit operativa

Elementi di memoria locale usati per conservare Svolge tutte le elaborazioni richieste (aritmetiche, logiche,
temporaneamente dei dati (es. risultati parziali). grafiche, ...).
E composta di:
Pochi (8...128) - ALU
- flag
- registri
Dimensione di una word (8...64 bit)

87 88

ALU (Arithmetic-Logic Unit) Unit di controllo

Svolge tutti i calcoli (aritmetici e logici) E il cervello dellelaboratore:


- in base al programma fornitole ...
- ed allo stato di tutte le unit ...
Solitamente composta da circuiti combinatori
- decide loperazione da eseguire ...
- ed emette gli ordini relativi

89 90
Ciclo base di un elaboratore CPU e FPU

Central Processing Unit (CPU):


- CPU = UO + UC
- microprocessore (mP) = CPU + frattaglie
Preleva una istruzione
dalla memoria centrale
Floating Point Unit (FPU):
- UO dedicata ai numeri reali
- alias coprocessore matematico
Interpreta listruzione

Esegue listruzione

91 92

Il clock Il clock

Ogni elaboratore contiene un elemento di T = periodo di clock


temporizzazione (detto clock ) che genera un riferimento - unit di misura = s
temporale comune per tutti gli elementi costituenti il f = frequenza di clock ( = 1 / T )
sistema di elaborazione. - unit di misura = s1 = Hz (cicli/s)

T
93 94

Nota Nota

In un Intel Core i7-2700 la frequenza di clock 3.5 GHz Diversi Intel Core i7 e i5 sono costruiti con tecnologia a
- In 3.5 miliardesimi di secondo la luce percorre 1 metro (104.93 32 nm
cm) - Il diametro di un atomo di cesio 0.5 nm
- Un globulo rosso alto 2 000 nm e largo 7 000 nm
- Un capello spesso 100 000 nm

95 96
Tempistica delle istruzioni

Un ciclo-macchina lintervallo di tempo in cui viene


svolta una operazione elementare ed un multiplo intero
del periodo del clock
Lesecuzione di unistruzione richiede un numero intero
di cicli macchina, variabile a seconda del tipo di istruzione
Memoria

97 98

Memoria Indirizzamento

Memorizza i dati e le istruzioni necessarie allelaboratore La memoria organizzata in celle (mimima unit
per operare. accessibile direttamente). Ad ogni cella di memoria
Caratteristiche: associato un indirizzo (numerico) per identificarla
- indirizzamento univocamente.
- parallelismo
- accesso (sequenziale o casuale)

1 7

2 5 8

3 6 9
99 100

Parallelismo Memoria interna

Ogni cella di memoria contiene una quantit fissa di bit: Allinterno dellelaboratore
- identica per tutte le celle (di una certa unit di memoria) E` allo stato solido (chip)
- accessibile con ununica istruzione
Solitamente volatile
- un multiplo del byte
Veloce (nanosecondi, 10-9s)
- minimo un byte (tipicamente una word per la memoria principale
a supporto dell'UO) Quantit limitata (qualche GB)
Non rimovibile
Costosa (0.1 / MB)

101 102
Memoria esterna Memoria RAM (Random Access Memory)

Allesterno dellelaboratore Circuiti integrati


Talvolta rimovibile
Non elettronica (es. magnetica) Il tempo di accesso costante (indipendente dalla cella
Permanente scelta)
Lenta (millisecondi, 10-3 s)
Grande quantit (qualche TB) Ta = costante
Economica (0.1 / GB)
Ormai sinonimo di memoria interna volatile casuale a
lettura e scrittura

103 104

La memoria RAM La memoria centrale

I bit li voglio
nella RAM
Sistema Operativo RAM

Contengo i dati ed i Programmi RAM


programmi
in esecuzione
Memoria Video RAM video

Programma davvio
(boot program) ROM

105 106

Memoria RAM La Famiglia delle DRAM

Le memorie RAM possono essere di due tipi EDO RAM EDO RAM
- SRAM: RAM statiche BEDO RAM
Veloci (10 ns)
SD RAM
Minor impaccamento
Elevato costo per bit DDR2 - DDR3
DRAM (Rambus RAM)
- DRAM: RAM dinamiche
Meno veloci (60 ns) DDR2
Maggior impaccamento (64 Mbit/chip)
Minor costo per bit
Rambus

DDR3

107 108
Le schede delle DRAM Memoria ROM (Read-Only Memory)

SIMM SIMM E un concetto (memorie a sola lettura ) ma anche una


single in-line memory modules classe di dispositivi allo stato solido (memorie a
canale di trasferimento a 32 bit prevalente lettura = molto pi veloce o facile della
DIMM scrittura).
dual in-line memory modules
canale di trasferimento a 32 bit DIMM ROM
RIMM - dati scritti in fabbrica
Rambus in-line memory module
PROM (Programmable ROM)
RIMM - dati scritti dallutente tramite un apparecchio speciale
(programmatore)

109 110

Memoria ROM (Cont.) Unit di controllo

EPROM (Erasable PROM) E il cuore dellelaboratore:


- PROM cancellabile tramite UV - in base al programma fornitole ...
- ed allo stato di tutte le unit ...
- decide loperazione da eseguire ...
EAROM (Electrically Alterable ROM)
- ed emette gli ordini relativi
- PROM cancellabile tramite circuito elettronico speciale

EEPROM, E2PROM (Electrically Erasable PROM)


- scrivibile/cancellabile mediante specifiche istruzioni mentre
installata sul sistema

Flash memory
- EEPROM veloce nella cancellazione (un blocco/tutta invece di un
byte alla volta)
111 112

Unit di controllo: schema funzionale Componenti dellUC

PC (Program Counter)
PC M registro che indica sempre lindirizzo della cella di
memoria che contiene la prossima istruzione da eseguire

IR IR (Instruction Register)
registro che memorizza temporaneamente loperazione
corrente da eseguire

logica di stato Logica di controllo


interpreta il codice macchina in IR per decidere ed emette
controllo comandi gli ordini che le varie unit devono eseguire

113 114
Esecuzione di unistruzione MIPS (Million Instructions Per Second)

Tre fasi distinte: f = frequenza di clock [ Hz = cicli/s ]


- fetch IR M [ PC ] T = periodo di clock = 1 / f [ s ]
PC PC + 1
C = cicli macchina / istruzione
- decode ordini decode(IR)
- execute ready? go! IPS = f / C = 1 / ( T C )
MIPS = IPS / 106

115 116

MFLOPS (Million FLoating-point


Nota
Operations Per Second)
Velocit di elaborazione per problemi di tipo scientifico Calcolatrice tascabile: 10 FLOPS
Tianhe-1 (): 2 566 petaFLOPS
i.e., 2 566 000 000 000 000 000 FLOPS

117 118

Caratteristiche di un bus Tipi fondamentali di bus

Trasporto di un solo dato per volta Un singolo bus suddiviso in tre sotto bus, detti:
- bus dati (DBus)
- bus degli indirizzi (ABus)
Frequenza = n. di dati trasportati al secondo
- bus di controllo (CBus)

Ampiezza = n. di bit di cui costituito un singolo dato

Se mal dimensionato, potrebbe essere un collo di bottiglia M1 M2 I O

119 120
Massima memoria interna
Vecchie CPU Intel per PC
(fisicamente presente)
CPU DBus ABus Cache FPU La dimensione dellAbus determina il max numero di celle
di memoria indirizzabili
8088 8 bit 20 bit No No La dimensione del Dbus indica la dimensione di una
cella di memoria
8086 16 bit 20 bit No No
80286 16 bit 24 bit No No max mem = 2|Abus| x |Dbus| bit

80386 32 bit 32 bit No No


Esempio (Abus da 20 bit, Dbus da 16 bit):
8 KB S - max mem = 220 x 2 byte = 2 MB
80486 32 bit 32 bit
- ossia 1 M celle di memoria, ognuna da 2 byte
Pentium 64 bit 32 bit 8+8KB S
Pentium 3 64 bit 32 bit 8+8/256 S
121 122

Massima memoria esterna Architettura del PC

La memoria esterna (es. dischi) non dipende dallAbus Clock Coproc Cache
perch viene vista come un periferico (di input e/o di Host
CPU (L1)
output) bus
BUS veloce
(AGP)
La massima quantit di memoria esterna dipende dal bus
DRAM Cache
di I/O (quello su cui sono collegati i periferici)
(L2)
BUS veloce
(PCI)

BUS lento LAN


(ISA)

123 124

Architettura di un PC tradizionale floppy


parallela
USB
CPU + cache PS/2
ISA
FSB
scheda PCIe x 16
northbridge RAM
grafica ( AGP )
( custom ) BIOS
N slot PCIe x 1 AGP
southbridge LPC alimentazione
N slot PCI
super I/O
PCI / PCI-X
int. audio
NIC DRAM
grafica FDD keyb IDE
on-board dischi
porte seriale mouse
PATA dischi
SATA USB parallela 125 126
CPU multi-core Esempio: CPU dual-core

Aumentare le prestazioni aumentando la frequenza di Nota: un singolo processo non pu usufruire di pi di un


clock difficile (interferenze EM, dissipazione di calore, core (a meno che il programma, la CPU ed il Sistema
velocit dei componenti): Operativo siano multi-thread).

MIPS f ma anche Potenza (e Temperatura) f


CPU core CPU core
L1 cache L1 cache
quindi:
f0 2f0 I0 2I0 ma T0 2T0

Pi facile aumentare il numero di operazioni svolte


L2 cache
simultaneamente (CPU multi-core):
interfaccia bus
1 core( f0 ) = ( I0 , T0 ) 2 core( f0 ) = ( 2I0 , T0 )
127 128

Pentium IV AMD Athlon 64

Dual core (due cpu sullo stesso chip) Dual core (due cpu sullo stesso chip)
Architettura a 32 bit Architettura a 32/64 bit
Tecnologia CMOS da 90 nm a 130 nm Tecnologia CMOS da 90 nm a 130 nm
Cache Cache
- L1: 8K dati, 12K istruzioni - L1: 64K dati, 64K istruzioni
- L2: da 256K a 2MB - L2: da 512K a 1MB
- L3: 2MB (versioni di punta) - L3: 2MB (versioni di punta)
Clock da 1.5 a 3.8 GHz Clock da 1.8 a 2.4 GHz

129 130

Genesi del linguaggio C

Sviluppato tra il 1969 ed il 1973


presso gli AT&T Bell Laboratories
(Ken Thompson, B. Kernighan, Dennis
Linguaggio C Ritchie)
- Per uso interno
- Legato allo sviluppo del sistema Ken Brian Dennis
operativo Unix Thompson Kernighan Ritchie

Nel 1978 viene pubblicato The C


Programming Language, prima
specifica ufficiale del linguaggio
- Detto K&R

132
Caratteristiche generali del linguaggio C Storia
Il C un linguaggio: Sviluppo
- Imperativo ad alto livello - 1969-1973
... ma anche poco astratto - Ken Thompson e Dennis Ritchie
- Strutturato - AT&T Bell Labs
... ma con eccezioni
- Tipizzato Versioni del C e Standard
Ogni oggetto ha un tipo - K&R (1978)
- Elementare - C89 (ANSI X3.159:1989)
Poche keyword - C90 (ISO/IEC 9899:1990)
- Case sensitive - C99 (ANSI/ISO/IEC 9899:1999, INCITS/ISO/IEC 9899:1999)
Maiuscolo diverso da minuscolo negli identificatori!
- Portabile
Non tutti i compilatori sono standard!
- Standard ANSI
- GCC: Quasi C99, con alcune mancanze ed estensioni
- Borland & Microsoft: Abbastanza C89/C90

133 134

Diffusione attuale Un esempio

I linguaggi attualmente pi diffusi al mondo sono:


- C
- C++, unevoluzione del C #include <stdio.h>
- Java, la cui sintassi tratta da C++
- C#, estremamente simile a Java e C++ int main(void)
{
Il linguaggio C uno dei linguaggi pi diffusi printf("hello, world\n");
La sintassi del linguaggio C ripresa da tutti gli altri
linguaggi principali return 0;
}

135 136

Applicazioni console Modello di applicazioni console

Interazione utente limitata a due casi


- Stampa di messaggi, informazioni e dati a video Scrittura somma.c
- Immissione di un dato via tastiera programma Programma
sorgente in C
Linsieme tastiera+video viene detto terminale
Nessuna caratteristica grafica
Elaborazione Compilatore C
- Sequenziale
- Interattiva somma.exe
- Mono-utente Programma
eseguibile

Visualizzazione
Immissione dati
risultati
137 138
Compilatore C Scrittura del programma

Traduce i programmi sorgenti scritti in linguaggio C in Un sorgente C un normale file di testo


programmi eseguibili Si utilizza un editor di testi
a sua volta un programma eseguibile, a disposizione del - Blocco Note
programmatore - Editor specializzati per programmatori
Controlla lassenza di errori di sintassi del linguaggio
Non serve allutente finale del programma
Ne esistono diversi, sia gratuiti che commerciali

139 140

Editor per programmatori Ambienti integrati

Colorazione ed evidenziazione della sintassi Applicazioni software integrate che contengono al loro
Indentazione automatica interno
- Un editor di testi per programmatori
Attivazione automatica della compilazione
- Un compilatore C
Identificazione delle parentesi corrispondenti
- Un ambiente di verifica dei programmi (debugger)
Molti disponibili, sia gratuiti che commerciali IDE: Integrated
Development
Environment

141 142

Identificatori Identificatori (Cont.)

Si riferiscono ad una delle seguenti entit: Caratteristiche:


- Costanti - Esterni: Gli oggetti del sistema
- Variabili Case insensitive
- Tipi Significativi almeno i primi 6 caratteri
- Sottoprogrammi - Interni: Le entit del programma
- File Case sensitive
Significativi almeno i primi 31 caratteri
- Etichette
- Riservati:
Parole chiave del linguaggio
Regole: Elementi della libreria C standard
- Iniziano con carattere alfabetico o _
- Contengono caratteri alfanumerici o _

143 144
Commenti Parole chiave
Testo libero inserito allinterno del programma Riservate!
Non viene considerato dal compilatore
Nel C standard sono 32
Serve al programmatore, non al sistema! auto double int struct
break else long switch
Formato:
- Racchiuso tra /* */ case enum register typedef
- Non possibile annidarli char extern return union
- Da // fino alla fine della linea
const float short unsigned
Esempi: continue for signed void
/* Questo un commento ! */
default goto sizeof volatile
/* Questo /* risulter in un */ errore */
// Questo un altro commento do if static while

145 146

Struttura di un programma C Struttura di un programma C (Cont.)

Struttura generale: Parte dichiarativa globale


- Elenco degli oggetti che compongono il programma e specifica
delle loro caratteristiche
Categoria degli oggetti
Parte dichiarativa globale - Tipicamente dati
main() Tipo degli oggetti
- Numerici, non numerici
{
Parte dichiarativa locale main
Parte esecutiva - Parola chiave che indica il punto di inizio del programma quando
viene eseguito dal sistema operativo
} - Contenuto delimitato da parentesi graffe { }

147 148

Struttura di un programma C (Cont.) Struttura di un programma C (Cont.)

Parte dichiarativa locale Programma minimo:


- Elenco degli oggetti che compongono il main e specifica delle
loro caratteristiche
main() Start

Parte esecutiva {
- Sequenza di istruzioni } Stop
- Quella che descriviamo con il diagramma di flusso!

file prova.c

149 150
Notazione Pre-processore C

Per specificare la sintassi di unistruzione utilizziamo un La compilazione C passa attraverso un passo preliminare
formalismo particolare che precede la vera e propria traduzione in linguaggio
macchina

Simboli utilizzati
Il programma che realizza questa fase detto
- <nome> Un generico nome
pre-processore
Esempio: <numero> indica che va specificato un generico valore
numerico
Funzione principale: Espansione delle direttive che
- [ <op> ] Unoperazione opzionale iniziano con il simbolo #

- c Uno specifico simbolo Direttive principali:


Esempio: ? indica che comparir il carattere ? esplicitamente - #include
- #define
- nome Una parola chiave
151 152

Direttiva #include Direttiva #include

Sintassi: Esempio:
file.c mydef.h
- #include <file> #include mydef.h
int x,y;
<file> pu essere specificato come: ....
double z;
<<nomefile>> per includere un file di sistema int main() {
- Esempio: ...
#include <stdio.h> }
<nomefile> per includere un file definito dal programmatore
- Esempio:
#include miofile.h Pre-processore
int x,y;
double z;
Significato: ....
<file> viene espanso ed incluso per intero nel file sorgente int main() {
...
}

153 154

I dati numerici

Sono quelli pi usati in ambito scientifico nei moderni


sistemi di elaborazione tutti gli altri tipi di dato sono
trasformati in dati numerici

Tutti i tentativi di elaborare direttamente dati non


Dati numerici o sono falliti o si sono mostrati molto pi
inefficienti che non effettuare lelaborazione solo dopo
aver trasformato i dati in forma numerica

156
Come contiamo? Sistemi di numerazione

Il sistema di numerazione del mondo occidentale (sistema Non posizionali (additivi):


indo-arabo) : - egiziano
- decimale - romano
- posizionale - greco

252 = 2 100 + 5 10 + 2 1
= 2 102 + 5 101 + 2 100

157 158

Sistemi di numerazione Sistemi di numerazione

Posizionali: Ibridi:
- babilonese (2 cifre, sessagesimale) - cinese
- inuit, selti, maya (ventesimale)
- indo-arabo (decimale)

159 160

Sistema di numerazione posizionale Bit e interruttori

Occorre definire la base B da cui discendono varie


caratteristiche: Interruttore ha due stati
- cifre = { 0, 1, 2, ..., B-1 } (aperto-chiuso, ON_OFF)
- peso della cifra i-esima = Bi
- rappresentazione (numeri naturali) su N cifre

N 1 Aperto = 0
A ai B i

i 0
Chiuso = 1

161 162
Il sistema binario Alcuni numeri binari

Base = 2 0 ... 0 1000 ... 8


1 ... 1 1001 ... 9
Cifre = { 0, 1 } 10 ... 2 1010 ... 10
11 ... 3 1011 ... 11
100 ... 4 1100 ... 12
Esempio: 101 ... 5 1101 ... 13
1012 = 1 22 + 0 21 + 1 20 110 ... 6 1110 ... 14
=14+11 111 ... 7 1111 ... 15
= 510

163 164

Conversione di numeri naturali


Alcune potenze di due
da binario a decimale
20 ... 1 29 ... 512 Si applica direttamente la definizione effettuando la
21 ... 2 210 ... 1024 somma pesata delle cifre binarie:
22 ... 4 211 ... 2048
23 ... 8 212 ... 4096 11012 = 1 23 + 1 22 + 0 21 + 1 20
24 ... 16 213 ... 8192 = 8+4+0+1
25 ... 32 214 ... 16384
26 ... 64 215 ... 32768 = 1310
27 ... 128 216 ... 65536
28 ... 256

165 166

Terminologia Terminologia

Bit
Byte 10110110
Word
Double word/Long word
MSB LSB
Most Least
Significant Significant
Bit Bit

167 168
Limiti del sistema binario Limiti del sistema binario
(rappresentazione naturale) (rappresentazione naturale)
Consideriamo numeri naturali in binario:
- 1 bit ~ 2 numeri ~ { 0, 1 }2 ~ [ 0 1 ]10 bit simboli min10 max10
- 2 bit ~ 4 numeri ~ { 00, 01, 10, 11} 2 ~ [03]10 4 16 0 15
8 256 0 255
Quindi in generale per numeri naturali a N bit: 16 65 536 0 65 535
- combinazioni distinte
32 4 294 967 296 0 4 294 967 295
2N
- intervallo di valori
0 x 2N 1 [ base 10 ]
(000...0) x (111...1) [ base 2 ]

169 170

Somma in binario Somma in binario

Regole base: Si effettuano le somme parziali tra i bit dello stesso peso,
0 + 0 = 0 propagando gli eventuali riporti:
0 + 1 = 1
1 + 0 = 1 11
1 + 1 = 0 ( carry = 1 ) 0110 +
0111 =
1101

171 172

Sottrazione in binario Sottrazione in binario

Regole base: Si effettuano le somme parziali tra i bit dello stesso peso,
0 - 0 = 0 propagando gli eventuali riporti:
0 - 1 = 1 ( borrow = 1 )
1 - 0 = 1 1
1 - 1 = 0 0001 -
0110 =
0011

173 174
Overflow Overflow

Si usa il termine overflow per indicare lerrore che si Nella somma in binario puro si ha overflow quando:
verifica in un sistema di calcolo automatico quando il - si lavora con numero fisso di bit
risultato di unoperazione non rappresentabile con la - si ha carry sul MSB
medesima codifica e numero di bit degli operandi.

175 176

Overflow - esempio Il sistema ottale

Ipotesi: operazioni su numeri da 4 bit codificati in binario base = 8 (talvolta indicata con Q per Octal)
puro - cifre = { 0, 1, 2, 3, 4, 5, 6, 7 }
- utile per scrivere in modo compatto i numeri binari ( 3:1 )

0101 +
1110 = 1 0 1 1 1 0 0 1 2

-------- ---
10011
2 7 1 8

overflow

177 178

Il sistema esadecimale Rappresentazione dei numeri interi relativi

base = 16 (talvolta indicata con H per Hexadecimal)


- cifre = { 0, 1, ..., 9, A, B, C, D, E, F }
- utile per scrivere in modo compatto i numeri binari ( 4:1 )

10111001 2

B 9 16

+ 25 -9
C C
179 180
I numeri con segno Codifica modulo e segno

Il segno dei numeri pu essere solo di due tipi: un bit per il segno (tipicamente il MSB):
- positivo ( + ) 0 = segno positivo ( + )
- negativo ( ) 1 = segno negativo ( )

E quindi facile rappresentarlo in binario ... ma non N-1 bit per il valore assoluto (anche detto modulo)
sempre la soluzione pi semplice quella migliore!
Modulo e segno
Complemento a uno
Complemento a due
Eccesso X
segno modulo
1 bit N-1 bit

181 182

Modulo e segno: esempi Modulo e segno

Usando una codifica su quattro bit:


Svantaggi:
- doppio zero (+ 0, - 0)
+ 310 0011M&S - operazioni complesse
310 1011M&S - es. somma A+B
0000M&S + 010
1000M&S 010 A>0 A<0
B>0 A+B B - |A|
B<0 A - |B| - ( |A| + |B| )

183 184

Modulo e segno: limiti Codifica in complemento a due

In una rappresentazione M&S su N bit: In questa codifica per un numero a N bit:


- il MSB ha peso negativo (pari a -2N-1)
- ( 2N-1 - 1 ) x + ( 2N-1 - 1 ) - gli altri bit hanno peso positivo

Esempi: Ne consegue che MSB indica sempre il segno:


-0=+ 1=
- 8 bit = [ -127 ... +127 ]
- 16 bit = [ -32 767 ... +32 767 ]
Esempi (complemento a due su 4 bit):
- 1000CA2 = -23 = -810
- 1111CA2 = -23 + 22+ 21 + 20 = -8 +4 +2 +1 = -110
- 0111CA2 = 22 + 21 + 20 = 710

185 186
Complemento a 2 Somma e sottrazione in CA2

La somma e sottrazione si effettuano direttamente,


La rappresentazione in complemento a due oggi la pi
senza badare ai segni degli operandi:
diffusa perch semplifica la realizzazione dei circuiti per
eseguire le operazioni aritmetiche ACA2 + BCA2 ACA2 + BCA2
Possono essere applicate le regole binarie a tutti i bit ACA2 - BCA2 ACA2 - BCA2

187 188

Somma e sottrazione in CA2 Somma in CA2 - esempio

La sottrazione si pu effettuare sommando al


minuendo il CA2 del sottraendo: 00100110 + 11001011

ACA2 BCA2 ACA2 + BCA2 00100110 +


11001011 =
(nota: nella sottrazione B gi codificato in CA2 ma gli ---------------
11110001
si applica loperazione CA2)

verifica: 38 + ( 53) = 15

189 190

Sottrazione in CA2 - esempio Overflow nella somma in CA2

00100110 11001011 Operandi con segno discorde: non si pu mai verificare


overflow.
00100110 -
11001011 = Operandi con segno concorde: c overflow quando il
--------------- risultato ha segno discorde.
01011011
In ogni caso, si trascura sempre il carry sul MSB.
verifica: 38 ( 53) = 91

191 192
Esempio overflow in CA2 (somma) Overflow nella sottrazione in CA2

Poich la differenza in CA2 ricondotta ad una somma, in


0101 + 1110 + generale per loverflow valgono le stesse regole della
0100 = 1101 = somma.
---------- ----------
Fa eccezione il caso in cui il sottraendo il valore pi
1001 11011 =
negativo possibile (100); in questo caso la regola :
1011
- minuendo negativo: non si pu mai verificare overflow
- minuendo positivo: c sempre overflow
overflow! OK
Nota: come si giustifica questa regola?
(5+4=9) ( -2 + -3 = -5 )
impossibile in CA2 su 4 bit

193 194

Esempio overflow in CA2 (sottrazione) Formato IEEE-754

Mantissa nella forma 1, (valore max < 2)


3 (-8) -3 (-8)
Base dellesponente pari a 2
0011 + 1101 +
1000 = 1000 =
---------- ---------- IEEE 754 SP:
1011 10101 = segno esponente mantissa
0101
1 bit 8 bit 23 bit
overflow! OK ( +5 )
+11 impossibile in
CA2 su 4 bit IEEE 754 DP:
segno esponente mantissa

1 bit 11 bit 52 bit


195 196

IEEE-754 SP: intervallo di valori Problemi

Numero fisso del numero di bit


I numeri sono rappresentati da sequenze di cifre
underflow ( 0 )
Problemi:
- Intervallo di rappresentazione
- Overflow
- Precisione

-1038 -10-38 0 10-38 1038

overflow (NaN)

197 198
Errore assoluto (e ) Errore assoluto - esempi

Dato un numero A composto da N cifre, lerrore assoluto Qualunque sia la base ed il numero di cifre, lerrore
della sua rappresentazione non superiore alla quantit assoluto dei numeri interi sempre non superiore a 1:
non nulla pi piccola (in valore assoluto)
rappresentabile con N cifre 510 e 110 2710 e 110
Nota: talvolta lerrore assoluto anche detto precisione
(assoluta) di un numero
Lerrore assoluto dei numeri razionali dipende dal
numero di cifre usate per rappresentarli:
- es. 0.510 e 0.110
- es. 0.5010 e 0.0110
- es. 1.010 e 0.110

199 200

Elaborazione dellinformazione
Interi o floating-point?
non numerica
Interi:
- precisione = 1
- intervallo di valori limitato
- es. (32 bit) ~ 2 000 000 000
- es. (64 bit) ~ 9 000 000 000 000 000 000
Floating-point:
- precisione = variabile
- es. (32 bit) ~ 9 999 999 10 38
- es. (64 bit) ~ 9 999 999 999 999 999 10 308

201 202

Informazione non numerica Rappresentazioni numeriche

Se in quantit finita, si pu mettere in corrispondenza coi Dati N bit


numeri interi. - si possono codificare 2N oggetti distinti
- usabili per varie rappresentazioni numeriche

Esempio (usando 3 bit):

oggetti binari 000 001 010 011 100 101 110 111
num. naturali 0 1 2 3 4 5 6 7
num. relativi (M&S) +0 +1 +2 +3 -0 -1 -2 -3

00 01 10 num. relativi (CA2) +0 +1 +2 +3 -4 -3 -2 -1

203 204
Caratteri Codice ASCII

Occorre una codifica standard perch il genere di Usato anche nelle telecomunicazioni.
informazione pi scambiata: Usa 8 bit (originariamente 7 bit per US-ASCII) per
- codice ASCII (American Standard Code for Information rappresentare:
Interchange)
- 52 caratteri alfabetici (a...z A...Z)
- codice EBCDIC (Extended BCD Interchange Code)
- 10 cifre (0...9)
- segni di interpunzione (,;!?...)
- caratteri di controllo

205 206

Caratteri di controllo Codice ASCII - esempio

CR ( 13 ) Carriage Return
LF, NL ( 10 ) New Line, Line Feed 01000001 A 00100000
FF, NP ( 12 ) New Page, Form Feed 01110101 u 01110100 t
HT (9) Horizontal Tab 01100111 g 01110101 u
VT ( 11 ) Vertical Tab 01110101 u 01110100 t
NUL (0) Null 01110010 r 01110100 t
BEL (7) Bell 01101001 i 01101001 i
EOT (4) End-Of-Transmission 00100000 00100001 !
... ... ... 01100001 a

207 208

Rappresentazione di un testo in
UNICODE e UTF-8
formato ASCII
Unicode esprime tutti i caratteri di tutte le lingue del Caratteri in codice ASCII
mondo (pi di un milione).
UTF-8 la codifica di Unicode pi usata: Ogni riga terminata dal terminatore di riga:
- 1 byte per caratteri US-ASCII (MSB=0) in MS-DOS e Windows = CR + LF
- 2 byte per caratteri Latini con simboli diacritici, Greco, Cirillico, in UNIX = LF
Armeno, Ebraico, Arabo, Siriano e Maldiviano in MacOS = CR
- 3 byte per altre lingue di uso comune
- 4 byte per caratteri rarissimi
Pagine talvolta separate da FF
- raccomandata da IETF per e-mail

209 210
Codifiche o formati di testo/stampa Formato testi

Non confondere il formato di un file word, con codice


ASCII!!
Un testo pu essere memorizzato in due formati
- Formattato: sono memorizzate sequenze di byte che definiscono
laspetto del testo (e.g., font, spaziatura)
- Non formattato: sono memorizzati unicamente i caratteri che
compongono il testo

Caratteri Caratteri
di controllo di stampa(ASCII)

211 212

PDF Dichiarazione di dati

Il PDF (Portable Document Format) un formato open di In C, tutti i dati devono essere dichiarati prima di essere
file basato su un linguaggio di descrizione di pagina utilizzati!
sviluppato da Adobe Systems per rappresentare
documenti in modo indipendente dallhardware e dal La dichiarazione di un dato richiede:
software utilizzati per generarli o per visualizzarli
- Lallocazione di uno spazio in memoria atto a contenere il dato
Un file PDF pu descrivere documenti che contengono - Lassegnazione di un nome a tale spazio in memoria
testo e/o immagini a qualsiasi risoluzione
In particolare, occorre specificare:
- Nome (identificatore)
- Tipo
- Modalit di accesso (variabile o costante)

213 214

Tipi base (primitivi) Modificatori dei tipi base

Sono quelli forniti direttamente dal C Sono previsti dei modificatori, identificati da parole chiave
da premettere ai tipi base
- Segno:
Identificati da parole chiave! signed/unsigned
- char caratteri ASCII - Applicabili ai tipi char e int
signed: Valore numerico con segno
- int interi (complemento a 2)
unsigned: Valore numerico senza segno
- float reali (floating point singola precisione) - Dimensione:
- double reali (floating point doppia precisione) short/long
- Applicabili al tipo int
- Utilizzabili anche senza specificare int
La dimensione precisa di questi tipi dipende
dallarchitettura (non definita dal linguaggio)
- |char| = 8 bit = 1 Byte sempre

215 216
Modificatori dei tipi base (Cont.) Variabili

Interi Locazioni di memoria destinate alla memorizzazione di


- [signed/unsigned] short [int] dati il cui valore modificabile
- [signed/unsigned] int Sintassi:
- [signed/unsigned] long [int]
<tipo> <variabile> ;
Reali
- float <variabile>: Identificatore che indica il nome della variabile
- double
Sintassi alternativa (dichiarazioni multiple):

<tipo> <lista di variabili>;

<lista di variabili>: Lista di identificatori separati da ,

217 218

Variabili (Cont.) Esempi di nomi

Esempi:
int x;
char ch; a b a1 a2
long int x1, x2, x3;
double pi;
short int stipendio; num n N somma max
long y, z;

area perimetro perim


Usiamo nomi significativi!
- Esempi:
int x0a11; /* NO */ n_elementi Nelementi risultato
int valore; /* SI */
float raggio; /* SI */
trovato nome risposta

219 220

Esempi Esempi

a 3.1
i 0 float a, b ;
float pigr ;
int i, j ; b
int N ;
float Nav, Qe ; 2.0
int x ; j 2 a = 3.1 ;
i = 0 ;
b = 2.0 ; pigr 3.1415
pigr = 3.1415926 ;
j = 2 ; N
N = 100 ; 100 Nav = 6.02e23 ;
Qe = 1.6e-19 ;
x = -3124 ; Nav 6.021023
x -3124
Qe 1.61019
221 222
Valore contenuto Valore contenuto

Ogni variabile, in ogni istante di tempo, possiede un certo Ogni variabile, in ogni istante di tempo, possiede un certo
valore valore
Le variabili appena definite hanno valore ignoto Le variabili appena definite hanno valore ignoto
- Variabili non inizializzate - Variabili non inizializzate
In momenti diversi il valore pu cambiare In momenti diversi il valore pu cambiare

a ? ? a 37
t t
definizione definizione inizializzazione
Es. int a; Es. a = 37;

223 224

Valore contenuto Valore contenuto

Ogni variabile, in ogni istante di tempo, possiede un certo Ogni variabile, in ogni istante di tempo, possiede un certo
valore valore
Le variabili appena definite hanno valore ignoto Le variabili appena definite hanno valore ignoto
- Variabili non inizializzate - Variabili non inizializzate
In momenti diversi il valore pu cambiare In momenti diversi il valore pu cambiare

? 37 a -4 ? 37 -4 a -3
t t
definizione inizializzazione altra definizione inizializzazione altra incremento
assegnazione assegnazione Es. a = a+1;
Es. a = -4;
225 226

Costanti Costanti (Cont.)


Locazioni di memoria destinate alla memorizzazione di dati il cui Esempi di valori attribuibili ad una costante:
valore non modificabile
- Costanti di tipo char:
Sintassi: f
const <tipo> <costante> = <valore> ; - Costanti di tipo int, short, long
26
<costante> : Identificatore che indica il nome della costante 0x1a,0X1a
<valore> : Valore che la costante deve assumere 26L
26u
Esempi: 26UL
- const double PIGRECO = 3.14159;
- Costanti di tipo float, double
- const char SEPARATORE = $;
- const float ALIQUOTA = 0.2; -212.6
-2.126e2, -2.126E2, -212.6f
Convenzione:
- Identificatori delle constanti tipicamente in MAIUSCOLO

227 228
Costanti speciali Visibilit delle variabili

Caratteri ASCII non stampabili e/o speciali Ogni variabile utilizzabile allinterno di un preciso
ambiente di visibilit (scope)
Ottenibili tramite sequenze di escape
\<codice ASCII ottale su tre cifre>
Variabili globali
- Definite allesterno del main()
Esempi:
- \007
- \013 Variabili locali
- Definite allinterno del main()
- Pi in generale, definite allinterno di un blocco
Caratteri predefiniti
- \b backspace
- \f form feed
- \n line feed
- \t tab
229 230

Struttura a blocchi Visibilit delle variabili: Esempio

In C, possibile raccogliere istruzioni in blocchi racchiudendole tra int n;


parentesi graffe
double x;
main() {
Significato: Delimitazione di un ambiente di visibilit di oggetti
(variabili, costanti)
int a,b,c;
double y;
Corrispondente ad una sequenza di istruzioni
{
int d;
Esempio:
double z;
{ }
int a=2; }
int b; a e b sono definite
solo allinterno del blocco! - n,x: Visibili in tutto il file
b=2*a; - a,b,c,y: Visibili in tutto il main()
} - d,z: Visibili nel blocco delimitato dalle parentesi graffe

231 232

Settimana n.3

Obiettivi Contenuti
Struttura base di un scanf e printf a livello
programma in C. elementare
Espressioni aritmetiche ed
Costrutti condizionali
semplici operatori base (+ - * / %) Istruzioni elementari
Operatori relazionali
Condizioni complesse
Algebra di Boole
Costrutti condizionali
Costrutto if e if-else
annidati
Operatori logici e di
incremento
If annidati

233
Istruzioni elementari Assegnazione

Corrispondono ai blocchi di azione dei diagrammi di Sintassi:


<variabile> = <valore>
flusso:
Non unuguaglianza!
Due categorie: - Significato: <valore> viene assegnato a <variabile>
- <variabile> e <valore> devono essere di tipi compatibili
- <variabile> deve essere stata dichiarata precedentemente!
- Assegnazione - Esempi:
int x;
float y;
x = 3;
- Input/output (I/O) y = -323.9498;

Pu essere inclusa nella dichiarazione di una variabile


- Esempi:
int x = 3;
float y = -323.9498;

235 236

Istruzioni di I/O I/O formattato

Diverse categorie in base al tipo di informazione letta o Output


scritta: - Istruzione printf()
- I/O formattato
- I/O a caratteri
Input
- I/O per righe
- Istruzione scanf()
Richiede la nozione di stringa. Come tale, sar trattata in seguito

Nota: Lutilizzo di queste istruzioni richiede linserimento di una


In C, le operazioni di I/O non sono gestite tramite vere e direttiva
proprie istruzioni, bens mediante opportune funzioni. #include <stdio.h>
- Il concetto di funzione verr introdotto successivamente; in allinizio del file sorgente
questa sezione le funzioni di I/O saranno impropriamente - Significato: includi il file stdio.h
chiamate istruzioni
- Contiene alcune dichiarazioni

237 238

Istruzione printf() Istruzione printf(): Esempi

Sintassi:
printf(<formato>,<arg1>,...,<argn>); int x=2;
<formato>: Sequenza di caratteri che determina il formato di stampa di float z=0.5;
ognuno dei vari argomenti
char c=a;
output
Pu contenere:
- Caratteri (stampati come appaiono) printf(%d %f %c\n,x,z,c);
- Direttive di formato nella forma %<carattere>
2 0.5 a
%d intero
%u unsigned
%s stringa
%c carattere
%x esadecimale output
%o ottale
%f float printf(%f***%c***%d\n,z,c,x);
%g double
0.5***a***2
- <arg1>,...,<argn>: Le quantit (espressioni) che si vogliono stampare
Associati alle direttive di formato nello stesso ordine!

239 240
Istruzione scanf() Significato di scanf()

Sintassi: Istruzioni di input vanno viste come assegnazioni


scanf(<formato>,<arg1>,...,<argn>); dinamiche:
- Lassegnazione dei valori alle variabili avviene al tempo di
<formato>: come per printf esecuzione e viene deciso dallutente
<arg1>,...,<argn>: le variabili cui si vogliono assegnare valori

IMPORTANTE:
Assegnazioni tradizionali = Assegnazioni statiche
I nomi delle variabili vanno precedute dalloperatore & che indica - Lassegnazione dei valori alle variabili scritta nel codice!
lindirizzo della variabile (vedremo pi avanti il perch)

Esempio:
int x;
float z;
scanf(%d %f, &x, &z);

241 242

I/O formattato avanzato I/O formattato avanzato (Cont.)

Le direttive della stringa formato di printf e scanf - scanf:


sono in realt pi complesse %[*][max dim][dimensione]<carattere>
[*]: Non fa effettuare lassegnazione (ad es., per saltare un dato in input)
- printf: [max dim]: Dimensione massima in caratteri del campo
%[flag][min dim][.precisione][dimensione]<carattere> [dimensione]: Uno tra:
[flag]: Pi usati h argomento short
- Giustificazione della stampa a sinistra
l argomento long
+ Premette sempre il segno
carattere: Visto in precedenza
[min dim]: Dimensione minima di stampa in caratteri
[precisione]: Numero di cifre frazionarie (per numeri reali)
[dimensione]: Uno tra:
h argomento short
l argomento long
carattere: Visto in precedenza

243 244

printf() e scanf(): Esempio Espressioni


#include <stdio.h>
Combinazioni di variabili, costanti ed operatori
main()
{
int a; Il valore di unespressione pu essere assegnato ad una variabile:
float b; <variabile> = <espressione>
printf(Dammi un numero intero (A): ); - Significato:
if(scanf(%d,&a) != 1) <espressione> valutata ed il valore ottenuto assegnato a <variabile>
{ - <variabile> e <espressione> devono essere di tipi compatibili
printf(Errore!\n);
return 1;
} Esistono varie categorie di operatori, applicabili a tipi di dato diversi:
printf(Dammi un numero reale (B): ); - Operatori aritmetici
if(scanf(%f,&b) != 1) - Operatori relazionali
{
printf(Errore!\n); - Operatori logici
return 1; - Operatori su bit
}
- Operatori di modifica del tipo (cast)
printf(A= %d\n,a);
printf(B= %f\n,b); - Operatori di calcolo della dimensione di un tipo: sizeof()
}

245 246
Operatori aritmetici Divisione tra interi: Esempio

Quattro operatori (per numeri reali e interi): #include <stdio.h>


+ - * / main()
Per numeri interi, esiste loperatore % che ritorna il resto {
della divisione intera int a, b;

printf(Dammi un numero intero (A): );


Stesse regole di precedenza dellaritmetica ordinaria scanf(%d,&a);
printf(\n);
Esempi: printf(Dammi un numero intero (B): );
int x=5; scanf(%d,&b);
int y=2; printf(\n);
int q, r; printf(A div B = %d\n, a/b);
q = x / y; // (q = 2, troncamento) printf(A mod B = %d\n, a%b);
r = x % y; // (r = 1) }
247 248

Quesito Soluzione

Che operazione svolge il seguente frammento di Che operazione svolge il seguente frammento di
programma? programma?
a = 10;
b = 25; a = 10;
a = b ; b = 25;
b = a ; a = b ;
b = a ;

tempo
a = 10 b = 25 a = 25 b = 25

249 250

Quesito Soluzione

Come fare a scambiare tra di loro i valori di due variabili? E necessario utilizzare una variabile di appoggio

tmp = a;
a = b;
b = tmp;
a 7 b 12

tempo
tmp = 7 a = -12 b=7

251 252
Operatori di confronto in C Operatori relazionali

Uguaglianza Operano su quantit numeriche o char e forniscono un


- Uguale: a == b risultato booleano:
- Diverso: a != b < <= > >= == !=
Ordine
- Maggiore: a > b Il risultato sempre di tipo int
- Minore: a < b
- risultato = 0 FALSO
- Maggiore o uguale: a >= b
- risultato 0 VERO
- Minore o uguale: a <= b

253 254

La logica degli elaboratori elettronici La logica Booleana

Nel 1847 George Boole introdusse un nuovo tipo di logica


formale, basata esclusivamente su enunciati di cui fosse
possibile verificare in modo inequivocabile la verit o la
Ma quale logica
falsit.
del $@#?! ...

255 256

Variabili Booleane Operatori Booleani

Variabili in grado di assumere solo due valori: Operatori unari (es. Not )
- VERO op : B B
- FALSO

Operatori binari (es. And )


In ogni problema importante distinguere le variabili op : B2 B
indipendenti da quelle dipendenti.

Descritti tramite una tavola della verit (per N operandi,


la tabella ha 2N righe che elencano tutte le possibili
combinazioni di valori delle variabili indipendenti ed il
valore assunto dalla variabile dipendente)

257 258
Tavola della verit (truth table) Espressioni Booleane

Unespressione Booleana una combinazione di variabili


ed operatori Booleani.
A B A op B
falso falso falso Ad esempio:
A e ( non B )
falso vero falso
vero falso falso
vero vero vero

259 260

Funzioni Booleane Operatore NOT

Una funzione Booleana unapplicazione molti-a-uno:


f : BN B
A A
Ad esempio:
f (A, B) = A e ( non B )
falso vero
vero falso

Nota: per comodit grafica talvolta la


negazione indicata con un apice dopo la
variabile o lespressione negata (es. A)
261 262

La porta INV / NOT Operatore AND

A B AB

A Y falso falso falso


falso vero falso
Y = A vero falso falso
vero vero vero

263 264
La porta AND Operatore OR

A B A+B
A
Y falso falso falso
B
falso vero vero

Y=AB vero falso vero


vero vero vero

265 266

La porta OR Operatore XOR

A B AB
A falso falso falso
Y
B
falso vero vero

Y=A+B vero falso vero


vero vero falso

267 268

La porta XOR Propriet commutativa e associativa

AB=BA
A A+B=B+A
Y
B
A B C = ( A B) C = A (B C) = (A C)
B
Y = A B = A B + A B A + B + C = (A + B) + C = A + (B + C) = (A + C) + B

269 270
Propriet distributiva Teorema di De Morgan

Teorema:
A(B+C)=AB+AC
f ( a, b, ..., z; +, ) = f ( a, b, ..., z; , + )
A+(BC)=(A+B)(A+C)
ovvero (negando entrambi i membri):
f ( a, b, ..., z; +, ) = f ( a, b, ..., z; , + )

Ad esempio:
- A + B = ( A B )
- ( A + B ) = A B

271 272

Dimostrazioni in algebra Booleana Dimostrazioni: un esempio

Siccome lalgebra Booleana contempla solo due valori


A+(BC)=(A+B)(A+C)?
possibile effettuare le dimostrazioni (di propriet o
teoremi) considerando esaustivamente tutti i casi
possibili: A B C A+B C (A + B) (A + C)
- 2 variabili 4 combinazioni 0 0 0 0 +00= 0 (0+0) (0+0) = 0
- 3 variabili 8 combinazioni 0 0 1 0 +01= 0 (0+0) (0+1) = 0
- 4 variabili 16 combinazioni 0 1 0 0 +10= 0 (0+1) (0+0) = 0
- ecc. 0 1 1 0 +11= 1 (0+1) (0+1) = 1
1 0 0 1 +00= 1 (1+0) (1+0) = 1
1 0 1 1 +01= 1 (1+0) (1+1) = 1
1 1 0 1 +10= 1 (1+1) (1+0) = 1
1 1 1 1 +11= 1 (1+1) (1+1) = 1

273 274

Dal transistor al chip Dal problema al circuito


transistore
Dato un problema per ottenere il circuito corrispondente si
10 applicano i seguenti passi:
porta logica
1. Individuare le variabili booleane
( logic gate ) 2. Creare la tabella di verit
3. Generare la funzione F a partire dalla tabella di verit
10 100,000 4. Progettare il circuito usando le porte logiche coerentemente con F

circuito integrato ( chip )

piedino ( pin )
275 276
Memoria Istruzione if

E importante non solo fare calcoli, ma anche Sintassi:


memorizzare dati (es. i risultati parziali di una lunga if (<condizione>)
Falso
Vero
sequenza di operazioni). <blocco1> condizione

A questo fine si usa un elemento logico speciale: il flip- [else


blocco1 blocco2
flop. <blocco2>]
- elemento base dei circuiti con memoria
- memorizza un bit <condizione>: Espressione booleana
<blocco1>: Sequenza di istruzioni
Se la sequenza contiene pi di una istruzione, necessario
racchiuderle tra parentesi graffe

Significato:
- Se vera <condizione>, esegui le istruzioni di <blocco1>,
altrimenti esegui quelle di <blocco2>
277 278

Istruzione if : Esempio Operatori logici

Leggere due valori A e B, calcolarne la differenza in Operano su espressioni booleane e forniscono un risultato
valore assoluto D = |A-B| e stamparne il risultato booleano:
! && ||
main() NOT AND OR
{ Equivalenti agli operatori booleani di base
int A,B,D; - Stesse regole di precedenza
NOT > AND > OR
scanf(%d %d,&A,&B); Esempi:
if (A > B) - (x>0) && (x<10) (x compreso tra 0 e 10)
D = A-B; - (x1>x2) || (x1 == 3)
else
D = B-A; Le espressioni logiche sono valutate da sinistra a destra
printf(%d\n,D);
} La valutazione viene interrotta non appena il risultato
univocamente determinato
279 280

Operatori logici (Cont.) Scelte annidate

Nelle istruzioni del


blocco vero o del V F
Operatore Sintassi C1
Esempio blocco else, possibile
booleano in C inserire altri blocchi di A1
scelta V F
C2 B
AND && (x>=a)&&(x<=b) In tal caso la seconda
scelta risulta annidata
OR || (v1>=18)||(v2>=18) allinterno della prima A2 A3

A4
NOT ! !(a>b)

281 282
Settimana n.4 Istruzione switch

Sintassi:
switch (<espressione>)
Obiettivi Contenuti {
Concetto di ciclo Costrutto switch case <costante1>:
espressione
<blocco1>
Cicli semplici Cast e sizeof
break;
Cicli annidati Costrutto while case <costante2>:
Ciclo for <blocco2>
break;
Ciclo Do-while blocco1 blocco2 blocco default
...
Istruzioni break e continue default:
Concetto di ciclo annidato <blocco default>
ed esempio }
<espressione>: Espressione a valore numerico
Problem solving su dati
<blocco1>, <blocco2>, : Sequenza di istruzioni (no parentesi graffe!)
scalari
283 284

Istruzione switch (Cont.) Istruzione switch (Cont.)

Significato: switch ( e )
- In base al valore di <espressione>, esegui le istruzioni del case {
corrispondenti case v1:
A1 ; e=...
- Nel caso nessun case venga intercettato, esegui le istruzioni
break ; e=v1 e=v2

altrimenti
corrispondenti al caso default
e=v3
case v2: A1
NOTE: A2 ; A2
break ;
- I vari case devono rappresentare condizioni mutualmente A3
ESCLUSIVE! case v3: ...
- I vari case vengono eseguiti in sequenza A3 ;
An
Per evitare questo, si usa listruzione break allinterno di un blocco break ;
...........
default:
An ;
}
285 286

Istruzione switch: Esempio Operatori di incremento


int x; Per le assegnazioni composte pi comuni sono previsti
... degli operatori espliciti:
switch (x) { ++ --
case 1:
printf(Sono nel caso 1\n); Casi particolari degli operatori composti dei precedenti
break;
case 2:
Significato:
printf(Sono nel caso 2\n);
- Operatore ++ -> +=1
break; - Operatore -- -> -=1
default:
printf(N caso 1 n caso 2\n);
Esempi:
break;
- x++;
}
- valore--;

287 288
Operatori di incremento (Cont.) Rango delle espressioni aritmetiche

Possono essere utilizzati sia in notazione prefissa che in In C, possibile lavorare con operandi non dello stesso tipo
notazione postfissa Le operazioni aritmetiche avvengono dopo aver promosso tutti gli
operandi al tipo di rango pi alto:

Prefissa: La variabile viene modificata prima di essere _Bool


utilizzata in unespressione char
short
unsigned short
int
Postfissa: La variabile viene modificata dopo averla unsigned int
long
utilizzata in unespressione unsigned long
long long
unsigned long long
float
Esempio: Assumendo x=4: double
long double
- Se si esegue y=x++, si otterr come risultato x=5 e y=4;
- Se si esegue y=++x, si otterr come risultato x=5 e y=5;

289 290

Operatori di cast Operatori di cast: Esempio

In alcuni casi, pu essere necessario convertire esplicitamente #include <stdio.h>


unespressione in uno specifico tipo
- Quando le regole di conversione automatica non si applicano
main()
- Esempio: int i; double d; {
lassegnazione i = d; fa perdere informazione int a, b;

printf(Dammi un numero intero (A): );


Sintassi:
scanf(%d,&a);
( <tipo> ) <espressione>;
printf(Dammi un numero intero (B): );
- Significato: Forza <espressione> ad essere interpretata come se fosse
di tipo <tipo> scanf(%d,&b);
if(b==0)
Esempio: printf(Errore: divisione per zero!!\n);
... else
double f; printf(A / B = %f\n, ((float)a)/b);
f = (double) 10; }
291 292

Operatore sizeof() Operatore sizeof(): Esempio

E possibile calcolare il numero di byte utilizzato dai tipi di dato di #include <stdio.h>
base utilizzando loperatore sizeof
main()
Sintassi: {
sizeof (<tipo>) printf(tipo n.byte\n);
printf(----------- ------\n);
Ritorna il numero di byte occupato da <tipo> printf(char %d\n, sizeof(char));
printf(int %d\n, sizeof(int));
printf(long %d\n, sizeof(long));
Esempio:
unsigned int size; printf(long long %d\n, sizeof(long long));
size = sizeof(float); /* size = 4 */ printf(float %d\n, sizeof(float));
printf(double %d\n, sizeof(double));
Luso delloperatore sizeof() pu essere esteso al calcolo dello printf(long double %d\n, sizeof(long double));
spazio occupato da espressioni, vettori e strutture }

293 294
Flusso di esecuzione ciclico Istruzione while

Sintassi:
Prima del A while (<condizione>)
ciclo <blocco>

Istruzioni B <condizione>: Una condizione Booleana


<blocco>: Sequenza di istruzioni
che vengono
Se pi di una istruzione, va racchiuso tra graffe
ripetute C

V Realizza la struttura di tipo while


Condizione condizione
D? F
di ripetizione V
F Significato:
- Ripeti <blocco> finch
E
blocco
Dopo il ciclo <condizione> vera

295 296

Notazione grafica (while) Istruzione while: Esempio

Leggere un valore N, calcolare la somma S dei primi N


A numeri interi e stamparla
Ingresso
Condizione
#include <stdio.h>
V F main() {
C Corpo int N, i, S;
i = 1; S = 0; /* inizializzazioni */
scanf (%d, &N);
B while (i <= N) {
S = S+i; /* operazione iterativa */
i++; /* aggiornamento condizione */
}
Ritorno Uscita printf (Somma = %d\n, S); /* output */
}
D
297 298

Anatomia di un ciclo Istruzione for

Conviene concepire il ciclo come 4 fasi Sintassi:


- Inizializzazione for (<inizializzazioni>; <condizione>; <incremento>)
- Condizione di ripetizione <blocco>
- Corpo
- Aggiornamento <inizializzazioni>: Le condizioni iniziali prima del ciclo
<condizione>: Una condizione booleana
<incremento>: Incremento della variabile diconteggio
<blocco>: Sequenza di istruzioni
Se contiene pi di una istruzione, va racchiuso tra graffe

Tutti i campi possono essere vuoti!

299 300
Istruzione for (Cont.) Istruzione for (Cont.)

Istruzione di Significato:
inizializzazione I - Equivalente a:

<inizializzazioni>
while (<condizione>) {
V F
for ( I; C; A ) C <blocco>
<incremento>
{ }
B ; Istruzione di
} aggiornamento B
Realizza un ciclo basato su conteggio
Tipicamente contiene una variabile indice che serve da iteratore:
A - Parte da un valore iniziale (inizializzazione)
- Arriva ad un valore finale (condizione)
Corpo Condizione - Attraverso uno specifico incremento (incremento)

301 302

Istruzione for (Cont.) Esercizio

Esempio: Introdurre da tastiera 100 numeri interi, e calcolarne la


- Leggere un carattere ch ed un intero N, e stampare una riga di N media. Si controlli che ogni numero inserito sia compreso
caratteri ch
Esempio: N=10, ch=* output = **********
tra 0 e 30; in caso contrario, il numero deve essere
- Formulazione iterativa: ignorato
Ripeti N volte loperazione stampa ch
- Soluzione: Analisi:
#include <stdio.h> - Problema iterativo
main() { - Media=?
int N, i;
char ch; - Controllo del valore inserito

scanf(%d %c, &N, &ch);


for (i=0; i<N; i++)
printf(%c, ch); /*senza \n !!!!*/
printf(\n);
}

303 304

Esercizio: Soluzione for e while


#include <stdio.h>
Il ciclo for pu essere considerato un caso particolare
main() {
int valore, i, Totale=0, M=0; del ciclo while
const int N = 100;
for (i=0; i<N; i++) /* per ogni valore introdotto */
{ In generale si usa:
scanf(%d, &valore);
if (valore < 0 || valore > 30) /* controllo validit */
- for per cicli di conteggio
printf(Valore non valido); Numero di iterazioni note a priori
else Condizione di fine ciclo tipo conteggio
{ /* caso normale */
Totale += valore; /* accumula nuovo valore in Totale */
- while per cicli generali
M ++; /* ho letto un dato in pi */ Numero di iterazioni non note a priori
} Condizione di fine ciclo tipo evento
}
printf(La media : %f\n, (float)Totale/M);
}

305 306
Cicli for con iterazioni note Cicli annidati

Alcuni problemi presentano una struttura


int i ; int i ; bidimensionale
- Loperazione iterativa stessa pu essere espressa come unaltra
for ( i=0; i<N; i=i+1 ) for ( i=1; i<=N; i=i+1 ) iterazione
{ {
....... .......
} } Realizzazione: Un ciclo che contiene un altro ciclo

Struttura:
int i ; int i ; for (...)
{
for ( i=N; i>0; i=i-1 ) for ( i=N-1; i>=0; i=i-1) for (...)
{ { {
....... ....... ...
}
} }
}

307 308

Cicli while annidati Cicli while annidati

V F V F V F
C C C
while( C )
{
V F V F
C2 while( C2 ) C2
{
B B2 ;
B2 } B2
}

309 310

Esempio Istruzione do

i = 0 ; Sintassi:
do
while( i<N ) <blocco>
{ while (<condizione>);
j = 0 ;
while( j<N ) <condizione>: Una condizione booleana
{ <blocco>: Sequenza di istruzioni
printf("i=%d - j=%d\n", i, j); Se pi di una istruzione, va racchiuso tra graffe

j = j + 1 ; Realizza la struttura di tipo repeat


blocco
}
Significato:
i = i + 1 ; V condizione
- Ripeti <blocco> finch
} <condizione> vera F
311 312
Istruzione do (Cont.) Istruzione do (Cont.)

Esempio:
A - Leggere un valore N controllando che il valore sia positivo.
In caso contrario, ripetere la lettura

#include <stdio.h>
main() {
B
int n;
V F do
C scanf (%d, &n);
while (n <= 0);
}

D
313 314

Istruzione do (Cont.) Interruzione dei cicli

sempre possibile trasformare un ciclo di tipo do in un Il linguaggio C mette a disposizione due istruzioni per
ciclo di tipo while semplice, anticipando e/o duplicando modificare il normale flusso di esecuzione di un ciclo:
una parte delle istruzioni - break:
Termina il ciclo
Lesecuzione continua dalla prima istruzione dopo la fine del ciclo
Esempio:
#include <stdio.h>
- continue:
main() {
Termina literazione corrente
int n; Lesecuzione continua con la prossima iterazione del ciclo
scanf (%d, &n);
while (n <= 0)
scanf (%d, &n);
}

315 316

Interruzione dei cicli (Cont.) break e continue

Trasformano i cicli in blocchi non strutturati In termini di diagrammi di flusso (esempio: ciclo while):
- Usare con cautela (e possibilmente non usare)
- Si pu sempre evitare luso di break/continue!
F F
condizione condizione
Usabili in ogni tipo di ciclo (while, for, do) V V
break continue

blocco blocco

317 318
break : Esempio break : Esempio (Cont.)

Acquisire una sequenza di numeri interi da tastiera; Versione senza break (strutturata)
terminare loperazione quando si legge il valore 0. int valore, finito = 0;
while (scanf("%d", &valore) && !finito)
Versione con break {
if (valore == 0)
int valore; {
while (scanf("%d", &valore)) printf("Valore non consentito\n");
{ finito = 1;
if (valore == 0) }
{ else
printf("Valore non consentito\n");
{
break; /* esce dal ciclo */
/* resto delle istruzioni del ciclo */
}
}
/* resto delle istruzioni del ciclo */ }
}

319 320

continue : Esempio continue : Esempio (Cont.)

Acquisire una sequenza di numeri interi da tastiera; Versione senza continue (strutturata)
ignorare i numeri pari al valore 0.
int valore;
while (scanf("%d", &valore))
Versione con continue {
if (valore == 0)
int valore;
{
while (scanf("%d", &valore)) printf("Valore non consentito\n");
{ }
if (valore == 0) else {
{ /* resto delle istruzioni del ciclo */
printf("Valore non consentito\n"); }
continue; /* va a leggere un nuovo valore */ }
}
/* resto delle istruzioni del ciclo */
}

321 322

Settimana n.5 Variabili e vettori

dato1
dato2
Obiettivi Contenuti
35 35
Vettori Definizione di vettori 7 7 dato
dato3
Dimensionamento statico dato4
14
dei vettori 14 32
dato5 32 -9
Operazioni elementari:
lettura, stampa, copia, -9 dato6 2
confronto di vettori 2 631
dato7 dato8
-18
631 dato9 -18 4
4 dato10 7
7
323 324
Da evitare... ...cos meglio!
int main(void)
{
int dato1, dato2, dato3, dato4, dato5 ;
int dato6, dato7, dato8, dato9, dato10 ; int main(void)
. . . . . {
scanf("%d", &dato1) ; int dato[10] ;
scanf("%d", &dato2) ; . . . . .
scanf("%d", &dato3) ; for( i=0; i<10; i++)
. . . scanf("%d", &dato[i]) ;
scanf("%d", &dato10) ;
for( i=9; i>=0; i--)
printf("%d\n", dato10) ; printf("%d\n", dato[i]) ;
printf("%d\n", dato9) ; }
printf("%d\n", dato8) ;
. . .
printf("%d\n", dato1) ;
}
325 326

Vettori Dichiarazione di un vettore

Insiemi di variabili dello stesso tipo aggregate in ununica entit Sintassi:


- Identificate globalmente da un nome <tipo> <nome vettore> [<dimensione>];
- Singole variabili ( elementi) individuate da un indice, corrispondente
alla loro posizione rispetto al primo elemento
- Lindice degli elementi parte da 0 Accesso ad un elemento:
- Gli elementi di un vettore sono memorizzati in celle di memoria <nome vettore> [<posizione>]
contigue!
Esempio:
a a a a0 a1 a2 a3 a4
int v[10];

- Definisce un insieme di 10 variabili intere


v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]

327 328

Dichiarazione di un vettore (Cont.) Inizializzazione di un vettore

E possibile assegnare un valore iniziale ad un vettore (solo) al


int dato[10] ; momento della sua dichiarazione

Equivalente ad assegnare OGNI elemento del vettore

Tipo di dato Nome del Numero di Sintassi (vettore di N elementi):


{<valore 0>, <valore 1>, ... ,<valore N-1>};
base vettore elementi Esempio:
int lista[4] = {2, 0, -1, 5};

NOTA: Se vengono specificati meno di N elementi, linizializzazione


assegna a partire dal primo valore. I successivi vengono posti a zero.
- Esempio:
int s[4] = {2, 0, -1};
/* s[0]=2, s[1]=0, s[2]=-1, s[3]=0 */

329 330
Vettori e indici Uso di una cella di un vettore

Lindice che definisce la posizione di un elemento di un Lelemento di un vettore utilizzabile come una qualsiasi
vettore DEVE essere intero! variabile:
- Non necessariamente costante! - utilizzabile allinterno di unespressione
Pu essere unespressione complessa (purch intera) tot = tot + dato[i] ;
- utilizzabile in istruzioni di assegnazione
dato[0] = 0 ;
Esempi:
- utilizzabile per stampare il valore
double a[100]; /* a vettore di double */
printf("%d\n", dato[k]) ;
double x;
- utilizzabile per leggere un valore
int i, j, k;
scanf("%d\n", &dato[k]) ;

x = a[2*i+j-k]; /* corretto! */

331 332

Vettori e cicli Direttiva #define

I cicli sono particolarmente utili per scandire un vettore Sintassi:


#define <costante> <valore>

Utilizzo tipico: Applicazione iterativa di unoperazione sugli


<costante>: Identificatore della costante simbolica
elementi di un vettore
Convenzionalmente indicato tutto in maiuscolo
<valore>: Un valore da assegnare alla costante
Schema:

Utilizzo:
int data[10];
- Definizione di costanti simboliche
for (i=0; i<10; i++)
- Maggiore leggibilit
{
- Maggiore flessibilt
// operazione su data[i]
Il cambiamento del valore della costante si applica a tutto il file!
}

333 334

Direttiva #define (Cont.) Direttiva #define (Cont.)

Esempio:
- #define PI 3.1415
- #define N 80
#define N 10 Definizione
- ... della
- double z = PI * x; costante
- int vect[N]; int main(void)
{ Uso della
int dato[N] ; costante
. . .
}

335 336
Modificatore const Sintassi

Stessa sintassi per dichiarare una variabile


Parola chiave const
int main(void) Definizione Valore della costante specificato dal segno =
{ della
Definizione terminata da segno ;
const int N = 10 ; costante
Necessario specificare il tipo (es. int)
int dato[N] ; Uso della Il valore di N non si pu pi cambiare
costante
. . .
} const int N = 10 ;

337 338

Stampa vettore di interi Lettura vettore di interi

printf("Vettore di %d interi\n", N) ; printf("Lettura di %d interi\n", N) ;

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


{ {
printf("Elemento %d: ", i+1) ; printf("Elemento %d: ", i+1) ;
printf("%d\n", v[i]) ; scanf("%d", &v[i]) ;
} }

339 340

Copia di un vettore Copia di un vettore

35 12 35 35
7 2 7 7
14 73 14 14 /* copia il contenuto di v[] in w[] */
32 -12 32 32
-9 0 -9 -9 for( i=0; i<N; i++ )
2 0 Copia v in w 2 2 {
w[i] = v[i] ;
631 -17 631 631 }
-18 44 -18 -18
4 1 4 4
7 17 7 7
v w v w
341 342
Esercizio 1 Esercizio 1: Soluzione
#include <stdio.h>
Leggere 10 valori interi da tastiera, memorizzarli in un main()
vettore e calcolarne il minimo ed il massimo {
int v[10];
int i, max, min;

Analisi: for (i=0; i<10; i++)


scanf(%d, &v[i]);
- Il calcolo del minimo e del massimo richiedono la scansione
dellintero vettore /* uso il primo elemento per inizializzare min e max*/
max = v[0];
- Il generico elemento viene confrontato con il minimo corrente ed min = v[0];
il massimo corrente
for (i=1; i<10; i++) {
Se minore del minimo, aggiorno il minimo if (v[i] > max)
Se maggiore del massimo, aggiorno il massimo max = v[i];
- Importante linizializzazione del minimo/massimo corrente! if (v[i] < min)
min = v[i];
}
printf("Il massimo e': %3d\n", max);
printf("Il minimo e' : %3d\n", min);
}

343 344

Esercizio 2 Esercizio 2: Soluzione

Scrivere un programma che legga un valore decimale #include <stdio.h>


main()
minore di 1000 e lo converta nella corrispondente {
int v[10] = {0};
codifica binaria int i=9; /* ultima posizione del vettore */
unsigned N; /* unsigned perch positivo */

printf("Inserire un numero positivo (<1000): ");


Analisi: scanf("%d", &N);

- Usiamo lalgoritmo di conversione binaria visto a lezione if (N > 1000)


printf("Errore: il numero deve essere < 1000\n");
Divisioni sucessive per 2 else {
Si memorizzano i resti nella posizione del vettore di peso while(N != 0) {
v[i] = (N % 2); /* resto della divisione per 2! */
corrispondente N = N/2; /* divido N per 2 */
- La cifra meno significativa lultima posizione del vettore! i--;
}
- Essenziale determinare la dimensione massima del vettore
for (i=0; i<10; i++)
Per codificare un numero < 1000 servono 10 bit (210=1024) printf("%d", v[i]);
printf("\n");
}
}

345 346

Settimana n.6 Ricerca di un elemento

Dato un valore numerico, verificare


Obiettivi Contenuti - se almeno uno degli elementi del vettore uguale al valore
numerico
Ricerche in Vettori Ricerca di esistenza - in caso affermativo, dire dove si trova
Flag Ricerca di universalit - in caso negativo, dire che non esiste
Funzioni Ricerca di duplicati Si tratta di una classica istanza del problema di ricerca di
Problem solving su dati esistenza``
vettoriali
Definizione di Funzioni
Passaggio di parametri e
valore di ritorno

347 348
Ricerca di un elemento: Esempio (1/3) Ricerca di un elemento: Esempio (2/3)

trovato = 0 ;
pos = -1 ;
int dato ; /* dato da ricercare */
int trovato ; /* flag per ricerca */
for( i=0 ; i<N ; i++ )
int pos ; /* posizione elemento */
{
if( v[i] == dato )
...
{
trovato = 1 ;
printf("Elemento da ricercare? ");
pos = i ;
scanf("%d", &dato) ;
}
}

349 350

Ricerca di un elemento: Esempio (3/3) Varianti

Altri tipi di ricerche


- Contare quante volte presente lelemento cercato
- Cercare se esiste almeno un elemento maggiore (o minore) del
if( trovato==1 ) valore specificato
{ - Cercare se esiste un elemento approssimativamente uguale a
printf("Elemento trovato " quello specificato
"alla posizione %d\n", pos+1) ; - ...
}
else
{
printf("Elemento non trovato\n");
}

351 352

Ricerca del massimo Ricerca del massimo: Esempio (1/2)

Dato un vettore (di interi o reali), determinare float max ; /* valore del massimo */
- quale sia lelemento di valore massimo int posmax ; /* posizione del max */
- quale sia la posizione in cui si trova tale elemento
...
Conviene applicare la stessa tecnica per lidentificazione max = r[0] ;
del massimo gi vista in precedenza posmax = 0 ;
- Conviene inizializzare il max al valore del primo elemento
for( i=1 ; i<N ; i++ )
{
if( r[i]>max )
{
max = r[i] ;
posmax = i ;
}
}
353 354
Ricerca del massimo: Esempio (2/2) Ricerca di esistenza o universalit

Lutilizzo dei flag pu essere utile quando si desiderino


verificare delle propriet su un certo insieme di dati
- vero che tutti i dati verificano la propriet?
- vero che almeno un dato verifica la propriet?
- vero che nessun dato verifica la propriet?
- vero che almeno un dato non verifica la propriet?
printf("Il max vale %f e si ", max) ;
printf("trova in posiz. %d\n", posmax) ;

355 356

Esempi Formalizzazione

Verificare che tutti i dati inseriti dallutente siano positivi vero che tutti i dati verificano la propriet?
Determinare se una sequenza di dati inseriti dallutente - x : P(x)
crescente vero che almeno un dato verifica la propriet?
Due numeri non sono primi tra loro se hanno almeno un - x : P(x)
divisore comune vero che nessun dato verifica la propriet?
- esiste almeno un numero che sia divisore dei due numeri dati - x : not P(x)
Un poligono regolare ha tutti i lati di lunghezza uguale vero che almeno un dato non verifica la propriet?
- ogni coppia di lati consecutivi ha uguale lunghezza - x : not P(x)

357 358

Realizzazione (1/2) Realizzazione (2/2)

Esistenza: x : P(x) Universalit: x : P(x) Esistenza: x : not P(x) Universalit: x : not P(x)
- Inizializzo flag F = 0 - Inizializzo flag F = 1 - Inizializzo flag F = 0 - Inizializzo flag F = 1

- Ciclo su tutte le x - Ciclo su tutte le x - Ciclo su tutte le x - Ciclo su tutte le x


Se P(x) vera Se P(x) falsa Se P(x) falsa Se P(x) vera
- Pongo F = 1 - Pongo F = 0 - Pongo F = 1 - Pongo F = 0

- Se F = 1, lesistenza - Se F = 1, luniversalit - Se F = 1, lesistenza - Se F = 1, luniversalit


dimostrata dimostrata dimostrata dimostrata
- Se F = 0, lesistenza - Se F = 0, luniversalit - Se F = 0, lesistenza - Se F = 0, luniversalit
negata negata negata negata

359 360
Esempio 1 Esempio 2

Verificare che tutti i dati inseriti dallutente siano positivi Determinare se una sequenza di dati inseriti dallutente
crescente
int positivi ;
... int crescente ;
positivi = 1 ; ...
i = 0 ; crescente = 1 ;
while( i<n ) precedente = INT_MIN ;
{ i = 0 ;
... while( i<n )
if( dato <= 0 ) {
positivi = 0 ; ...
.... if( dato < precedente )
i = i + 1 ; crescente = 0 ;
} precedente = dato ;
if( positivi == 1 ) ....
printf("Tutti positivi\n"); i = i + 1 ;
}

361 362

Esempio 3 Esempio 4

Due numeri non sono primi tra loro se hanno almeno un Un poligono regolare ha tutti i lati di lunghezza uguale
divisore comune
int rego ;
int A, B ; ...
int noprimi ; rego = 1 ;
... precedente = INT_MIN ;
noprimi = 0 ; i = 0 ;
i = 2 ; while( i<n )
while( i<=A ) {
{ ...
... if( lato != precedente )
if( (A%i==0) && (B%i==0) ) rego = 0 ;
noprimi = 1 ; precedente = lato ;
.... ....
i = i + 1 ; i = i + 1 ;
} }

363 364

Ricerca di duplicati Sottoprogrammi

Un vettore v contiene elementi duplicati? Un programma realistico pu consistere di migliaia di


istruzioni
for( i=0 ; i<N ; i++ )
{ Sebbene fattibile, una soluzione monolitica del
duplicato = 0; problema:
for( j = 0; j<N ; j++ ) - Non molto produttiva:
{ Riuso del codice?
if( (v[i]== v[j]) && (i != j) ) Comprensione del codice?
{ - Non intuitiva:
duplicato = 1 ; Tendenza ad organizzare in modo strutturato
} Struttura gerarchica a partire dal problema complesso fino a
sottoproblemi sempre pi semplici
}
if( duplicato == 1 )
printf( v[%d] duplicato\n, i); Approccio top-down
}
365 366
Approccio top-down Approccio top-down (Cont.)

Decomposizione del problema in sottoproblemi pi Esempio: Pulizia di una casa


semplici

Ripetibile su pi livelli
Pulizia
casa
Sottoproblemi terminali = Risolvibili in modo semplice
Pulizia Pulizia Pulizia
bagno cucina camera

Togli Togli Togli


Lava Lucida Lava Lucida Lava Lucida
polvere polvere polvere

367 368

Approccio top-down (Cont.) Funzioni e procedure

I linguaggi di programmazione permettono di suddividere Procedure:


le operazioni in modo simile tramite sottoprogrammi - Sottoprogrammi che NON ritornano un risultato
- Detti anche funzioni o procedure

Funzioni:
La gerarchia delle operazioni si traduce in una gerarchia - Sottoprogrammi che ritornano un risultato (di qualche tipo
di sottoprogrammi primitivo o non)

main() una funzione! In generale, procedure e funzioni hanno dei parametri


(o argomenti)
- Vista funzionale:

parametri f risultato

369 370

Funzioni e procedure in C Definizione di una funzione

Nel C K&R: Stabilisce un nome per un insieme di operazioni


- Esistono solo funzioni (tutto ritorna un valore)
- Si pu ignorare il valore ritornato dalle funzioni
Sintassi:
<tipo risultato> <nome funzione> (<parametri formali >)
{
Dal C89 (ANSI) in poi:
<istruzioni>
- Funzioni il cui valore di ritorno deve essere ignorato (void)
}
- Funzioni void procedure
- Se la funzione non ha un risultato, <tipo risultato> deve essere
void
- Per ritornare il controllo alla funzione chiamante, nelle
<istruzioni> deve comparire una istruzione
return <valore>; se non void
return; se void

371 372
Definizione di una funzione (Cont.) Prototipi

Tutte le funzioni sono definite allo stesso livello del Cos come per le variabili, buona pratica dichiarare
main() allinizio del programma le funzioni prima del loro uso
- NON si pu definire una funzione dentro unaltra (prototipi)

main() una funzione! Sintassi:


- Tipo del valore di ritorno: int - Come per la definizione, ma si omette il contenuto (istruzioni)
- Parametri: Vedremo pi avanti! della funzione

373 374

Prototipi: Esempio Funzioni e parametri


#include <stdio.h> Parametri e risultato sono sempre associati ad un tipo
int func1(int a);
int func2(float b);
...
Esempio:
float media(int a, int b)
main ()
{
int a
} media() float
int b
int func1(int a)
{ I tipi di parametri e risultato devono essere rispettati
quando la funzione viene utilizzata!
}

int func2(float b) Esempio:


{
float x; int a,b;
} x = media(a, b);
375 376

Utilizzo di una funzione Utilizzo di una funzione: Esempio


#include <stdio.h>
Deve rispettare linterfaccia della definizione
int modabs(int v1, int v2); //prototipo

Utilizzata come una normale istruzione main() {


int x,y,d;
<variabile> = <nome funzione> (<parametri attuali>); scanf(%d %d,&x,&y);
d = modabs(x,y); // utilizzo
printf(%d\n,d);
Pu essere usata ovunque }

- Una funzione pu anche invocare se stessa (funzione ricorsiva) int modabs (int v1, int v2) // definizione
{
int v;
if (v1>=v2) {
v = v1-v2;
} else {
v = v2-v1;
}
return v;
}

377 378
Parametri formali e attuali Parametri formali e attuali (Cont.)

E importante distinguere tra: Vista funzionale:


- Parametri formali: - Definizione:
Specificati nella definizione di una funzione
- Parametri attuali: int x
Specificati durante il suo utilizzo Func double
double y
Esempio:
- funzione Func - Utilizzo:
Definizione: double Func(int x,double y)
- Parametri formali: (x,y) a*2 => x
Utilizzo: double z = Func(a*2, 1.34); Func double
- Parametri attuali: (Risultato di a*2, 1.34) 1.34 => y

379 380

Passaggio dei parametri Passaggio dei parametri: Esempio


#include <stdio.h>
In C, il passaggio dei parametri avviene per valore
void swap(int a, int b);
- Significato: Il valore dei parametri attuali viene copiato in variabili
locali della funzione main() {
int x,y;
scanf(%d %d,&x,&y);
Implicazione: printf(%d %d\n,x,y);
swap(x,y);
- I parametri attuali non vengono MAI modificati dalle istruzioni /* x e y NON VENGONO MODIFICATI */
della funzione
printf(%d %d\n,x,y);
}

void swap(int a, int b)


{
int tmp;
tmp = a;
a = b;
b = tmp;
return;
}
381 382

Passaggio dei parametri (Cont.) Passaggio dei parametri: Esempio


#include <stdio.h>
E possibile modificare lo schema di passaggio per valore
in modo che i parametri attuali vengano modificati dalle void swap(int *a, int *b);

istruzioni della funzione main() {


int x,y;
scanf(%d %d,&x,&y);
Passaggio per indirizzo (by reference) printf(%d %d\n,x,y);
swap(&x,&y); Passo lindirizzo
- Parametri attuali = indirizzi di variabili di x e y
/* x e y SONO ORA MODIFICATI */
- Parametri formali = puntatori al tipo corrispondente dei printf(%d %d\n,x,y);
parametri attuali }

- Concetto: void swap(int *a, int *b)


Passando gli indirizzi dei parametri formali posso modificarne {
il valore int tmp;
tmp = *a;
- La teoria dei puntatori verr ripresa in dettaglio pi avanti *a = *b; Uso *a e *b
Per il momento sufficiente sapere che: *b = tmp; come interi
- &<variabile> fornisce lindirizzo di memoria di <variabile> return;
- *<puntatore> fornisce il dato contenuto nella variabile puntata da <puntatore> }

383 384
Passaggio dei parametri (Cont.) Vettori e funzioni

Il passaggio dei parametri per indirizzo indispensabile Le funzioni possono avere come parametri dei vettori o
quando la funzione deve ritornare pi di un risultato matrici:
- Parametri formali
Si indica il nome del vettore, con [ ] senza dimensione
- Parametri attuali
Il nome del vettore SENZA [ ]
Parametri F Risultati
Il nome del vettore indica lindirizzo del primo elemento,
quindi il vettore passato per indirizzo!

385 386

Vettori e funzioni (Cont.) Esercizio

Conseguenza: Scrivere una funzione nonnull() che ritorni il numero di


- Gli elementi di un vettore passato come argomento vengono elementi non nulli di un vettore di interi passato come
SEMPRE modificati! parametro

ATTENZIONE: Dato che il vettore passato per


Soluzione:
indirizzo, la funzione che riceve il vettore come
int nonnull(int v[], int dim)
argomento non ne conosce la lunghezza!!!! {
Allinterno della funzione
int i, n=0;
bisogna sapere la dimensione
Occorre quindi passare alla funzione anche la dimensione for (i=0; i<dim; i++) {
del vettore
if (v[i] != 0)
del vettore!
n++;
}
Se v[ ] fosse modificato dentro la
funzione, il valore sarebbe
return n;
modificato anche nella funzione
}
chiamante
387 388

Settimana n.7 Funzioni matematiche

Utilizzabili includendo in testa al programma


Obiettivi Contenuti
Funzioni <math.h>
#include <math.h>
Caratteri
Vettori di caratteri Il tipo char
Input/output di caratteri NOTA: Le funzioni trigonometriche (sia dirette sia
Stringhe inverse) operano su angoli espressi in radianti
Operazioni su variabili char
Funzioni <ctype.h>
Stringhe come vettori di char
Il terminatore nullo
Stringhe come tipo gestito
dalla libreria
Funzioni di I/O sulle stringhe

389 390
math.h math.h (Cont.)
funzione definizione
double sin (double x) sin (x)
double cos (double x) funzione definizione
cos (x)
double pow (double x, double y) xY
double tan (double x) tan (x)
double sqrt (double x) radice quadrata
double asin (double x) asin (x)
double log (double x) logaritmo naturale
double acos (double x) acos (x)
double log10 (double x) logaritmo decimale
double atan (double x) atan (x)
double exp (double x) eX
double atan2 (double y, double x) atan ( y / x )
double sinh (double x) sinh (x)
double cosh (double x) cosh (x)
double tanh (double x) tanh (x)
391 392

math.h (Cont.) Funzioni matematiche: Esempio


#include <stdio.h>
#include <math.h>
funzione definizione
double log2(double x);
double ceil (double x) ceil (x)
main()
double floor (double x) floor (x) {
int nogg, nbit;
double fabs (double x) valore assoluto printf(Dammi il numero di oggetti: );
scanf(%d, &nogg);
double fmod (double x, double y) modulo nbit=ceil(log2((double)nogg));
printf(Per rappresentare %d oggetti servono %d
restituisce la parte bit\n, nogg, nbit);
double modf (double x, double frazionaria di x e }
*ipart) memorizza la parte
intera di x in ipart double log2(double x)
{
return log(x)/log((double)2);
}

393 394

Codice ASCII Dualit caratteri - numeri

Ogni carattere rappresentato dal suo codice ASCII

y 7 W ! %
121 55 87 33 37

Ogni stringa rappresentata dai codici ASCII dei caratteri


di cui composta

F u l v i o 0 6 A Z N
70 117 108 118 105 111 48 54 65 90 78

0 1 1 - 5 6 4 6 3 3 2
48 49 49 45 53 54 52 54 51 51 50

395 396
I/O a caratteri EOF

Acquisizione/stampa di un carattere alla volta EOF = End-of-File

Istruzioni: Rappresenta in realt un valore fittizio corrispondente


- int getchar() alla fine dellinput
Legge un carattere da tastiera
Il carattere viene fornito come risultato di getchar (valore intero)
In caso di errore il risultato la costante EOF (dichiarata in stdio.h) Indica che non ci sono pi dati in input

- int putchar(<carattere>) EOF pu essere prodotto in diversi modi:


Stampa <carattere> su schermo - Automaticamente, se si sta leggendo un file
<carattere>: Un dato di tipo char - Premendo CTRL+Z in MS-DOS o VMS
- Premendo CTRL+D in Unix

397 398

I/O a caratteri: Esempio scanf/printf e getchar/putchar

#include <stdio.h> scanf e printf sono costruite a partire da


getchar/putchar
main()
{
scanf/printf sono utili quando noto il formato (tipo)
int tasto;
del dato che viene letto
- Esempio: Serie di dati con formato fisso
printf(Premi un tasto...\n);
tasto = getchar();
if (tasto != EOF) /* errore ? */ getchar/putchar sono utili quando non noto tale
{ formato
printf(Hai premuto %c\n, tasto); - Esempio: Un testo
printf(Codice ASCII = %d\n, tasto);
}
}
399 400

Funzioni di utilit Funzioni di utilit: vista dinsieme

Classificazione caratteri (<ctype.h>)


funzione definizione
int isalnum (char c) Se c lettera o cifra A...F G...Z
int isalpha (char c) Se c lettera isupper !"#$%&'()
int isascii(char c) Se c lettera o cifra *+,-./:
int isdigit (char c) Se c una cifra a...f g...z ;<=>?@[\]
islower
int islower(char c) Se c minuscola
isalpha
^_`{|}~
ispunct
int isupper (char c) Se c maiuscola
int isspace(char c) Se c spazio,tab,\n
0...9
isdigit
int iscntrl(char c) Se c di controllo isxdigit
isalnum isgraph
Se c stampabile, non
int isgraph(char c)
spazio Spazio isprint
int isprint(char c) Se c stampabile
int ispunct(char c) Se c di interpunzione Caratteri di Tab
int toupper(char c) Converte in maiuscolo controllo Newline isspace
int tolower(char c) Converte in minuscolo iscntrl
401 402
Stringhe Stringhe (Cont.)

Nel linguaggio C non supportato esplicitamente alcun Definizione:


tipo di dato stringa Sequenze di caratteri terminate dal carattere \0 (NULL)
Le informazioni di tipo stringa vengono memorizzate ed
elaborate ricorrendo a semplici vettori di caratteri Tecnicamente:
Vettori di caratteri terminati da un carattere aggiuntivo \0 (NULL)

Memorizzate come i vettori


char saluto[10] ;
La lunghezza della stringa pu essere definita implicitamente
mediante lassegnazione di una costante stringa, rappresentata da
una sequenza di caratteri racchiusa tra doppi apici
B u o n g i o r n o
Esempio: c i a o ! \0
char s[] = ciao!;
s[0] s[1] s[2] s[3] s[4] s[5]
403 404

Stringhe (Cont.) Formattazione di stringhe


NOTA: La stringa vuota non un vettore vuoto! Le operazioni di I/O formattato possono essere
- Esempio: char s[] = ;
\0
effettuate anche da/su stringhe
s[0]
Attenzione: a diverso da a Funzioni
int sscanf(char* <stringa>,char* <formato>,<espressioni>);
Infatti a indica il carattere a, mentre a rappresenta la stringa a - Restituisce EOF in caso di errore, altrimenti il numero di campi
(quindi con \0 finale). letti con successo
int sprintf(char* <stringa>,char* <formato>,<variabili>));
Graficamente:
- Restituisce il numero di caratteri scritti
- Ciao ----> C i a o \0
Utili in casi molto particolari per costruire/analizzare
- a ----> a \0 stringhe con un formato fisso
- a ----> a
405 406

I/O di stringhe Esempio

Diamo per scontato di utilizzare la convenzione del


terminatore nullo
Si possono utilizzare
- Funzioni di lettura e scrittura carattere per carattere
Come nellesercizio precedente const int MAX = 20 ;
- Funzioni di lettura e scrittura di stringhe intere char nome[MAX+1] ;
scanf e printf
gets e puts printf("Come ti chiami? ") ;

scanf("%s", nome) ;

407 408
Esempio Esempio

printf("Buongiorno, ") ;
const int MAX = 20 ;
printf("%s", nome) ;
char nome[MAX+1] ;
printf("!\n") ;
printf("Come ti chiami? ") ;

gets(nome) ;
printf("Buongiorno, %s!\n", nome) ;

409 410

Esempio Settimana n.8

Obiettivi Contenuti
Stringhe Funzioni <string.h>
Matrici Vettori multidimensionali
printf("Buongiorno, ") ; Vettori di Stringhe Matrice come estensione
puts(nome) ; dei vettori
/* No!! printf("!\n") ; */ Problem solving su dati
testuali

411 412

Manipolazione di stringhe Funzioni di libreria per stringhe

Data la loro natura di tipo aggregato, le stringhe non Utilizzabili includendo in testa al programma
possono essere usate come variabili qualunque #include <string.h>
funzione definizione
definizione
Esempi di operazioni non lecite: concatenazione
char* strcat (char* s1, char* s2); concatenazione s1+s2
char s1[20], s2[10], s3[50]; s1+s2
... char* strchr (char* s, int c); ricerca di c in s
s1 = abcdefg; int strcmp (char* s1, char* s2); confronto
confronto
s2 =
s3 =
hijklmno;
s1 + s2;
NO! char* strcpy (char* s1, char* s2); s1
s1 <= s2
<= s2
int strlen (char* s); lunghezza di ss
lunghezza di

A questo scopo esistono apposite funzioni per la char* strncat (char* s1,char* s2,int n); concat.
concat. nn car.
car. max
max
manipolazione delle stringhe char* strncpy (char* s1,char* s2,int n); copia
copia nn car.
car. max
max
char* strncmp(char* dest,char* src,int n); cfr.
cfr. n car. max
n car. max

413 414
Funzioni di libreria per stringhe (Cont.) Esercizio 1

NOTE: Realizzare un meccanismo di cifratura di un testo che


- Non possibile usare vettori come valori di ritorno delle funzioni consiste nellinvertire le righe del testo stesso
di libreria
Esempio:
char s[20] Esempio:
...
s = strcat(stringa1, stringa2); /* NO! */
- Alcune funzioni possono essere usate senza risultato
Esempio: atlov anu areC
Cera una volta
strcpy(<stringa destinazione>, <stringa origine>)
strcat(<stringa destinazione>, <stringa origine>)
un re che ... ehc er nu

- Il valore di ritorno coincide con la stringa destinazione

415 416

Esercizio 1: Soluzione Esercizio 2


#include <stdio.h> Si scriva un programma che legga da tastiera due
main()
{ stringhe e cancelli dalla prima stringa i caratteri contenuti
int i,j, len; nella seconda stringa
char s[80], dest[80]; /* una riga */

while (gets(s) != NULL) { Esempio:


len = strlen(s); j = 0; - str1: Olimpico
for (i=len-1;i>=0;i--) { - str2: Oio
dest[j] = s[i]; - risultato: lmpc
j++;
}
dest[j]='\0';
puts(dest);
}
}

417 418

Esercizio 2: Soluzione Esercizio 2: Soluzione (Cont.)


#include <stdio.h> char *elimina(char str1[], char str2[])
#define MAXCAR 128 {
int i, j, k;
char *elimina(char str1[], char str2[]);
for(i=j=0;str1[i]!= \0;i++)
main() {
{ for(k=0;(str2[k]!= \0) && (str1[i]!=str2[k]);k++);
char str1[MAXCAR], str2[MAXCAR]; if(str2[k]== \0)
printf(Dammi la stringa str1: ); str1[j++]=str1[i];
scanf(%s, str1); }
printf(Dammi la stringa str2: ); str1[j]=\0;
scanf(%s, str2); return str1;
printf(str1-str2= %s\n, elimina(str1,str2)); }
}
419 420
I/O a righe I/O a righe (Cont.)

Acquisizione/stampa di una riga alla volta Largomento di gets/puts di tipo puntatore


- Riga = Serie di caratteri terminata da \n (discussione pi avanti), definito come segue:
char*
Istruzioni:
- char *gets(<stringa>) Significato: Il puntatore ad una stringa contiene lindirizzo
Legge una riga da tastiera (fino al \n)
di memoria in cui il primo carattere della stringa
La riga viene fornita come stringa (<stringa>), senza il carattere \n
memorizzato
In caso di errore, il risultato la costante NULL (definita in stdio.h)

- int puts(<stringa>) Esempio: s


Stampa <stringa> su schermo - char* s;
Aggiunge sempre \n alla stringa

421 422

I/O a righe (Cont.) I/O a righe: Esempio

NOTE: Programma che replica su video una riga di testo scritta


- puts/gets sono costruite a partire da getchar/putchar dallutente
- Uso di gets richiede lallocazione dello spazio di memoria per la
riga letta in input #include <stdio.h>
Gestione dei puntatori che vedremo pi avanti
main()
- puts(s) identica a printf(%s\n,s);
{
char *s, *res;
Usate meno di frequente delle altre istruzioni di I/O printf(Scrivi qualcosa\n);
//res = gets(s);
if (res != NULL) // if (gets(s)!= NULL) /* errore ? */
{
puts(Hai inserito); //printf(Hai inserito\n);
puts(s); //printf(%s\n,s);
}
}

423 424

Vettori multidimensionali Vettori multidimensionali (Cont.)

E possibile estendere il concetto di variabile indicizzata a Sintassi:


pi dimensioni <tipo> <nome vettore> [<dim1>][<dim2>] [<dimN>];
- Utilizzo tipico:
Vettori bidimensionali per realizzare tabelle (matrici) Accesso ad un elemento:
<nome vettore> [<pos1>] [<pos2>] [<posN>]
Implementazione: Vettore di vettori
Esempio:
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] a[0]
int v[3][2];
a a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] a[1]

a[2][0] a[2][1] a[2][2] a[2][3] a[2][4] a[2]


Inizializzazione:
- Inizializzazione per righe!
Esempio:
int a[3][5]; int v[3][2] = {{8,1},{1,9},{0,3}}; // vettore 3x2
int w[3][2] = { 8,1, 1,9, 0,3 }; // equivalente

425 426
Matrice bidimensionale Vettori multidimensionali e cicli

colonne Per vettori a pi dimensioni, la scansione va applicata a


tutte le dimensioni
0 1 2 ... M-1 - Cicli annidati
0 1 2 3 4 5
1 2 4 6 8 10 Esempio:
Accesso agli elementi di una matrice 3x5
3 6 9 12 15
righe 2
4 8 12 16 20 int x[3][5];
...

5 10 15 20 25
N-1 6 12 18 24 30 for (i=0;i < 3; i++) { /* per ogni riga i */
for (j=0; j < 5; j++) { /* per ogni colonna j */
... // operazione su x[i][j]
}
pitagora }

427 428

Stampa per righe matrice di reali Lettura per righe matrice di reali

printf("Immetti matrice %d x %d\n",


printf("Matrice: %d x %d\n", N, M); N, M) ;

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


{
{ /* Stampa la riga i-esima */
for(j=0; j<M; j++) printf("Riga %d:\n", i+1) ;
{ for(j=0; j<M; j++)
{
printf("%f ", mat[i][j]) ;
} printf("Elemento (%d,%d): ",
i+1, j+1) ;
printf("\n");
} scanf("%f", &mat[i][j]) ;
}
}

429 430

Somma per righe Esercizio 1

Scrivere un programma che acquisisca da tastiera gli


elementi di una matrice quadrata 5x5 e che stampi su
for(i=0 ; i<N ; i++) video la matrice trasposta
{
somma = 0.0 ; Analisi:
for(j=0; j<M; j++) - Per il caricamento dei dati nella matrice, utilzziamo due cicli for
somma = somma + mat[i][j] ; annidati
sr[i] = somma ; Il pi interno scandisce la matrice per colonne, utilizzando lindice j
} Il pi esterno scandisce la matrice per righe, utilizzando lindice i
- Per la stampa della matrice trasposta, utilizziamo due cicli for
for(i=0; i<N; i++) annidati, ma con gli indici di riga (i) e colonna (j) scambiati
rispetto al caso dellacquisizione dei dati
printf("Somma riga %d = %f\n",
i+1, sr[i]) ;

431 432
Esercizio 1: Soluzione Esercizio 2
#include <stdio.h>
Scrivere un programma che legga da tastiera una matrice
main() quadrata di dimensioni massime 32x32 e stampi su video
{ la matrice stessa con accanto a destra la somma di
int matrice[5][5], i, j;
ciascuna riga ed in basso la somma di ciascuna colonna
printf("Inserire gli elementi per righe:\n"); - Le dimensioni della matrice devono essere inserite da tastiera
for (i=0; i<5; i++)
for (j=0; j<5; j++)
scanf("%d", &matrice[i][j]); Esempio:
printf("\n\n");
4 3 1 2 10
/* stampa della matrice trasposta */ 1 7 2 2 12
for (j=0; j<5; j++) {
for (i=0; i<5; i++) 3 3 5 0 11
printf("%5d", matrice[i][j]);
printf("\n");
8 13 8 4
}
}
433 434

Esercizio 2 (Cont.) Esercizio 2: Soluzione

Analisi: #include <stdio.h>


#define MAXDIM 32
- Il caricamento dei valori nella matrice avviene con un doppio ciclo
for annidato main()
- Le somme delle varie righe sono memorizzate in un vettore {
vet_righe avente un numero di elementi pari al numero di righe
della matrice int matrice[MAXDIM][MAXDIM],
- Le somme delle varie colonne sono memorizzate in un vettore vet_righe[MAXDIM],
vet_col avente un numero di elementi pari al numero di colonne vet_col[MAXDIM],
della matrice nrighe, ncol, somma, i, j;
- Il calcolo delle somme delle righe viene eseguito tramite un
doppio ciclo for annidato che scandisce la matrice per righe printf("Inserire le dimensioni della matrice: ");
scanf("%d %d", &nrighe, &ncol);
- Il calcolo delle somme delle colonne viene eseguito tramite un
/* caricamento elementi della matrice per righe */
doppio ciclo for annidato che scandisce la matrice per colonne
printf("Inserire gli elementi per righe:\n");
- La stampa della matrice e del vettore vet_righe avviene con un for (i=0; i<nrighe; i++)
doppio ciclo for annidato for (j=0; j<ncol; j++)
- La stampa del vettore col avviene con un singolo ciclo for scanf("%d", &matrice[i][j]);

435 436

Esercizio 2: Soluzione (Cont.) Esercizio 2: Soluzione (Cont.)

/* calcolo della somma delle righe */ /* stampa matrice e vettore somma delle righe*/
for (i=0; i<nrighe; i++) { printf("\n\n");
somma = 0; for (i=0; i<nrighe; i++) {
for (j=0; j<ncol; j++) for (j=0; j<ncol; j++)
somma = somma + matrice[i][j]; printf("%4d", matrice[i][j]);
vet_righe[i] = somma; printf("%7d\n", vet_righe[i]);
} }
/* stampa vettore somma delle colonne */
/* calcolo della somma delle colonne */ printf("\n");
for (j=0; j<ncol; j++) { for (j=0; j<ncol; j++)
somma = 0; printf("%4d", vet_col[j]);
for (i=0; i<nrighe; i++) printf("\n\n");
somma = somma + matrice[i][j];
vet_col[j] = somma; }
}

437 438
Settimana n.9 Il sistema dei tipi C

Obiettivi Contenuti
Tipi di dato scalari Il sistema dei tipi scalari in Tipo di dato

(completi) C (completo) Tipi Scalari Tipi Strutturati void

Argomenti sulla linea di Attivazione di programmi Tipi interi Tipi reali Enumerazioni Vettori

comando da command line char float Strutture

Argc, argv int double Union


Conversione degli short / long long Puntatori
argomenti
Funzioni
La funzione exit signed/unsigned

439 440

I tipi interi in C Specifiche del C

=
Tipo Descrizione Esempi sizeof(char) 1
char Caratteri ASCII 'a' '7' '!'
<
int Interi +2 -18 0
+24221
sizeof(short int) sizeof(int) sizeof(long int)
short int con meno bit
long int con pi bit
= = =
unsigned int Interi senza 0 1 423
segno 23234
sizeof(unsigned sizeof( sizeof(unsigned
unsigned short int con meno bit short int) unsigned int) long int)
unsigned long int con pi bit

441 442

Intervallo di rappresentazione Compilatori a 32 bit

Tipo N. Bit Min Max


Tipo Min Max char 8 -128 127
char CHAR_MIN CHAR_MAX int 32 -2147483648 2147483647
int INT_MIN INT_MAX short int 16 -32768 32767
short int SHRT_MIN SHRT_MAX long int 32 -2147483648 2147483647
long int LONG_MIN LONG_MAX unsigned 32 0 4294967295
unsigned int 0 UINT_MAX int
unsigned short int 0 USHRT_MAX unsigned 16 0 65536
unsigned long int 0 ULONG_MAX short int
unsigned 32 0 4294967295
#include <limits.h> long int

443 444
I tipi reali in C Numero di bit

Tipo Descrizione Tipo Dimensione Mantissa Esponente


float Numeri reali in singola precisione float 32 bit 23 bit 8 bit
double Numeri reali in doppia precisione double 64 bit 53 bit 10 bit
long double Numeri reali in massima precisione long double double

segno esponente
segno esponente

eeeeee eeeeee
A 1
.mmmmm
2 A 1
.mmmmm
2
mantissa mantissa

445 446

Intervallo di rappresentazione Specificatori di formato

float
Tipo scanf printf
0 char %c %c %d
int %d %d
1.17549435E-38 short int %hd %hd %d
3.40282347E+38 long int %ld %ld
unsigned int %u %o %x %u %o %x
double unsigned short int %hu %hu
0
unsigned long int %lu %lu
2.2250738585072014E-308 float %f %f %g
double %lf %f %g
1.7976931348623157E+308

447 448

Il modello console

Sistema Operativo

Finestra di comando
Argomenti sulla linea Argomenti Codice di uscita
di comando
Programma utente

int main()

450
Argomenti sulla linea di comando Argomenti del main()

In C, possibile passare informazioni ad un programma Prototipo:


specificando degli argomenti sulla linea di comando
- Esempio: main (int argc, char* argv[])
C:\> myprog <arg1> <arg2> ... <argN>
- argc: Numero di argomenti specificati
Comuni in molti comandi interattivi Esiste sempre almeno un argomento (il nome del programma)
- Esempio: MS-DOS
C:\> copy file1.txt dest.txt
- argv: Vettore di stringhe
argv[0] = primo argomento
Automaticamente memorizzati negli argomenti del argv[i] = generico argomento
main() argv[argc-1] = ultimo argomento

451 452

Esempi argc e argv

Struttura:
- Esempio: c:\> prog.exe 3 file.dat 3.2
C:\progr>quadrato Numero argomenti = 0
argv[0] prog.exe\0

Numero argomenti = 1 argv[1] 3\0


C:\progr>quadrato 5
Argomento 1 = 5
argv[2] file.dat\0 argc=4

Numero argomenti = 2 argv[3] 3.2\0


C:\progr>quadrato 5 K Argomento 1 = 5
NULL
Argomento 2 = K
453 454

argc e argv (Cont.) Conversione degli argomenti

Ciclo per lelaborazione degli argomenti Il C mette a disposizione tre funzioni per la conversione
for (i=0; i<argc; i++) { di una stringa in valori numerici
/* int atoi(char *s);
elabora argv[i] come stringa long atol(char *s);
*/ double atof(char *s);
}
Esempio:
NOTA: int x = atoi(2) ; // x=2
- Qualunque sia la natura dellargomento, sempre una stringa long y = atol(23L); // y=23
- Necessario quindi uno strumento per convertire in modo double z = atof(2.35e-2); // z=0.0235
efficiente stringhe in tipi numerici

Definite in stdlib.h
455 456
atoi, atof, atol: esempi Conversione degli argomenti (Cont.)

NOTA: Si assume che la stringa rappresenti lequivalente


char line[80] ; char line[80] ; di un valore numerico:
int x ; float x ; - cifre, +,- per interi
- cifre, +,-,l,L per long
gets(line) ; gets(line) ;
- cifre, +,-,e,E,. per reali
x = atoi(line) ; x = atof(line) ;

In caso di conversione errata o non possibile le funzioni


char line[80] ; char line[80] ; restituiscono il valore 0
long int x ; double x ; - Necessario in certi casi controllare il valore della conversione!

gets(line) ; gets(line) ;
x = atol(line) ; x = atof(line) ; NOTA: Importante controllare il valore di ogni argv[i]!

457 458

Conversione degli argomenti (Cont.) Programmi e opzioni

Esempio: Alcuni argomenti sulla linea di comando indicano


Programma C che prevede due argomenti sulla linea di tipicamente delle modalit di funzionamento alternative
comando: di un programma
- Primo argomento: Un intero
- Secondo argomento: Una stringa
Queste opzioni (dette flag o switch) sono
convenzionalmente specificate come
Schema: -<carattere>
int x;
per distinguerle dagli argomenti veri e propri
char s[80];
x = atoi(argv[1]);
strcpy(s,argv[2]); /* s=argv[2] errato! */ Esempio
C:\> myprog -x -u file.txt
opzioni argomento

459 460

La funzione exit Esercizio 1

Esiste inoltre la funzione di libreria exit, dichiarata in Scrivere un programma che legga sulla linea di
<stdlib.h>, che: comando due interi N e D, e stampi tutti i numeri minori
- Interrompe lesecuzione del programma o uguali ad N divisibili per D
- Ritorna il valore specificato
Il vantaggio rispetto allistruzione return che pu
essere usata allinterno di qualsiasi funzione, non solo
del main

void exit(int value) ;

461 462
Esercizio 1: Soluzione Esercizio 2
#include <stdio.h> Scrivere un programma m2m che legga da input un
main(int argc, char* argv[]) { testo e converta tutte le lettere maiuscole in minuscole e
int N, D, i; viceversa, a seconda dei flag specificati sulla linea di
if (argc != 3) { comando
fprintf(stderr,Numero argomenti non valido\n); -l, -L conversione in minuscolo
return 1;
-u, -U conversione in maiuscolo
}
if (argv[1] != NULL) N = atoi(argv[1]); Un ulteriore flag -h permette di stampare un help
if (argv[2] != NULL) D = atoi(argv[2]);

for (i=1;i<=N;i++) {
Utilizzo:
Altrimenti le operazioni m2m l
if ((i % D) == 0) {
successive operano su m2m -L
printf(%d\n,i);
stringhe = NULL m2m u
}
} m2m -U
} m2m -h

463 464

Esercizio 2: Soluzione Esercizio 3


#include <stdio.h>
Scrivere un frammento di codice che gestisca gli
main(int argc, char* argv[]) { argomenti sulla linea di comando per un programma
int lowercase = 0, uppercase = 0;
TEST.EXE il cui comando ha la seguente sintassi:
for (i=1; i<argc; i++) TEST.EXE [-a][-b] <nome file>
{
switch (argv[i][1]) { - I flag a e b sono opzionali (e possono essere in un ordine
case l: qualunque)
case L: - Lultimo argomento (<nome file>) obbligatorio (ed sempre
lowercase = 1; lultimo)
break;
case u:
case U: - Esempi validi di invocazione:
uppercase = 1; TEST.EXE <nome file>
break;
TEST.EXE a <nome file>
case h:
printf(Uso: m2m [-luh]\n); TEST.EXE b <nome file>
} TEST.EXE a -b <nome file>
} TEST.EXE b -a <nome file>
...
}
465 466

Esercizio 3: Soluzione Esercizio 3: Soluzione (Cont.)


main(int argc, char* argv[]) {
int i, aflag=0, bflag=0; }
char filename[80]; else {
/* Non e un flag. Esce dal programma */
if (argc >= 2) { /* almeno due argomenti */ fprintf(stderr,"Errore di sintassi.\n");
/* copiamo in una stringa, verra aperto dopo */ return;
strcpy (filename, argv[argc-1]); }
}
/* processiamo gli altri (eventuali argomenti) */ }
for (i=1; i<= argc-1; i++) { else {
if (argv[i][0] == '-') {/* e un flag */ /* sintassi errata. Esce dal programma */
switch (argv[i][1]) { fprintf(stderr,"Errore di sintassi.\n");
case 'a': return;
aflag = 1; break; }
case 'b': }
bflag = 1; break;
default:
fprintf(stderr,"Opzione non corretta.\n");
}
}

467 468
Settimana n.10

Obiettivi Contenuti
Strutture Struct. Operatore .
Vettori di strutture Definizione vettori di struct
Definizione di struct Tipi aggregati
contenenti vettori (es.
stringhe)

469

Tipi aggregati Tipi aggregati: esempio

In C, possibile definire dati composti da elementi


eterogenei (detti record), aggregandoli in una singola studente
variabile
- Individuata dalla keyword struct cognome: Rossi
nome: Mario
Sintassi (definizione di tipo): matricola: 123456 media: 27.25

struct <identificatore> {
campi
};

I campi sono nel formato:


<tipo> <nome campo>;

471 472

struct struct: Esempi

Una definizione di struct equivale ad una definizione di struct complex {


tipo double re;
double im;
Successivamente, una struttura pu essere usata come
un tipo per dichiarare variabili }

Esempio: struct identity {


struct complex { char nome[30];
double re;
char cognome[30];
double im;
} char codicefiscale[15];
... int altezza;
struct complex num1, num2; char statocivile;
}
473 474
Accesso ai campi di una struct Definizione di struct come tipo

Una struttura permette di accedere ai singoli campi E possibile definire un nuovo tipo a partire da una
tramite loperatore ., applicato a variabili del struct tramite la direttiva typedef
corrispondente tipo struct - Passabile come parametro
<variabile>.<campo> - Indicizzabile in vettori
Esempio:
struct complex { Sintassi:
double re; typedef <tipo> <nome nuovo tipo>;
double im;
}
Esempio:
... typedef struct complex {
struct complex num1, num2; double re;
num1.re = 0.33; num1.im = -0.43943; double im; compl z1,z2;
num2.re = -0.133; num2.im = -0.49; } compl;

475 476

Definizione di struct come tipo (Cont.) Operazioni su struct

Passaggio di struct come argomenti Confronto:


int f1 (compl z1, compl z2) - Non possibile confrontare due variabili dello stesso tipo di struct
usando il loro nome
Esempio:
struct come risultato di funzioni compl s1, s2 s1==s2 o s1!=s2 un errore di sintassi
compl f2(.....) - Il confronto deve avvenire confrontando i campi uno ad uno
Esempio:
compl s1, s2 (s1.re == s2.re) && (s1.im == s2.im)
Vettore di struct
compl lista[10]; Inizializzazione:
- Come per i vettori, tramite una lista di valori tra {}
Esempio:
Nota: compl s1 = {0.1213, 2.655};
La direttiva typedef applicabile anche non alle strutture per
definire nuovi tipi - Lassociazione posizionale: In caso di valori mancanti, questi vengono
- Esempio: typedef unsigned char BIT8; inizializzati a:
0, per valori numerici
NULL per puntatori

477 478

Esercizio 1 Esercizio 1: Soluzione


#include <stdio.h>
Data la seguente struct:
struct stud { #define NSTUD 10
char nome[40];
typedef struct stud {
unsigned int matricola;
char nome[40];
unsigned int voto; unsigned int matricola;
} unsigned int voto;
}studente;
- Si definisca un corrispondente tipo studente
- Si scriva un main() che allochi un vettore di 10 elementi e che
invochi la funzione descritta di seguito int ContaInsufficienti(studente vett[], int dim); /*
prototipo */
- Si scriva una funzione ContaInsufficienti() che riceva come
argomento il vettore sopracitato e ritorni il numero di studenti che
sono insufficienti

479 480
Esercizio 1: Soluzione (Cont.) Esercizio 2
main()
{ Data una struct che rappresenta un punto nel piano
int i, NumIns; cartesiano a due dimensioni:
studente Lista[NSTUD];
struct point {
/* assumiamo che il programma riempia double x;
con valori opportuni la lista */ double y;
NumIns = ContaInsufficienti(Lista, NSTUD); };
printf("Il numero di insufficienti e': %d.\n", NumIns); ed il relativo tipo typedef struct point Point; scrivere le
}
seguenti funzioni che operano su oggetti di tipo Point:
int ContaInsufficienti(studente s[], int numstud) - double DistanzaDaOrigine (Point p);
{ - double Distanza (Point p1, Point p2);
int i, n=0;
- int Quadrante (Point p); /* in quale quadrante */
for (i=0; i<numstud; i++) { - int Allineati(Point p1, Point p2, Point p3);
if (s[i].voto < 18) /* se sono allineati */
n++;
} - int Insterseca(Point p1, Point p2);
return n; /* se il segmento che ha per estremi p1 e p2
} interseca un qualunque asse*/

481 482

Esercizio 2: Soluzione Esercizio 2: Soluzione (Cont.)


double DistanzaDaOrigine (Point p) int Allineati (Point p1, Point p2, Point p3)
{ {
return sqrt(p.x*p.x + p.y*p.y); double r1, r2;
} /* verifichiamo che il rapporto tra y e x
delle due coppie di punti sia identico */
r1 = (p2.y-p1.y)/(p2.x-p1.x);
double Distanza (Point p1, Point p2) r2 = (p3.y-p2.y)/(p3.x-p2.x);
{ if (r1 == r2)
return sqrt((p1.x-p2.x)*(p1.x-p2.x) + return 1;
(p1.y-p2.y)*(p1.y-p2.y)); else
} return 0;
}
int Quadrante (Point p)
int Interseca(Point p1, Point p2)
{ {
if (p.x >= 0 && p.y >= 0) return 1; /* verifichiamo se sono in quadranti diversi */
if (p.x <= 0 && p.y >= 0) return 2; if (Quadrante(p1) == Quadrante(p2))
if (p.x <= 0 && p.y <= 0) return 3; return 0;
if (p.x >= 0 && p.y <= 0) return 4; else
} return 1;
}

483 484

Settimana n.11

Obiettivi Contenuti
File di testo Concetto di file e funzioni
fopen/fclose
Funzioni fgets+sscanf Files
Approfondimenti su printf
e scanf

485
Vista dinsieme dei formati di file File sequenziali

Il modo pi comune per realizzare I/O da file consiste


nellutilizzo del cosiddetto accesso bufferizzato
- Informazioni prelevate dal file attraverso una memoria interna al
File
sistema (detta buffer)
File binario File ASCII

Formato Formato Testo Testo Linguaggio Vantaggi:


proprietario standard puro formattato formale
- Livello di astrazione pi elevato
.doc .pdf .txt .html .c
- Possibilit di I/O formattato
.psd .zip .csv .xml

.xls .jpeg .rtf .java


I/O non bufferizzato:
- Accesso diretto a livello binario un carattere per volta

487 488

File sequenziali (Cont.) File sequenziali (Cont.)

Il C vede i file come un flusso (stream) sequenziale di Accesso tramite una variabile di tipo FILE*
byte
- Nessuna struttura particolare: Definita in stdio.h
La strutturazione del contenuto a carico del programmatore
- Carattere terminatore alla fine del file: EOF Dichiarazione:
FILE* <file>;
Byte 0 1 2 . N-1
FILE* contiene un insieme di variabili che permettono laccesso per
EOF tipi

Al momento dellattivazione di un programma vengono


automaticamente attivati tre file:
NOTA: Laccesso sequenziale implica limpossibilit di: - stdin
- Leggere allindietro - stdout
- Saltare ad uno specifico punto del file - stderr

489 490

File sequenziali (Cont.) File sequenziali (Cont.)

La struttura dati FILE contiene vari campi: stdin automaticamente associato allo standard input
(tastiera)
- short level; /* Fill/empty level of buffer */
- unsigned flags; /* File status flags */
- char fd; /* File descriptor */ stdout e stderr sono automaticamente associati allo
- unsigned char hold; /* Ungetc char if no buffer */ standard output (video)
- short bsize; /* Buffer size */
- unsigned char *buffer; /* Data transfer buffer */
- unsigned char *curp; /* Current active pointer */ stdin,stdout,stderr sono direttamente utilizzabili
- unsigned istemp; /* Temporary file indicator */
- short token; /* Used for validity checking */
nelle istruzioni per laccesso a file
- In altre parole, sono delle variabili predefinite di tipo FILE*

491 492
File: Operazioni Stati di un file

Luso di un file passa attraverso tre fasi fondamentali Directory Apertura del file Stream
- Apertura del file Nome file Posizione attuale
- Accesso al file Lettura / Scrittura
- Chiusura del file Testo / Binario
File aperto
File chiuso
Prima di aprire un file occorre dichiararlo! Risiede su disco,
Risiede su disco, il programma ha
il programma non accesso al suo
ha accesso al suo contenuto
contenuto attraverso lo
stream associato
Chiusura del file

493 494

Apertura di un file Apertura di un file (Cont.)

Per accedere ad un file necessario aprirlo: - <modo>: Tipo di accesso al file


r: sola lettura
- Apertura: w: sola scrittura (cancella il file se esiste)
Connessione di un file fisico (su disco) ad un file logico (interno al a: append (aggiunge in coda ad un file)
programma) r+: lettura/scrittura su file esistente
w+: lettura/scrittura su nuovo file
a+: lettura/scrittura in coda o su nuovo file
Funzione:
FILE* fopen(char* <nomefile>, char* <modo>); - Ritorna:
Il puntatore al file in caso di successo
<nomefile>: Nome del file fisico NULL in caso di errore

495 496

Chiusura di un file Apertura e chiusura di un file: Esempio

Quando lutilizzo del file fisico terminato, consigliabile FILE *fp; /* variabile di tipo file */
chiudere il file: ...
- Chiusura:
Cancellazione della connessione di un file fisico (su disco) ad un /* apro file testo.dat in lettura *\
file logico (interno al programma) fp = fopen(testo.dat,r);

Funzione: if (fp == NULL)


int fclose(FILE* <file>); printf(Errore nellapertura\n);
else
<file>: File aperto in precedenza con fopen() {
- Ritorna: /* qui posso accedere a testo.dat usando fp */
0 se loperazione si chiude correttamente }
EOF in caso di errore ...
fclose(fp);
497 498
Lettura di un file Scrittura di un file

Apertura del file Leggi riga / Apertura del file Scrivi riga /
Leggi carattere Scrivi carattere

File aperto in File aperto in


lettura lettura File aperto in Scrivi riga /
Scrivi carattere
scrittura
Posizione iniziale Posizione intermedia
(primo carattere) (n-esimo carattere) Posizione iniziale
(primo carattere) File aperto in
scrittura
File aperto in
Condizione
end-of-file lettura La posizione intermedia Posizione intermedia
diviene posizione finale (n-esimo carattere)
Leggi riga /
Posizione finale Leggi carattere
Chiusura del file (ultimo carattere)
Chiusura del file
499 500

Aggiunta ad un file Lettura a caratteri

Apertura del file Scrivi riga / Lettura:


Scrivi carattere - int getc (FILE* <file>);
- int fgetc (FILE* <file>);
Legge un carattere alla volta dal file
File aperto in Scrivi riga /
Scrivi carattere Restituisce il carattere letto o EOF in caso di fine file o errore
aggiunta

Posizione finale NOTA: getchar() equivale a getc(stdin)


File aperto in
(ultimo carattere) aggiunta

Posizione intermedia
La posizione intermedia (n-esimo carattere
diviene posizione finale dopo lultimo)

Chiusura del file


501 502

Scrittura a caratteri Lettura a righe

Scrittura: Lettura:
- int putc (int c, FILE* <file>); char* fgets(char* <s>,int <n>,FILE* <file>);
- int fputc (int c, FILE* < file>); - Legge una stringa dal file fermandosi al pi dopo n-1 caratteri
Scrive un carattere alla volta nel file - Leventuale \n NON viene eliminato (diverso da gets !)
Restituisce il carattere scritto o EOF in caso di errore - Restituisce il puntatore alla stringa letta o NULL in caso di fine file
o errore
NOTA: putchar() equivale a putc(,stdout)
NOTA: gets() equivale a fgets(,stdin)

503 504
Scrittura a righe Lettura formattata

Scrittura: Lettura:
int fputs(char* <s>, FILE* <file>); int fscanf(FILE* <file>,char* <formato>,...);
- Scrive la stringa <s> nel senza aggiungere \n - Come scanf(), con un parametro addizionale che rappresenta
(diverso da puts !) un file
- Restituisce lultimo carattere scritto, oppure EOF in caso di errore - Restituisce il numero di campi convertiti, oppure EOF in caso di
fine file
NOTA: puts() equivale a fputs(,stdout)
NOTA: scanf() equivale a fscanf(stdin,)

505 506

Scrittura formattata Altre funzioni

Scrittura: FILE* freopen(char* <nomefile>,char* <modo>);


int fprintf(FILE* <file>,char* <formato>,...); - Come fopen, ma si applica ad un file gi esistente
- Come printf(), con un parametro addizionale che rappresenta
- Restituisce il puntatore al file oppure NULL
un file
- Restituisce il numero di byte scritti, oppure EOF in caso di errore
int fflush(FILE* <file>);
NOTA: printf() equivale a - Cancella il contenuto di un file
fprintf(stdout,) - Restituisce 0 se termina correttamente oppure EOF

int feof(FILE* <file>);


- Restituisce falso (0) se il puntatore NON posizionato alla fine del
file
- Restituisce vero (!0) se il puntatore posizionato alla fine del file

507 508

Posizionamento in un file Schema generale di lettura da file

Ad ogni file associato un buffer ed un puntatore


allinterno di questo buffer leggi un dato dal file;
finch (non finito il file)
La posizione del puntatore pu essere manipolata con {
alcune funzioni elabora il dato;
leggi un dato dal file;
Pi utile: }
void rewind (FILE* <file>)
- Posiziona il puntatore allinizio del file
La condizione non finito il file pu essere
- Utile per ripartire dallinizio nella scansione di un file
realizzata in vari modi:
- Usando i valori restituiti dalle funzioni di input (consigliato)
- Usando la funzione feof()

509 510
Esempio 1 Esempio 1 (Cont.)

Lettura di un file formattato (esempio: Un intero per riga) Versione compatta senza memorizzare il risultato di
- Uso dei valori restituiti dalle funzioni di input (fscanf) fscanf()
- Usiamo fscanf() direttamente nella condizione di fine input
res = fscanf (fp, %d, &val);
while (res != EOF) while (fscanf (fp,%d,&val) != EOF)
{ {
elabora val; elabora val;
res = fscanf (fp, %d, &val); }
}

511 512

Esempio 2 Esempio 3

Lettura di un file formattato (esempio: Un intero per riga) Lettura di un file non formattato
- Uso di feof() - Uso dei valori restituiti dalle funzioni di input (getc)

fscanf (fp, %d, &val); c = getc(fp);


while (c != EOF)
while (!feof(fp)) {
{ elabora c; Versione 1
elabora val; c = getc(fp);
}
fscanf (fp, %d, &val);
}
while ((c=getc(fp))!= EOF)
{
elabora c; Versione 2
}

513 514

Esempio 4 Lettura di un file: fgets + sscanf

Lettura di un file non formattato Lettura di un file formattato in cui ogni riga abbia un dato
- Uso dei valori restituiti dalle funzioni di input (fgets) numero di campi di tipo noto (esempio un intero, ed una
stringa)
s = fgets(s,80,fp); - Uso di fgets per leggere la riga, e di sscanf per leggere i campi
while (s != NULL)
{ Versione 1
elabora s;
s = fgets(s,80,fp); while ((s = fgets(s,80,fp))!= NULL)
} {
sscanf( s, %d %s, &intero, stringa );
}

while ((s = fgets(s,80,fp))!= NULL)


{
elabora s; Versione 2
}

515 516
Esercizio Esercizio: Soluzione

Leggere un file estremi.dat contenente coppie di #include <stdio.h>


numeri interi (x,y), una per riga e scrivere un secondo file
diff.dat che contenga le differenze x-y, una per riga main() {
FILE *fpin, *fpout;
int x,y;
Esempio: /* apertura del primo file */
if ((fpin = fopen(estremi.dat,r)) == NULL)
File 1 File 2 {
fprintf(stderr,Errore nellapertura\n);
23 32 -9
return 1;
2 11 -9
13 }
19 6
23 5 18
3 2 1

517 518

Esercizio: Soluzione (Cont.) Avvertenza


/* apertura del secondo file */ In generale, errato tentare di memorizzare il contenuto
if ((fpout = fopen(diff.dat,w)) == NULL)
di un file in un vettore
{
- La dimensione (numero di righe o di dati) di un file non quasi
fprintf(stderr,Errore nellapertura\n);
mai nota a priori
return 1;
- Se la dimensione nota, tipicamente molto grande!
}
/* input */
while (fscanf(fpin,%d %d,&x,&y) != EOF)
{
/* ora ho a disposizione x e y */
fprintf(fpout,%d\n,x-y);
}
fclose (fpin);
fclose (fpout);
}

519 520

Formattazione delloutput Specificatori di formato

Loutput (su schermo o su file) viene formattato Tipo printf


solitamente mediante la funzione printf (o fprintf) char %c %d
Ogni dato viene stampato attraverso un opportuno int %d
specificatore di formato (codici %)
short int %hd %d
Ciascuno di questi codici dispone di ulteriori opzioni per
meglio controllare la formattazione long int %ld
- Stampa incolonnata unsigned int %u %o %x
- Numero di cifre decimali unsigned short int %hu
- Spazi di riempimento
unsigned long int %lu
- ...
float %f %e %g
double %f %e %g
char [] %s
521 522
Esempi Esempi (Cont.)

Istruzione Risultato Istruzione Risultato


printf("%d", 13) ; 13 printf("%.1d", 13) ; 13
printf("%1d", 13) ; 13 printf("%.4d", 13) ; 0013
printf("%3d", 13) ; 13 printf("%6.4d", 13) ; 0013
printf("%f", 13.14) ; 13.140000 printf("%4.6d", 13) ; 000013
printf("%6f", 13.14) ; 13.140000
printf("%.2s", "ciao") ; ci
printf("%12f", 13.14) ; 13.140000
printf("%.6s", "ciao") ; ciao
printf("%6s", "ciao") ; ciao
printf("%6.3s", "ciao") ; cia

523 524

Esempi (Cont.) Esempi (Cont.)

Istruzione Risultato Istruzione Risultato


printf("%.2f", 13.14) ; 13.14 printf("%6d", 13) ; 13
printf("%.4f", 13.14) ; 13.1400 printf("%-6d", 13) ; 13
printf("%6.4f", 13.14) ; 13.1400 printf("%06d", 13) ; 000013
printf("%9.4f", 13.14) ; 13.1400
printf("%6s", "ciao") ; ciao
printf("%-6s", "ciao") ; ciao

525 526

Esempi (Cont.) Approfondimenti su scanf

Tipologie di caratteri nella stringa di formato


Istruzione Risultato Modificatori degli specificatori di formato
printf("%d", 13) ; 13 Valore di ritorno
printf("%d", -13) ; -13 Specificatore %[]
printf("%+d", 13) ; +13
printf("%+d", -13) ; -13
printf("% d", 13) ; 13
printf("% d", -13) ; -13

527 528
Stringa di formato (1/2) Stringa di formato (2/2)

Caratteri stampabili: Specificatori di formato (%-codice):


- scanf si aspetta che tali caratteri compaiano esattamente - Se il codice non %c, innanzitutto scanf salta ogni eventuale
nellinput sequenza di caratteri di spaziatura
- Se no, interrompe la lettura - scanf legge i caratteri successivi e cerca di convertirli secondo il
Spaziatura (whitespace): formato specificato
- Spazio, tab, a capo - La lettura si interrompe al primo carattere che non pu essere
interpretato come parte del campo
- scanf salta ogni (eventuale) sequenza di caratteri di spaziatura
- Si ferma al primo carattere non di spaziatura (o End-of-File)

529 530

Specificatori di formato Esempi

Tipo scanf
char %c Istruzione Input Risultato
int %d scanf("%d", &x) ; 134xyz x = 134
short int %hd scanf("%2d", &x) ; 134xyz x = 13
long int %ld scanf("%s", v) ; 134xyz v = "134xyz"
unsigned int %u %o %x scanf("%2s", v) ; 134xyz v = "13"
unsigned short int %hu
unsigned long int %lu
float %f
double %lf
char [] %s %[...]
531 532

Esempi (Cont.) Valore di ritorno

La funzione scanf ritorna un valore intero:


Istruzione Input Risultato - Numero di elementi (%) effettivamente letti
Non conta quelli saltati con %*
scanf("%d %s", &x, v) ; 10 Pippo x = 10 Non conta quelli non letti perch linput non conteneva i caratteri
v = "Pippo" desiderati
Non conta quelli non letti perch linput finito troppo presto
scanf("%s", v) ; 10 Pippo x immutato - End-of-File per fscanf
v = "10" - Fine stringa per sscanf

scanf("%*d %s", v) ; 10 Pippo x immutato - EOF se linput era gi in condizione End-of-File allinizio della
lettura
v = "Pippo"

533 534
Lettura di stringhe Esempi (Cont.)

La lettura di stringhe avviene solitamente con lo


Pattern Effetto
specificatore di formato %s
- Salta tutti i caratteri di spaziatura
%[r] Legge solo sequenze di 'r'
- Acquisisci tutti i caratteri seguenti, fermandosi al primo carattere %[abcABC] Legge sequenze composte da a, b, c, A, B, C, in
di spaziatura (senza leggerlo) qualsiasi ordine e di qualsiasi lunghezza
Qualora linput dei separatori diversi da spazio, possibile %[a-cA-C] Idem come sopra
istruire scanf su quali siano i caratteri leciti, mediante lo %[a-zA-Z] Sequenze di lettere alfabetiche
specificatore %[pattern] %[0-9] Sequenze di cifre numeriche
%[a-zA-Z0-9] Sequenze alfanumeriche
%[^x] Qualunque sequenza che non contiene 'x'
%[^\n] Legge fino a file riga
%[^,;.!? ] Si ferma alla punteggiatura o spazio

535 536

Settimana n.12

Obiettivi Contenuti
Comprensione degli Cenno ai puntatori
operatori & e * Puntatori e vettori
Puntatori e stringhe Puntatori
Cenno alla allocazione
dinamica di un vettore

537

Puntatori Puntatori (Cont.)

Puntatori = Variabili che contengono indirizzi di memoria Lindirizzo di una variabile (da assegnare, per esempio, ad un
- Indirizzi = Indirizzi di una variabile (di qualche tipo) puntatore) determinabile tramite loperatore unario & posto a
fianco dellidentificatore della variabile
Definiti tramite loperatore unario * posto accanto al nome della
variabile Sintassi:
& <identificatore>
Sintassi:
<tipo> * <identificatore> Esempio:
int a, *ptr;
Per ogni tipo di variabile puntata, esiste un tipo diverso di ptr = &a;
puntatore
- Esempi:
int x; int *px;
double y; double *py;

539 540
Puntatori: Esempio Puntatori (Cont.)
int x=5, *px; Gli operatori * e & sono luno linverso dellaltro
Indirizzi - Lapplicazione consecutiva in qualunque ordine ad un puntatore
fornisce lo stesso risultato
px = &x; /* px = indirizzo di x */ Esempio:
*&px e &*px sono la stessa cosa!
x 5 10016
printf(%d\n,x); --> 5 In termini di operatori:
- *= Operatore di indirezione
printf(%d\n,px); --> 10016
Opera su un indirizzo
printf(%d\n,&x); --> 10016 Ritorna il valore contenuto in quellindirizzo
printf(%d\n,*px); --> 5 - & = Operatore di indirizzo
Opera su una variabile
px 10016 28104 Ritorna lindirizzo di una variabile
/* x e *px sono la stessa cosa! */

Quindi:
*(&px): Fornisce il contenuto della casella che contiene lindirizzo di px
Memoria &(*px): Fornisce lindirizzo della variabile (*px) puntata da px

541 542

Puntatori (Cont.)

Esempio:
main()
{
int a, *aptr;
a=7;
aptr = &a;

printf(lindirizzo di a e %p\n, &a); Puntatori e vettori


printf(il valore di aptr e %p\n, aptr);

printf(il valore di a e %p\n, a);


printf(il valore di *aptr e %p\n, *aptr);

printf(&*aptr = %p ----- *&aptr = %p\n,


&*aptr, *&aptr);

543

Puntatori e vettori Puntatori e vettori: Analogie

La relazione tra puntatori e vettori in C molto stretta Lanalogia tra puntatori e vettori si basa sul fatto che, dato
Elemento di connessione: un vettore a[]
- Il nome di un vettore rappresenta un indirizzo a[i] e *(aptr+i) sono la stessa cosa
Indirizzo del primo elemento!
- Esempio:
int a[8], *aptr;
Due modi per accedere al generico elemento del vettore:
Lassegnazione aptr = a; fa puntare aptr al primo
1. Usando larray (tramite indice)
elemento del vettore a 2. Usando un puntatore (tramite scostamento o offset)
int a[8]
aptr a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] Interpretazione:
aptr+i = Indirizzo dellelemento che si trova ad i posizioni dallinizio
*(aptr+i) = Contenuto di tale elemento

aptr = a
a
545 546
Puntatori e vettori: Analogie (Cont.) Puntatori e vettori: Esempio
main()
E possibile equivalentemente: {
- Accedere al vettore tramite offset usando il nome del vettore int b[] = {1,2,3,4};
int *bptr = b;
*(a+i) int i, offset;

- Accedere al vettore tramite indice usando il puntatore printf(== notazione indicizzata ==\n);
for(i=0; i<4; i++) {
aptr[i] printf(b[%d] = %d\n,i, b[i]);
}
printf(== notazione tramite offset e vettore ==\n);
Riassumendo: for(offset=0; offset<4; offset++) {
- Dati int a[], *aptr=a; laccesso al generico elemento i del printf(*(b+%d) = %d\n,offset, *(b+offset));
}
vettore a pu avvenire mediante: printf(== notazione tramite indice e puntatore ==\n);
a[i] for(i=0; i<4; i++) {
printf(bptr[%d] = %d\n,i, bptr[i]);
*(a+i) }
aptr[i] printf(== notazione tramite offset e puntatore ==\n);
for(offset=0; offset<4; offset++) {
*(aptr+i) printf(*(bptr+%d) = %d\n,offset, *(bptr+offset));
}
}
547 548

Puntatori e vettori: Differenze

Un puntatore una variabile che pu assumere valori


differenti

Il nome di un vettore fisso e non pu essere modificato

Esempio:
Puntatori e stringhe
int v[10], *vptr;
...
vptr = a; /* OK */
vptr += 3; /* OK */
v = vptr; /* NO, v non si pu modificare */
v += 3; /* NO, v non si pu modificare */

549

Puntatori e stringhe Puntatori e stringhe: Esempio


Stringa = Vettore di char terminato da \0 char v[] = abcd;
char *p = abcd;
Differenza sostanziale nella definizione di una stringa come vettore o
come puntatore
- Esempio: v
char v[] = abcd; 1000 a 2200 6400 p
char *p = abcd; 1001 b 2201
v un vettore: 1002 c ...
- I caratteri che lo compongono possono cambiare
- Si riferisce sempre alla stessa area di memoria
1003 d
p un puntatore: 1004 \0
- Si riferisce (punta) ad una stringa costante (abcd) 6400 a
- Si pu far puntare altrove (esempio: Scrivendo p = ...)
6401 b
- La modifica del contenuto di p ha risultato NON DEFINITO
6402 c
- Allocate in zone di memoria diverse!!! 6403 d
6405 \0
551 552
Puntatori e stringhe (Cont.)

Utilizzando la relazione tra puntatori e vettori possibile


sfruttare appieno la libreria delle stringhe
- Esempio:
char* strchr (char* s, int c);
/* Trova la prima occorrenza di c in s */
Allocazione dinamica
della memoria
char *p, *string = stringa di prova;
int n, i;
if ((p=strchr(string, )) != NULL) {
/* ho trovato uno spazio, p punta al carattere spazio*/
printf(La stringa prima dello spazio e: , );
n = p string;
for (i=0; i<n; i++) putchar(string[i]);
putchar(\n);
printf(La stringa dopo lo spazio e: %s\n, p+1);
}
else {
printf(Non ho trovato nella stringa %s\n, string);
}

553

Allocazione statica Allocazione statica: Esempio

Il C permette di allocare esclusivamente variabili in un #define MAX 1000


numero predefinito in fase di definizione (allocazione vett dimensionato in eccesso, in
statica della memoria): modo da soddisfare in ogni caso le
struct scheda { esigenze del programma, anche se
int codice; questo usa un numero minore di
- Variabili scalari: Una variabile alla volta elementi. Quindi in ogni caso vett
char nome[20]; sar composto da 1000 elementi da
char cognome[20]; 42 byte ciascuno, occupando cio
- Vettori: N variabili alla volta (con N valore costante)
42.000 byte
};

struct scheda vett[MAX];

555 556

Memoria dinamica Memoria dinamica (Cont.)

Questa limitazione pu essere superata allocando Lallocazione dinamica assegna memoria ad una variabile
esplicitamente la memoria (allocazione dinamica della in unarea apposita, fisicamente separata da quella in cui
memoria): vengono posizionate le variabili dichiarate staticamente

- Su richiesta:
Concettualmente:
Il programma in grado di determinare, ogni volta che lanciato, di
quanta memoria ha bisogno - Mappa di memoria di Istruzioni e dati
un programma allocati
staticamente
- Per quantit definite al tempo di esecuzione:
Il programma usa ad ogni istante soltanto la memoria di cui ha Memoria
bisogno, provvedendo periodicamente ad allocare la quantit di
memoria da usare e a liberare (deallocare) quella non pi utilizzata
Dati allocati Memoria
In tal modo si permette ad eventuali altri processi che lavorano in dinamicamente dinamica
parallelo sullo stesso sistema di meglio utilizzare la memoria
disponibile

557 558
Memoria dinamica: malloc Memoria dinamica: malloc (Cont.)

La memoria viene allocata dinamicamente tramite la Esempio:


funzione malloc() char *p;
p = (char*)malloc(10); // Alloca 10 caratteri a p

Sintassi:
Lallocazione dinamica permette di superare la
void* malloc(<dimensione>) limitazione del caso statico

<dimensione>: Numero (intero) di byte da allocare


Esempio:
int n;
- Valore di ritorno:
char p[n]; // Errore!!
Puntatore a cui viene assegnata la memoria allocata
In caso di errore (esempio, memoria non disponibile), ritorna NULL
int n;
NOTA:
char *p = (char*) malloc (n); // OK!!!
Dato che viene ritornato un puntatore void*, obbligatorio
forzare il risultato al tipo del puntatore desiderato

559 560

malloc: Esempio Settimana n.13


int *punt; Richiede lallocazione di una
int n; zona di memoria di n byte. Obiettivi Contenuti
Preparazione allesame Svolgimento temi desame
punt = (int *)malloc(n);
Trasforma il puntatore generico
if (punt == NULL) ritornato da malloc in un
puntatore a int.
{
printf (Errore di allocazione\n);
exit();
} Verifica che lallocazione sia
avvenuta regolarmente.

561 562

Settimana n.14

Obiettivi Contenuti
Preparazione allesame Svolgimento temi desame

563

Vous aimerez peut-être aussi