introduzione alla programmazione con linguaggi di alto livello -- introduzione al c --

40
Introduzione alla programmazione con linguaggi di alto livello -- Introduzione al C -- Vito Perrone

Upload: beau-dixon

Post on 31-Dec-2015

41 views

Category:

Documents


0 download

DESCRIPTION

Introduzione alla programmazione con linguaggi di alto livello -- Introduzione al C --. Vito Perrone. Indice. Obiettivi della programmazione in linguaggi di alto livello La macchina astratta C Struttura di un programma C Istruzioni principali del C Primi, semplici, esempi - PowerPoint PPT Presentation

TRANSCRIPT

Introduzione alla programmazione con linguaggi di alto livello

-- Introduzione al C --

Introduzione alla programmazione con linguaggi di alto livello

-- Introduzione al C --

Vito Perrone

Indice

•Obiettivi della programmazione in linguaggi di alto livello

•La macchina astratta C

•Struttura di un programma C

• Istruzioni principali del C

•Primi, semplici, esempi

•Primi esempi … un po’ meno semplici

Obiettivi della programmazione in linguaggi di alto livello (1)

• E’ meglio questo:0 READ1 STORE 1012 LOAD= 03 STORE 1024 LOAD 1015 BEQ 136 READ7 ADD 1028 STORE 1029 LOAD 10110 SUB= 111 STORE 10112 BR 413 LOAD 10214 WRITE15 END

Obiettivi della programmazione in linguaggi di alto livello (2)

• O questo:READSTORE CONTATORELOAD= 0STORE SOMMA

CICLO_SOMMA: LOAD CONTATOREBEQ STAMPA_FINALEREADADD SOMMASTORE SOMMALOAD CONTATORESUB=1STORE CONTATOREBR CICLO_SOMMA

STAMPA_FINALE: LOAD SOMMAWRITEEND

Obiettivi della programmazione in linguaggi di alto livello (3)

• Altri aspetti “sgradevoli” del linguaggio di von Neumann :“Esegui (a+b)*(c+d)” LOAD A

ADD B

STORE TEMP

LOAD C

ADD D

MULT TEMP

“RIPETI LA SEQUENZA DI OPERAZIONI FINCHE’ LA SEQUENZA DEI DATI NON E’ ESAURITA”

BEQ ….…..

La macchina astratta (del nucleo) del C

Elementi -e terminologia- essenziali• Standard Input, Standard Output

• Stringa: una successione finita di caratteri (per esempio “Giorgio, ieri, alfa-beta…”. E’ immagazzinata in celle consecutive, ciascuna contenente un singolo carattere della stringa.

• Le celle di memoria vengono chiamate anche variabili ( /= dall’omonimo concetto matematico!)

• Le variabili, le istruzioni e altri elementi del programma che saranno introdotti più avanti sono indicati tramite identificatori simbolici.

• identificatore simbolico: una successione di lettere e cifre, in cui al primo posto vi è una lettera. Il carattere speciale “_” viene considerato come cifra. Esempi:

• a, x, alfa, pippo, a1, xy23, Giuseppe, DopoDomani….

• Per il momento: numero di celle illimitato e ogni singola cella può contenere un qualsiasi valore numerico (sia intero sia reale) o un qualsiasi carattere

• Identificatori predefiniti e riservati (Per esempio, scanf e printf )• Parole chiave (Per comodità -di lettura umana, non del calcolatore!- le parole

chiave sono in neretto)

Struttura sintattica di un programma C

• Un programma C è composto da:

− un’intestazione seguita da

− una sequenza di istruzioni racchiusa tra i simboli { e }.

• L’intestazione è costituita dall’identificatore predefinito main seguito da una coppia di parentesi ( ) (per il momento vuote)

• Le istruzioni sono frasi del linguaggio di programmazione; ognuna di esse termina con il simbolo ‘;’.

Le principali istruzioni del C (1)

1. Istruzione di assegnamento • Assegna a una variabile il valore di un’espressione

• Esempi :

• x = 23;w = 'a';y = z;r3 = (alfa*43–xgg)*(delta–32*ijj);x = x+1;

• Se la cella a contiene il valore 45 e la cella z il valore 5, l’istruzione

• x = (a–z)/10• fa sì che nella cella x venga immagazzinato il valore 4.

• NB: per distinguere il valore carattere a dall’identificatore della variabile a, il primo viene indicato tra apici.

Le principali istruzioni del C (2)

2. Istruzioni di ingresso e uscita

• Consistono negli identificatori predefiniti scanf o printf seguiti da una coppia di parentesi che racchiude l’identificatore di una variabile.

• Determinano la lettura o scrittura del valore di una variabile dallo Standard Input o sullo Standard Output.

• Alcune comode abbreviazioni:

• printf((a–z)/10); per: temp = (az)/10; printf(temp);• dove temp denota una variabile non usata altrimenti nel programma.

• printf("alfa"); per: printf('a'); printf('l'); printf('f'); printf('a');

• differenza tra l’istruzione printf(2) e l’istruzione printf('2')?

Le principali istruzioni del C (3)

3. Istruzioni composte

• producono effetti diversi a seconda che siano verificate o meno certe condizioni sul valore delle variabili.

• Condizione (o espressione booleana): un’espressione il cui valore può essere vero o falso. Costruita mediante

– i normali operatori aritmetici,

– gli operatori di relazione (==, !=, <, >, <=, >=),

– gli operatori logici (!, ||, &&), corrispondenti, nell’ordine, alle operazioni logiche NOT, OR, AND.

• Esempi di condizioni:

x == 0

alfa > beta && x != 3

!((a + b)*3 > x || a < c)

Le principali istruzioni del C (4)

3.1 Istruzione condizionale

• costituita dalla parola chiave if, seguita da

– una condizione racchiusa tra parentesi tonde,

– una prima sequenza di istruzioni racchiusa tra parentesi graffe,

– la parola chiave else,

– una seconda sequenza di istruzioni racchiusa tra parentesi graffe.

– Il “ramo else” dell’istruzione può essere assente.

– Le parentesi graffe vengono in genere omesse quando la successione di istruzioni si riduce a un’istruzione singola.

• Esempi di istruzioni condizionali:

if(x == 0) z = 5; else y = z + w*y;if(x == 0) {z = 5;} else {y = z + w*y;}if ((x+y)*(z-2) > (23+v)) {z = x + 1; y = 13 + x;}if ((x == y && z >3) || w != y) z = 5; else {y = z + w*y; x = z;}

• Istruzioni scorrette:

if (x == 0) else y = z; y = 34;if (x == 0) a; else b + c;

• Esecuzione di un’istruzione condizionale:

− La macchina valuta la condizione, Nel caso “vero” esegue solamente la prima sequenza di istruzioni,

Nel caso “falso” esegue la seconda sequenza di istruzioni.

− Se manca il ramo else e la condizione è falsa, la macchina prosegue con l’istruzionesuccessiva all’istruzione condizionale.

Le principali istruzioni del C (5)

3.2 L’istruzione iterativa (ciclo o loop).• Permette la ripetizione dell’esecuzione di una sequenza di istruzioni ogni volta

che una certa condizione è verificata.

• È costituita dalla parola chiave while, seguita dalla condizione e da una sequenza di istruzioni fra parentesi graffe (detta corpo del ciclo).

• Esempi:

while (x >= 0) x = x – 1;while (z != y) {y = z – x; x = x*3;}

• Esecuzione di un’istruzione iterativa:– Valutazione della condizione

– Se questa è falsa non viene eseguito il corpo del ciclo e si passa direttamente all’istruzione successiva.

– Altrimenti si esegue una prima volta il corpo del ciclo; si valuta ancora la condizione e, nuovamente, si esegue il corpo del ciclo se essa è risultata vera. Quando la condizione risulta falsa si esce dal ciclo, ovvero si passa all’istruzione successiva all’istruzione iterativa. Il ciclo viene ripetuto finché la condizione rimane vera.

Le principali istruzioni del C (6)

• Alcune osservazioni:

• In un’istruzione ciclica, l’esecuzione potrebbe non terminare mai!– L’istruzione condizionale e l’istruzione iterativa sono dette istruzioni composte perché esse sono costruite componendo istruzioni più semplici;

– Molto utile per la costruzione di programmi complessi

– Un’istruzione composta può contenere al suo interno una qualsiasi altra istruzione, eventualmente essa stessa composta.

• Le macchine reali sono però costruite sullo schema di von Neumann:

• Chi si occupa di “colmare il gap” tra la macchina astratta C e la macchina reale -del tipo di v.N.?

• Il software di base. Più precisamente:–il compilatore, o, più raramente,

–l’interprete

Le principali istruzioni del C (7)

I primi, semplici, programmi in “quasi” C (1)

/*Programma NumeroMaggiore – prima versione */main(){

scanf(x);scanf(y);if (x > y) z = x; else z = y;printf(z);

}/

*Programma NumeroMaggiore – seconda versione */main(){

scanf(x);scanf(y);if (x > y) printf(x); else printf(y);

}

I primi, semplici, programmi in “quasi” C (2)

/*ProgrammaCercaIlPrimoZero */main(){

uno = 1;scanf (dato);while (dato !=0) scanf(dato);printf(uno);

}

I primi, semplici, programmi in “quasi” C (3)

/*ProgrammaSommaSequenza */main() {

somma = 0;scanf(numero);while (numero != 0){

somma = somma + numero;scanf(numero);

}printf(somma);

}

I primi, semplici, programmi in “quasi” C (4)

/*Programma per la valutazione di un triangolo */main() {

/*Lettura dei dati di ingresso */scanf(X); scanf(Y); scanf(Z);

/* Verifica che i dati possano essere le lunghezzedei lati di un triangolo */

if ((X < Y + Z) && (Y < X + Z) && (Z < X + Y))/*Distinzione tra i vari tipi di triangolo */

if (X == Y && Y == Z)printf("I dati letti corrispondono a un triangolo equilatero");else

if (X == Y || Y == Z || X == Z)printf("I dati letti corrispondono a un triangolo isoscele");elseprintf("I dati letti corrispondono a un triangolo scaleno");

elseprintf("I dati letti non corrispondono ad alcun triangolo");

}

• Come interpretare la seguente istruzione?

if (C1) if (C2) S1; else S2;

• Prima possibilità (l’else è attribuito all’if più esterno):

if (C1)if (C2) S1;

else S2;

• Seconda possibilità (l’else è attribuito all’if più interno):

if (C1)if (C2) S1;else S2;

• Convenzione: il primo ramo else viene attribuito all’ultimo if. Altrimenti, scriviamo esplicitamente:

if (C1) {if (C2) S1;} else S2;

Nota sull’istruzione if

Le variabili strutturate

• Un primo arricchimento della macchina astratta C

Gli array

• Un array viene identificato come qualsiasi altra variabile

• Però anche i suoi elementi sono variabili

• Ad essi si accede mediante un indice:• esempi:

scanf(s[2]);a[3] = s[1] + x;

if (a[4] > s[1] + 3) s[2] = a[2] + a[1];x = a[i];a[i] = a[i+1];a[i*x] = s[a[j+1]–3]*(y – a[y]);

• In C il primo elemento di ogni array è sempre lo 0-esimo

/* Programma InvertiSequenza */main() {

indice = 0;scanf(x);while (x != '%') {

sequenza[indice] = x;indice = indice + 1;scanf(x);

}while (indice > 0){

indice = indice - 1;printf(sequenza[indice]);

}}

Programma InvertiSequenza

Primi esempi… un po’ meno semplici

• Sviluppo e codifica incrementali di algoritmi

• Uso dello “pseudocodice” per raffinamenti successivi

Dal problema…

• Lo Standard Input contiene una serie di dati relativi a delle fatture: per ogni fattura una cella dello Standard Input ne contiene l’importo e le tre successive la data di emissione, nella forma “giorno” (un numero compreso tra 1 e 31), “mese”, “anno”. Il ‘%’ è posto dopo l’anno dell’ultima fattura.

• Si vogliono stampare, nell’ordine, sullo Standard Output:– la dicitura: IMPORTI FATTURE EMESSE;

– la sequenza di tutti gli importi, nello stesso ordine di ingresso, preceduti dal carattere $;

– la dicitura: TOTALE FATTURE EMESSE;

– il totale delle fatture stesse, precedute dal carattere $;

– la dicitura: DATE DI EMISSIONE;

– la sequenza delle date di emissione, nello stesso ordine di ingresso. I tre elementi di ogni data devono essere separati da una /; alla fine di ogni data va scritto il carattere #.

…all’algoritmo…

1. Un primo ciclo esegue la lettura dei vari dati, quattro per volta (infatti ogni fattura è descritta da quattro elementi). Ognuno dei quattro dati letti viene memorizzato, rispettivamente, in una cella di quattro diversi array, denominati fatture, giorno, mese e anno. L’indice di ognuno di questi array viene incrementato di 1 a ogni iterazione del ciclo. Durante questo ciclo viene anche calcolato l’importo totale delle varie fatture.

2. Viene stampata la dicitura IMPORTI FATTURE EMESSE mediante un’unica istruzione printf.

3. Un primo ciclo di scrittura stampa nell’ordine tutti gli elementi dell’array fatture intercalandoli con il simbolo $.

4. Viene stampata la dicitura TOTALE FATTURE EMESSE seguita da $ e dal valore del totale precedentemente calcolato.

5. Viene stampata la dicitura DATE DI EMISSIONE.

6. Un secondo ciclo di scrittura stampa le varie terne di valori “giorno, mese, anno”, prelevandole nell’ordine dai corrispondenti array e introducendo il carattere / tra giorno e mese e tra mese e anno, e il carattere # tra l’anno della data corrente e il giorno della terna successiva.

…al codice (1)/* Programma Fatture */

main() {

contatore = 0; totale = 0; scanf(dato);while (dato != '%') {

fatture[contatore] = dato; totale = totale + dato;scanf(dato); giorno[contatore] = dato;scanf(dato); mese[contatore] = dato;scanf(dato); anno[contatore] = dato;scanf(dato); contatore = contatore + 1;

}printf("IMPORTI FATTURE EMESSE");NumFatture = contatore; contatore = 0;while (contatore < NumFatture) {

printf('$'); printf(fatture[contatore]); contatore = contatore + 1;}printf("TOTALE FATTURE EMESSE"); printf('$'); printf(totale);

…al codice (2)

printf("DATE DI EMISSIONE"); contatore = 0;while (contatore < NumFatture){

printf(giorno[contatore]); printf('/');printf(mese[contatore]); printf('/');printf(anno[contatore]); printf('#');contatore = contatore + 1;

}}

Dal problema …

• Si vuole costruire un analizzatore di testo che sostituisca sistematicamente una parola con un’altra. Lo Standard Input della macchina abbia il contenuto seguente:

− In primo luogo è scritta (carattere per carattere) una parola (per “parola” intendiamo qui una sequenza di caratteri alfabetici); segue il carattere $; poi un’altra parola seguita dal carattere #; successivamente vi è una sequenza di parole separate tra di loro da uno spazio e chiusa da un % (cioè, dopo l’ultima parola c’è uno spazio seguito dal terminatore finale %).

• Il programma deve riscrivere su Standard Output il testo costituito dalla sequenza di parole dopo il #, sostituendo a ogni occorrenza della prima parola dello Standard Input la seconda. Se la prima parola manca, il programma deve stampare un messaggio che avverte l’utente dell’errore e sospendere l’esecuzione. Al contrario, può essere mancante la seconda parola: in tal caso si ottiene l’effetto di cancellare ogni occorrenza della prima parola; è ammesso il caso particolare che l’intero testo da riscrivere sia assente.

• NB: Possibilità di dati errati o, di condizioni eccezionali.

…all’algoritmo…

1. Verifica se prima del carattere $ esiste una parola. In caso negativo stampa il messaggio MANCA LA PAROLA DA SOSTITUIRE. In caso positivo procedi come segue.

2. Memorizza la prima parola del testo in un array di caratteri.

3. Memorizza la seconda parola in un altro array.

4. A questo punto fai la scansione dell’intero testo parola per parola (fino all’individuazione del carattere %).

4.1 Memorizza ogni parola in un array.4.2 Confronta la parola letta con la prima parola. Se le due

parolecoincidono, scrivi nello Standard Output la seconda parola,altrimenti scrivi la parola appena letta.

…a una prima parziale codifica…(1)/* Programma SostituzioneParole */

main() {

scanf(carattere);if (carattere == '$') printf("MANCA LA PAROLA DA SOSTITUIRE");else {[memorizza nell'array PrimaParola la sequenza di caratteri fino a '$'];[memorizza nell'array SecondaParola la sequenza di caratteri seguenti '$' fino a '#'];

scanf(carattere);while (carattere != '%'){[memorizza nell'array ParolaCorrente la sequenza di caratteri fino al prossimo spazio];[confronta PrimaParola con ParolaCorrente];if ([PrimaParola == ParolaCorrente])

[printf(SecondaParola)];else

[printf(ParolaCorrente)]; printf(' ');…

…a una prima parziale codifica…(2)

/* Programma SostituzioneParole (continuazione)*/…

/* Sia nel caso che si sia scritta la parola appena letta (ParolaCorrente), sia nel caso che si sia scritta la seconda parola al posto della prima, si scrive uno

spazio per separarla dalla parola successiva */scanf(carattere);

/* Inizia la lettura della prossima ParolaCorrente,a meno che il carattere letto non sia % */

}}

}

…alla codifica dei sottoproblemi (1)…

• Memorizzazione di una parola in un array,

• Scrittura di una parola

• Confronto tra due parole

…alla codifica dei sottoproblemi (2)…(confronto tra due parole)

if (LunghPrimaPar == LunghParCorr){

contatore = 0;while ((contatore < LunghPrimaPar) &&

PrimaParola[contatore] == ParolaCorrente[contatore]))

contatore = contatore + 1;if (contatore >= LunghPrimaPar)

printf("Le due parole coincidono");else

printf("Le due parole sono diverse");}else

printf("Le due parole sono diverse");

…al codice completo (1)

/* Programma SostituzioneParole */main() {

scanf(carattere);if (carattere == '$')

printf ("MANCA LA PAROLA DA SOSTITUIRE");else {

contatore = 0;while (carattere != '$')

…al codice completo (2)/* Programma SostituzioneParole (continuazione)*/

…/* Memorizzazione della prima parola */

{PrimaParola[contatore] = carattere;contatore = contatore + 1;scanf(carattere);

}LunghPrimaPar = contatore;scanf(carattere); contatore = 0;while (carattere != '#')

/* Memorizzazione della seconda parola */{

SecondaParola[contatore] = carattere;contatore = contatore + 1;scanf(carattere);

}LungSecPar = contatore;

…al codice completo (3)

/* Programma SostituzioneParole (continuazione)*/…

/* Si entra ora nella fase di scansione del testo */scanf(carattere);while (carattere != '%'){

contatore = 0;while carattere != ' '

/* Memorizzazione della parola corrente */{

ParolaCorrente[contatore] = carattere;contatore = contatore + 1;scanf(carattere);

}LungParCorr = contatore;

…al codice completo (4)/* Programma SostituzioneParole (continuazione)*/

…/* Si confronta la prima parola con la parola corrente */

if (LunghPrimaPar == LunghParCorr){

contatore = 0;while (contatore < LunghPrimaPar &&

PrimaParola[contatore] == ParolaCorrente[contatore])

contatore = contatore + 1;if (contatore >= LunghPrimaPar

/* Si ricopia la seconda parola */{

contatore = 0;while (contatore < LungSecPar) {

printf(SecondaParola[contatore]);contatore = contatore + 1;

}}else

…al codice completo (5)

/* Programma SostituzioneParole (continuazione)*/…

/* Si ricopia la parola corrente */{

contatore = 0;while (contatore < LungParCorr) {

printf(ParolaCorrente[contatore]);contatore = contatore + 1;

}}

}else

…al codice completo (6)/* Programma SostituzioneParole (continuazione)*/

…/* Si copia la Parola corrente: in questo caso le due parole sono differenti perché le

lunghezze sono differenti */{

contatore = 0;while (contatore < LungParCorr){

printf(ParolaCorrente[contatore]);contatore = contatore + 1;

}}printf(' ');

/*Sia nel caso che si sia scritta la parola appena letta (ParolaCorrente), sia nel caso che si sia scritta la seconda parola al posto della prima, si scrive uno spazio per

separarla dalla parola successiva*/scanf(carattere);

/* Inizia la lettura della prossima ParolaCorrente, a meno che il carattere letto non sia % */}

}}