Tipi di dati. una parola di memoria (16 o 32 bit), float. possibile rilevare errori nell uso di variabili mediante compilazione



Documenti analoghi
Tipi di dato-prima parte

Variabili e tipi di dato

Strutture. Strutture e Unioni. Definizione di strutture (2) Definizione di strutture (1)

Introduzione alla programmazione in C

4 3 4 = 4 x x x 10 0 aaa

LINGUAGGI DI PROGRAMMAZIONE

Funzioni in C. Violetta Lonati

Corso di Fondamenti di Informatica

Informatica. Rappresentazione dei numeri Numerazione binaria

Fondamenti di Informatica e Laboratorio T-AB Ingengeria dell Automazione a.a. 2008/2009. Lab 02 Tipi semplici in C

Alcune regole di base per scrivere un programma in linguaggio C

Esercizi di programmazione in C

NB L uso delle istruzioni condizionali annidate causa rischio di ambiguità quando qualcuna di loro manca del ramo else:

2. Spiegare brevemente qual è la funzione del compilatore e la sua importanza per il programmatore.

INFORMATICA - I puntatori Roberta Gerboni

Dall Algoritmo al Programma. Prof. Francesco Accarino IIS Altiero Spinelli Sesto San Giovanni

La selezione binaria

Alfabeto ed elementi lessicali del linguaggio C

Linguaggio C. Fondamenti. Struttura di un programma.

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Esercitazione Informatica I AA Nicola Paoletti

Elementi di informatica

Informazione analogica e digitale

MATLAB. Caratteristiche. Dati. Esempio di programma MATLAB. a = [1 2 3; 4 5 6; 7 8 9]; b = [1 2 3] ; c = a*b; c

Le variabili. Olga Scotti

Corso di Programmazione I dati nei linguaggi di programmazione Tipi Semplici. I dati nei linguaggi di programmazione. Dati. Dott.

Codifica binaria dei numeri

3. La sintassi di Java

Corso di Calcolo Numerico

Appunti del corso di Informatica 1. 6 Introduzione al linguaggio C

Appunti del corso di Informatica 1 (IN110 Fondamenti) 6 Introduzione al linguaggio C

Laboratorio di Informatica

Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi.

Rappresentazione dell informazione Codifica Binaria

Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori

SISTEMI DI NUMERAZIONE E CODICI

Informatica B. Sezione D. Scuola di Ingegneria Industriale Laurea in Ingegneria Energetica Laurea in Ingegneria Meccanica

void funzioneprova() { int x=2; cout<<"dentro la funzione x="<<x<<endl; }

Richiesta pagina PHP (es: index.php)

I sistemi di numerazione

Appunti sulla Macchina di Turing. Macchina di Turing

Corso di Informatica Generale (C. L. Economia e Commercio) Ing. Valerio Lacagnina Rappresentazione in virgola mobile

dall argomento argomento della malloc()

2. Codifica dell informazione

Codici Numerici. Modifica dell'informazione. Rappresentazione dei numeri.

Alessandro Pellegrini

Lezione 8. La macchina universale

Rappresentazione delle informazioni

LABORATORIO DI PROGRAMMAZIONE EDIZIONE 1, TURNO B

Obiettivi dell Analisi Numerica. Avviso. Risoluzione numerica di un modello. Analisi Numerica e Calcolo Scientifico

Sistemi di Numerazione Binaria NB.1

L espressione torna invece sempre vera (quindi la soluzione originale) se cambiamo contemporaneamente il verso: 1 < 0.

Rappresentazione di informazioni con un alfabeto finito

Risolvere un problema significa individuare un procedimento che permetta di arrivare al risultato partendo dai dati

(71,1), (35,1), (17,1), (8,1), (4,0), (2,0), (1,0), (0,1) 0, = 1, 431 0, = 0, 862 0, = 1, 792 0, = 1, 448 0, = 0, 896

Introduzione al Linguaggio C

Dati testuali. Caratteri e stringhe. Tipi di dato testuali. Dati testuali. Il sistema dei tipi C. Rappresentazione dei testi

Rappresentazione dei numeri in un calcolatore

APPELLO SCRITTO DI PROGRAMMAZIONE 1 CORSO DI LAUREA IN MATEMATICA UNIVERSITÀ DEGLI STUDI DI MILANO XI.2015

ESEMPIO 1: eseguire il complemento a 10 di 765

SCHEDA DI RECUPERO SUI NUMERI RELATIVI

Arduino: Programmazione

Verifica della correttezza formale del numero di partita IVA

LE SUCCESSIONI 1. COS E UNA SUCCESSIONE

+ / operatori di confronto (espressioni logiche/predicati) / = > < Pseudo codice. Pseudo codice

Definizione di nuovi tipi in C

Fondamenti di Informatica T. Linguaggio C: i puntatori

Sistema operativo: Gestione della memoria

Programmazione C Massimo Callisto De Donato massimo.callisto@unicam.it

Operazioni Aritmetiche e Codici in Binario Giuseppe Talarico 23/01/2013

Tipo di dato. Ci siamo già imbattuti in questo concetto. Definizione generale di tipo di dato

Codifica: dal diagramma a blocchi al linguaggio C++

Puntatori Passaggio di parametri per indirizzo

Matematica - SMID : Programmazione Febbraio 2009 FOGLIO RISPOSTE

Introduzione al MATLAB c Parte 2

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI

LA RAPPRESENTAZIONE DELLE INFORMAZIONI

ISTITUTO TECNICO INDUSTRIALE STATALE LA GESTIONE DEI FILE DI TESTO IN C++

Logica e codifica binaria dell informazione

ESAME SCRITTO DI ELEMENTI DI INFORMATICA E PROGRAMMAZIONE. 27 Gennaio 2015

= 1*2^7 + 1*2^6 + 0*2^5 + 1*2^4 + 0*2^3 + 0*2^2 + 1*2^1 + 0*2^0 = 210

Introduzione. Rappresentazione di numeri in macchina, condizion

Elementi di Informatica e Programmazione

Università degli Studi di Cassino Corso di Fondamenti di Informatica Puntatori. Anno Accademico 2010/2011 Francesco Tortorella

INFORMATICA 1 L. Mezzalira

Algoritmi e strutture dati. Codici di Huffman

COS È UN LINGUAGGIO? LINGUAGGI DI ALTO LIVELLO LA NOZIONE DI LINGUAGGIO LINGUAGGIO & PROGRAMMA

SISTEMI DI NUMERAZIONE DECIMALE E BINARIO

FONDAMENTI di INFORMATICA L. Mezzalira

Concetto di Funzione e Procedura METODI in Java

Esempi ed esercizi Aritmetica degli elaboratori e algebra di commutazione

Tipicamente un elaboratore è capace di trattare domini di dati di tipi primitivi

Programmazione I - Laboratorio

APPUNTI SUL LINGUAGGIO DI PROGRAMMAZIONE PASCAL

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica

Parte 1. Vettori di bit - AA. 2012/13 1.1

LE FUNZIONI A DUE VARIABILI

1 Serie di Taylor di una funzione

Nascita di Java. Che cos e Java? Caratteristiche di Java. Java: linguaggio a oggetti

Trattamento delle STRINGHE in C(++)

Transcript:

Tipi di dati tipo di dato insieme di valori + insieme di operazioni esempio, tipo intero..., 2, 1, 0, +1, +2,... + somma, sottrazione,... In C tutte variabili hanno un tipo associato stabilmente mediante la dichiarazione Conseguenze della tipizzazione delle variabili variabile determinato a priori insieme dei valori ammissibili insieme delle operazioni applicabili memoria necessaria (NB variabile da macchina a macchina) esempi char 1 byte (8 bit) int una parola di memoria (16 o 32 bit), float 4 byte possibile rilevare errori nell uso di variabili mediante compilazione Classificazione dei tipi di dati semplici valori considerati atomici (e.g., velocità, temperatura) strutturati valori aggregati di varie componenti (e.g., una data) predefiniti (built-in) definiti dall utente nel corredo del linguaggio usati quando non bastano queli predefiniti terzo fascicolo - 1 -

Tipi semplici predefiniti quattro tipi di base: char (caratteri) int (interi) float (reali) double (reali in precisione doppia) qualificatori di tipo signed e unsigned applicabili a char e int short e long applicabile a int long applicabile a double 12 tipi semplici predefiniti Tipo predefinito char signed char unsigned char signed short int signed int signed long int unsigned short int unsigned int unsigned long int float double long double Denominazioni alternative signed short, short signed, int long int, signed long, long unsigned short unsigned unsigned long short e long condizionano spazio allocato signed e unsigned, short e long condizionano insieme dei valori ( massimo e minimo) NB non necessario dichiarare tipi predefiniti si dichiarano direttamente variabili di quei tipi - 2 -

Il tipo int un approssimazione dell insieme degli interi della matematica spazio allocato ( insieme dei valori) dipende dalla macchina normalmente un int in una parola (tipicamente 16 o 32 bit) long e short possono modificare memoria allocata unico fatto garantito: spazio allocato (short int) spazio allocato (int) spazio allocato(long int) signed int unsigned int un bit per il segno tutti i bit per il valore intero supposto positivo esempio con parola di 16 signed int ha valori 2 15,..., 2 15 1 unsigned int la valori 0,..., 2 16 1 costanti simboliche predefinite INT_MIN massimo valore intero INT_MAX minimo valore intero valore predefinito ma dall implementazione del linguaggio (complitore e macchina) non dalla definizione del linguaggio dichiarate nel file <limits.h> nella standard library inclusione mediante direttiva #include<limits.h> altro fatto garantito: spazio allocato (signed int) = spazio allocato (unsigned int) operazioni applicabili a int e suoi derivati tramite qualificatori = Assegnamento di un valore int a una variabile int +, -, * Somma, sottrazione, moltiplicazione (tra int ha come risultato un int) / Divisione con troncamento (risultato int) % Resto della divisione intera == Relazione di uguaglianza!= Relazione di diversità <, >, <=, >= Relazione minore, maggiore, minore o uguale, maggiore o uguale - 3 -

se operazioni danno risultato fuori da insieme valori segnalazione di errore esempio se moltiplicazione tra interi dà valore > INT_MAX segnalazione di Integer Overflow) avverte utente che risultato concreto non corrisponde al valore atteso Esempio legge una successione di numeri interi positivi (termina valore 0) numero verifica se anno bisestile ( multiplo di 4) /* Programma AnnoBisestile */ #include <stdio.h> main() int anno, resto; printf("inserire un numero positivo per sapere se corrisponde a un anno bisestile un numero negativo o il numero zero fanno terminare il programma\n"); scanf("%d", &anno); while (anno > 0) /* Quando un numero è multiplo di 4 il resto della sua divisione per 4 è pari a zero */ resto = anno % 4; if (resto ==0) printf("l'anno %d è un anno bisestile\n", anno); else printf("l'anno %d non è un anno bisestile\n", anno); printf("inserire un numero positivo per sapere se corrisponde a un anno bisestile un numero negativo o il numero zero fanno terminare il programma\n"); scanf("%d", &anno); - 4 -

I tipi float e double approssimazione dei numeri reali della matematica sia per limiti nel valore sia per precisione di rappresentazione Esempi di rappresentazione decimale, o in virgola fissa 3.14 1 234.543 328 543. 0.000 076 dispendioso per valori molto grandi o molto piccoli in valore assoluto 10 900 o 10 900 rappresentazione in virgola mobile (floating point) due parti: mantissa ed esponente (base 10) separate da E se n ha mantissa m ed esponente e n = m 10 e esempio, 1 780 000.000 0023 in virgola mobile: 178 000.000 000 23E1 17 800 000 000 023E-7 1.780 000 000 0023E+6 ecc. NB possono verificarsi errori per arrotondamenti perdita di cifre meno significative nella mantissa errori non gravi (non percentualmente rilavanti) entrambe notazioni, virgola fissa e mobile impiegabili sia in memoria dell elaboratore sia nella rappresentazione (programmi e I/O) conversioni relative trasparenti all utente spazio e valori per variabili float e double dipendono da implementazione unico fatto certo: spazio (float) spazio (double) spazio (long double) - 5 -

Esempio tipico float in 4 byte e double in 8 byte accuratezza 6 decimali per float 15 decimali per double valori tra 10 38 e 10 +38 per float tra 10 308 e 10 +308 per double operazioni applicabili a float (anche a double e long double) = Assegnamento +, -, *, Somma, sottrazione, moltiplicazione / Divisione (risultato reale; simbolo identico a divisione intera) == Relazione di uguaglianza!= Relazione di diversità <, >, <=, >= Relazione minore di, etc. standard library fornisce funzioni predefinite (sqrt, pow, exp, sin, cos, tan...) nel testo, Appendice C, <math.h> applicate a valori double useremo double anche quando basta float Esempi trasforma temperatura in Fahrenheit ( F) in Celsius ( C) formula di conversione C = (5/9) ( F 32) NB 5 e 9 scritti come reali (con la virgola e una cifra decimale) / appkcato a 5 e 9 dà zero (quoziente troncato) /* Programma Fahrenheit Celsius */ #include <stdio.h> main() int Ftemp; float Ctemp; printf("inserire la temperatura in gradi Fahrenheit da convertire in gradi Celsius\n"); scanf("%d", &Ftemp); Ctemp = (5.0/9.0) * (Ftemp 32); printf("%d gradi Fahrenheit corrispondono a %f gradi Celsius\n", Ftemp, Ctemp); - 6 -

calcola il volume di sfera di raggio r mediante formula V = (4/3) πr 3. /* Programma VolumeSfera */ #include <stdio.h> main() const float Pi = 3.1415; float volume, raggio; printf("inserire il raggio della sfera\n"); scanf("%f", &raggio); volume = (4.0/3.0) * Pi * raggio * raggio * raggio; printf("il volume della sfera di raggio %f è %f\n, raggio, volume); Osservazione sull uso dei reali approssimazione nella rappresentazione pericolosi (non formalmente vietati) confronti di uguaglianza (x/y) * y == x potrebbe risultare falsa invece di if (x == y)... consigliabile scrivere if (x <= y +.000001 && y <= x +.000001)... - 7 -

Il tipo char char abbreviazione di character carattere lettere, cifre, simboli usuali delle tastiere codifica ASCII: ogni carattere codificato come valore intero codifica ASCII definisce ordinamento compatibile con quello alfabetico usuale Dec Simbolo ASCII Dec Simbolo ASCII 44, 87 W 45-88 X 46. 89 Y 47 / 90 Z 48 0 91 [ 49 1 92 \ 50 2 93 ] 51 3 94 ^ 52 4 95 _ 53 5 96 ` 54 6 97 a 55 7 98 b 56 8 99 c 57 9 100 d 58 : 101 e 59 ; 102 f 60 < 103 g 61 = 104 h 62 > 105 i 63? 106 j 64 @ 107 k 65 A 108 l 66 B 109 m 67 C 110 n 68 D 111 o 69 E 112 p 70 F 113 q 71 G 114 r 72 H 115 s 73 I 116 t 74 J 117 u 75 K 118 v 76 L 119 w 77 M 120 x 78 N 121 y 79 O 122 z 80 P 123 81 Q 124 82 R 125 83 S 126 ~ 84 T 127 Ž 85 U 128 Ç 86 V 129 ü standard library dà funzioni predefinite per manipolare caratteri vedi <ctype.h> in Appendice C - 8 -

caratteri di controllo la loro scrittura non visualizza un segno grafico provoca esecuzione operazione correlata \n = newline \b = backspace \t = horizontal tab \r = carriage return per variabili char, signed char e unsigned char allocato un byte 256 valori diversi per signed char 128 a +127 per unsigned char da 0 a 255 per char definite operazioni di assegnamento (=) aritmetiche (+,, *, /, %) relazionali (==,!=, < ecc.) char del tutto analoghi a int e rappresentati in memoria come interi caratteri trattati come piccoli interi piccoli interi trattati come caratteri esempio: legge e scrive caratteri, trasformando lettere minuscole in maiuscole /* Programma ManipolazioneCaratteri */ #include <stdio.h> main() char C, CM; printf("inserire un carattere # per terminare il programma\n"); scanf("%c", &C); while (C!= '#') printf("il codice ASCII del carattere %c è %d\n", C, C); if (C >= 'a' && C <= 'z') /* Se il carattere è una lettera minuscola */ /* La differenza 'a' 'A' è lo scarto fra la rappresentazione ASCII delle lettere maiuscole e minuscole dell'alfabeto */ CM = C ('a' 'A'); printf("la lettera maiuscola per %c è %c e il suo codice ASCII è %d\n", C, CM, CM); printf("inserire un carattere # per terminare il programma\n"); scanf("%c", &C); - 9 -

Classificazione dei tipi predefiniti del C Tipi integral: char signed char unsigned char short int long unsigned short unsigned unsigned long Tipi floating: float double long double Tipi arithmetic: tipi integral + tipi floating Ogni espressione a valore di tipo integral stampabile sia con formato char sia int caratteristiche condivise dai valori dei tipi arithmetic totalmente ordinati: x y ( x!= y x < y oppure y < x) limitati i valori dei tipi integral sono insiemi discreti non per i floating, detti densi, e.g. tra 3.0 e 4.0 numero molto elevato di reali - 10 -

Definizione di nuovi tipi forma tipica della dichiarazione Esempio typedef definizionenuovotipo ; typedef int anno; nome del nuovo tipo utilizzabile per altre dichiarazioni anno y; /* variabile y di tipo anno*/ possibile fare a meno di typedef, ma noi lo useremo sempre Tipi semplici definiti dall utente, per ridefinizione enumerazione esplicita dei valori forma tipica Ridefinizione typedef TipoEsistente NuovoTipo; Esempi typedef int typedef char typedef tipo1 typedef tipo2 tipo1; tipo2; tipo3; tipo4; Enumerazione esplicita dei valori valori elencati tra parentesi graffe, separati da una virgola Esempi typedef enum lun, mar, mer, gio, ven, sab, dom GiornoDellaSettimana; typedef enum rosso, verde, giallo, arancio, violetto, marrone, nero, ocra colore; typedef enum Giovanni, Claudia, Carla, Simone, Serafino persone; typedef enum gen, feb, mar, apr, mag, giu, lug, ago, set, ott, nov, dic mese;... persone individuo, individuo1, individuo2;... individuo = Giovanni; if (individuo1 == individuo2) individuo = Claudia; - 11 -

NB Giovanni e Claudia valori di tipo persone Giovanni e Claudia di tipo stringa NB: valori di tipo enumerativo codificati mediante interi applicabili tutti gli operatori degli interi esempi di relazioni vere (!= 0) apr < giu rosso < arancio (apr == 3) esempi di relazioni false (== 0) dom < lun Simone < Giovanni tipi enumerati, come gli integral, sono totalmente ordinati limitati enumerabili Esempio: definizione del tipo boolean analogo a quello del Pascal typedef enum boolean false, true boolean; flag, ok; Tipi strutturati informazione aggregata: esempi vettori e matrici in matematica elenchi di nomi archivi di fatture anagrafi, etc variabili strutturate memorizzano diversi elementi informativi costrutture array unva riabile di tipo array denotata (al solito) con un identificatore composta da sequenza di variabili dello stesso tipo memorizzate in celle consecutive accessibili direttamente identificate da loro posizione (indice 0) - 12 -

dichiarazione di un tipo array di nome anarray typedef int anarray[20]; /* un array di 20 int */ typedef double NuovaLista[30]; /* un array di 30 double */ dichiarazione di variabili di tipo anarray anarray lista1, lista2; anarray lista3; dichiarazione abbreviata di variabile array senza definire prima il tipo int lista[20]; lista array di 20 int Esempi scanf( %d, lista[2]); /* legge un dato nella terza cella dell array lista */ lista1[3] = lista2[1] + 5; indice di array dev essere di tipo integral è compreso tra 0 (incluso) e valore max indicato in dichiarazione (escluso) si può denotare con una variabile o in generale con un espressione x = a[i]; a[i] = a[i+1]; a[i*x] = s[a[j + 1] 3] * (y a[y]); Per accedere a cella di array, macchina astratta C deve: calcolare il valore dell indice; sommare il valore calcolato all indirizzo della prima cella dell array (la numero 0). dichiarazione di tipo con costruttore array consiste in: parola chiave typedef identificatore tipo elementi dell array; può essere qualsiasi identificatore nuovo tipo array om corso di definizione; dimensione dell array, un numero intero tra parentesi [] dichiarazione abbreviata di singola variabile array consiste in: identificatore tipo dell elemento dell array identificatore della variabile dimensione dell array, un numero intero tra parentesi [] - 13 -

NB l array è un costruttore di tipo, non un tipo ci sono tanti diversi tipi array, non uno solo differiscono per numero indici numero di elementi in ogni indice tipo elemento la locuzione la variabile a è di tipo array significa la variabile a è di un tipo ottenuto mediante il costruttore array dichiarazione di tipo array implicita in dichiarazione di variabile dichiarazione singola int lista[20]; o doppia typedef int anonimo[20]; anonimo lista; meglio la prima, in assenza di motivi per dare nome esplicito al tipo invece di typedef double VettoreDiReali[20]; VettoreDiReali v1, v2, v3; meglio la più semplice e altrettanto chiara double v1[20], v2[20], v3[20]; all opposto: typedef typedef PioggeMensili IndiciBorsa double PioggeMensili[12]; double IndiciBorsa[12]; Piogge87, Piogge88, Piogge89; Indici87, Indici88, Indici89; più comprensibile di double Piogge87[12], Piogge88[12], Piogge89[12], Indici87[12], Indici88[12], Indici89[12]; - 14 -

NB elementi degli array possono essere di tipi arbitrari (predefiniti, definiti dall utente, semplici o strutturati) possibile costruire array di array Esempio: typedef int typedef Vettore Vettore[20]; MatriceIntera20Per20[20]; MatriceIntera20Per20 matrice1; dichiarazione alternativa più sintetica per il tipo Matrice20Per20 typedef int Matrice20Per20[20][20]; e per la variabile matrice1 int matrice1[20][20]; Esempio: matrice tridimensionale potrebbe essere dichiarata come int matricetrid1[10][20][30]; per accedere agli elementi di matricetrid1 matricetrid1[2][8][15] Esempio: typedef enum colore rosso, verde, giallo, arancio, violetto, marrone, nero, ocra colore; ListaColori[10]; NB: array hanno dimensioni fisse, note al momento della compilazione ciò può provocare inconvenienti al programmatore array può essere troppo piccolo prevedere memoria aggiuntiva troppo grande spreco di memoria ma facilita realizzazione compilatori ed esecuzione programmi esempio classico: stringhe di caratteri typedef char String[30]; String Nome, Cognome; /* il cognome di un nobile spagnolo non ci sta per un italiano medio è troppo lungo*/ - 15 -

flessibilità parziale ottenibile con dichiarazione di costanti Esempio programma inverte una sequenza di un prefissato numero di interi /* Programma InvertiSequenza */ #include <stdio.h> main() int Contatore; int Memorizzazione[100]; Contatore = 0; while (Contatore < 100) /* NB il valore dell'indice di un array di 100 elementi varia da 0 a 99 */ scanf("%d", &Memorizzazione[Contatore]); Contatore = Contatore + 1; Contatore = Contatore 1; while (Contatore >= 0) printf("%d\n", Memorizzazione[Contatore]); Contatore = Contatore 1; programma fissato a 100 interi per considerare 1000 interi, sostituire tutte occorrenze di 100 con 1000 e ricompilare pericolo di errori nella sostituzione soluzione migliore: uso di una costante non si può usare costrutto const si usa direttiva #define #define LunghezzaSequenza 100 preprocessore sostituisce testualmente LunghezzaSequenza con 100-16 -

nuova versione più facilmente modificabile /* Program InvertiSequenza */ #include <stdio.h> #define LunghezzaSequenza 100 main() int Contatore; int Memorizzazione[LunghezzaSequenza]; Contatore = 0; while (Contatore < LunghezzaSequenza) scanf("%d", &Memorizzazione[Contatore]); Contatore = Contatore + 1; Contatore = Contatore 1; while (Contatore >= 0) printf("%d\n", Memorizzazione[Contatore]); Contatore = Contatore 1; a elementi di array applicabili operazioni caratteristiche del loro tipo NB: variabili array non possono essere oggetto di confronto o assegnamento confronto e assegnamento vanno fatti elemento per elemento Esempio typedef int anarray[10]; int i; anarray Array1, Array2; Array2 = Array1; /* SCORRETTO! */ i = 0; while (i <= 10) Array2[i] = Array1[i]; /* CORRETTO */ NB: nella standard library funzioni predefinite per manipolare stringhe stringhe array di caratteri parte significativa terminata da carattere speciale \0 (ASCII 0) stringa word w o r d \0-17 -

aggrega informazioni eterogenee Il costruttore struct Esempio variabili di tipo impiegato contenenti nome, cognome, codice fiscale, indirizzo, numero di telefono, stipendio, data di assunzione etc. uso di array innaturale o impossibile poiché elementi di array omogenei elementi aggregati si chiamano campi della struttura struct è costruttore di tipi come l array, usato per dichiarazioni di tipo dichiarazioni di variabili con tipo anonimo implicito sintassi della dichiarazione esplicita di tipo con struct: 1. parola chiave typedef struct 2. elenco dei campi racchiuso fra graffe 2.1. campo 2.1.1. tipo del campo, 2.1.2. identificatore del campo 2.1.3. terminatore ; 3. identificatore del nuovo tipo ottenuto tramite il costruttore struct; 4. terminatore ; NB se più campi dello stesso tipo al posto di identificatore del campo (punto 2.1.2) lista di identificatori separati da, Esempi 1. typedef struct int Giorno; int Mese; int Anno; Data; 2. typedef char String[30]; typedef struct String Destinatario; int Importo; Data DataEmissione; DescrizioneFatture; - 18 -

3. typedef enum On, Off AccType; typedef struct int AccType double CanaliTV; Canale; Accensione; CursoreLuminosita, CursoreColore, CursoreVolume; 4. typedef enum Dirigente, Impiegato, Operaio CatType; typedef struct String String int char Data CatType Dipendenti; Nome; Cognome; Stipendio; CodiceFiscale[16]; DataAssunzione; Categoria; dichiarazione di variabili di un tipo struct definito esplicitamente Dipendenti Dip1, Dip2; sintassi della dichiarazione abbreviata di variabili di tipo struct parola chiave struct elenco dei campi della struttura come nella dichiarazione esplicita; identificatore (o identificatori) di variabile (separati da virgola); terminatore di dichiarazione ; Esempio: dichiarazione abbreviata di Dip1 e Dip2 precedenti: struct String Nome; String Cognome; int Stipendio; char CodiceFiscale[16]; Data DataAssunzione; CatType Categoria; Dip1, Dip2; meccanismo per accedere ai singoli elementi: identificatore della struttura punto identificatore del campo Esempio: aumentare del 10% stipendio di Dip1 Dip1.Stipendio = Dip1.Stipendio + (Dip1.Stipendio*10) / 100; - 19 -

meccanismi di accesso combinabili esattamente come i costruttori di tipi Esempi: Dip1 è stato assunto il 3 gennaio 1993 Dip1.DataAssunzione.Giorno = 3; Dip1.DataAssunzione.Mese = 1; Dip1.DataAssunzione.Anno = 1993;... se la prima lettera del cognome di Dip1 è A... if (Dip1.Cognome[0] == 'A')... dichiarando variabile ArchivioFatture: DichiarazioneFatture ArchivioFatture[1000]; stampa importo fattura numero 500 se è stata emessa entro il 1991, altrimenti stampa messaggio if (ArchivioFatture[500].DataEmissione.Anno <= 1991) printf("%d", ArchivioFatture[500].Importo); else printf("la fattura in questione è stata emessa dopo il 1991\n"); a elementi di struttura applicabili tutte le operazioni caratteristiche del loro tipo a variabili struttura applicabili operazioni globali di confronto (==,!=) e assegnamento (NB contrario di quanto accade ad array) Esempio: Dipendenti Dip1, Dip2;... Dip2 = Dip1; NB: due campi del tipo Dipendenti sono array) array e strutture trattati in modo diverso - 20 -

Il costruttore puntatore finora ogni variabile denotata attraverso il suo nome x = a; meccanismo alternativo: i puntatori variabili il cui valore è un riferimento (indirizzo) a una variabile dichiarazione di un tipo puntatore denominato TipoPuntatore typedef TipoDato *TipoPuntatore; TipoPuntatore P; variabili di tipo TipoPuntatore contengono indirizzo a variabili di tipo TipoDato accesso a variabile puntata mediante operazione di dereferenziazione simbolo * prima del puntatore *P denota variabile il cui indirizzo è contenuto in P Esempio typedef TipoDato *TipoPuntatore; TipoPuntatore P; TipoDato x; le seguenti istruzioni sono ammissibili: *P = x; x = *P; effetto, supponendo che TipoDato sia int - 21 -

ai puntatori applicabili operazioni di confronto e di assegnamento operatore inverso a quello di dereferenziazione: indirizzo di, indicato col simbolo & Esempio typedef TipoDato *TipoPuntatore; TipoPuntatore P, Q; TipoDato y, z;... P = &y; Q = &z;... P = Q; NB dfferenza tra assegnamenti P = Q e *P = *Q: costrutto * è un costruttore di tipo come array e struct e con le stesse conseguenze - 22 -

Esempi di dichiarazione typedef TipoDato *TipoPuntatore; typedef AltroTipoDato *AltroTipoPuntatore; TipoDato *Puntatore; /* forma abbreviata di dichiarazione */ TipoDato **DoppioPuntatore; /* DoppioPuntatore punta a un puntatore a TipoDato */ TipoPuntatore P, Q; AltroTipoPuntatore P1, Q1; TipoDato x, y; AltroTipoDato z, w; istruzioni corrette Puntatore = &y; DoppioPuntatore = &P; Q1 = &z; P = &x; P = Q; *P = *Q; *Puntatore = x; P = *DoppioPuntatore; z = *P1; Puntatore = P; istruzioni scorrette: P1 = P; w = *P; *DoppioPuntatore = y; Puntatore = DoppioPuntatore; *P1 = *Q; strutture e puntatori se TipoDato di cui sopra dichiarato come typedef struct int PrimoCampo; char SecondoCampo; TipoDato; per accedere a componente PrimoCampo della variabile puntata da P: (*P).PrimoCampo (NB priorità di. maggiore di *, quindi servono parentesi) C fornisce notazione equivalente più sintetica P > PrimoCampo - 23 -

quindi si può scrivere sia P >PrimoCampo = 12; sia (*P).PrimoCampo = 12; valore NULL per i puntatori: informazione nel puntatore non significativa P == NULL consiglio: NON assumere che i puntatori inizialmente valgano NULL Esempio: array contenente 100 interi; assegna a due puntatori l indirizzo delle componenti con valore minimo e massimo /* Programma Puntatori all'elemento maggiore e minore di un array */ #define LunghezzaArray 100 main() int i; int ArrayDiInt[LunghezzaArray]; int *PuntaAMinore; int *PuntaAMaggiore;... PuntaAMinore = &ArrayDiInt[0]; i = 1; while (i < LunghezzaArray) if (ArrayDiInt[i] < *PuntaAMinore) PuntaAMinore = &ArrayDiInt[i]; i = i + 1; PuntaAMaggiore = &ArrayDiInt[0]; i = 1; while (i < LunghezzaArray) if (ArrayDiInt[i] > *PuntaAMaggiore) PuntaAMaggiore = &ArrayDiInt[i]; i = i + 1; - 24 -

Esempio: array DatiLavoratori con dati di 300 lavoratori (dirigenti, impiegati, operai) array Management con 10 puntatori a elementi di DatiLavoratori che sono dirigenti Stampa cognome e stipendi dei dirigenti che guadagnano più di 5000000 /* Programma Dirigenti */ #include <stdio.h> main() typedef enum dirigente, impiegato, operaio CatLav; typedef struct char Nome[30]; char Cognome[30]; CatLav Categoria; int Stipendio; char CodiceFiscale[16]; Lavoratore; Lavoratore DatiLavoratori[300]; Lavoratore *Management[10];... i = 0; while (i < 10) if (Management[i] >Stipendio > 5000000) j = 0; while (j < 30) printf("%c", Management[i] >Cognome[j]); j = j + 1; printf("%d \n", Management[i] >Stipendio); i = i + 1; attenzione, sul testo qsta istrzne sta erroneamente due righe più sotto rischi della programmazione mediante puntatori effetti collaterali (side effects) non facilmente e completamente prevedibili *P = 3; *Q = 5; P = Q; /* A questo punto *P = 5 */ *Q = 7; ora *Q = 7, ma anche, surrettiziamente, *P = 7 nota differenza con istruzioni analoghe senza puntatori int x, y; x = 3; y = 5; x = y; y = 7; /* x continua a valere 5 */ - 25 -

Array, puntatori e aritmetica dei puntatori in C stretta parentela tra array e puntatori fatti importanti elementi di array occupano in memoria numero di parole dipendente dal tipo elementi di array allocati in parole di memoria consecutive operatore sizeof dà numero di byte occupati da un tipo (o variabile) se su un calcolatore un valore int occupa 4 byte, dichiarando int a[5]; allora sizeof(a[2]) restituisce 4 e sizeof(a) restituisce 20, l ingombro complessivo dell array a nome di variabile di tipo array (e.g., a) è una costante di tipo puntatore (al tipo componente l array) con valore indirizzo della prima parola di memoria allocata all array C permette operazioni di somma e sottrazione tra puntatori sommando costante a puntatore valore incrementato di multiplo dell ingombro del tipo puntato TipoDato *P; se sizeof(tipodato) == 4 ( NB: stiamo assumendo parole di un byte ) P P+1 P+2 P+3 P+4-26 -

ciò utile in connessione agli array in presenza di int a[5]; int i; a[i] equivale a *(a+i) (i+1-simo elemento) quindi p = a è equivalente a p = &a[0]; p = a+1 è equivalente a p = &a[1]; NB non sono ammessi assegnamenti ad a perchè a è una costante a = p; /* errore */ a = a +1; /* errore */ se p e q puntano a due diversi elementi di un array p q dà la distanza nell array tra gli elementi puntati NB questa può non coincidere con differenza aritmetica tra valore numerico dei puntatori - 27 -

tipi in C: compatibilità e conversioni alcune incompatibilità tra tipi ovvie e necessarie esempio: non ha senso assegnare una variabile int a una variabile struct altri casi dubbi assegnamento di una variabile int a una float di una float a una int criterio adottato da C per calcolo di espressioni (e assegnamenti) se costanti e variabili dello stesso tipo operazione associata a quel tipo se di tipi diversi applica, se possibile regole di conversione trattiamo solo regole di conversione implicita, non quelle di conversione esplicita (cast) tipizzazione forte: regole verificabili a tempo di compilazione Espressioni che coinvolgono elementi eterogenei in tipo ogni espressione aritmetica (e.g., x + y) caratterizzata da valore del risultato tipo del risultato tipo degli operandi determina operazione eseguita se x e y di tipo int eseguita operazione del tipo int e restituito valore di tipo int se x di tipo short e y di tipo int si converte una delle due x temporaneamente convertita in int applicata operazione di somma tra interi prodotto risultato int - 28 -

regola generale per espressioni aritmetiche (conversione implicita) x op y quando tipi di x e y diversi in C i tipi sono ordinati in base alla precisione char < short < int < long < float < double < long double valori del tipo meno preciso implicitamente convertiti a valore del tipo più preciso (promozione) operazione effettuata con le regole del tipo più preciso risultato è un valore del tipo più preciso - 29 -

Assegnamenti che coinvolgono elementi eterogenei in tipo effettuate conversioni implicite Esempio double d; int i;... d = i; valore di i convertito a double e assegnato a d non c è perdita di informazione... i = d; d convertito a int (troncandolo), valore intero assegnato a i perdita informazione altro esempio già visto int Ftemp; float Ctemp; printf("inserire la temperatura in gradi Fahrenheit da convertire in gradi Celsius\n"); scanf("%d", &Ftemp); Ctemp = (5.0/9.0) * (Ftemp 32); 5.0 e 9.0 sono costanti reali risultato divisione è reale Ftemp variabile intera e 32 e costante intera risultato sottrazione intero moltiplicazione causa conversione implicita (promozione) di (Ftemp 32) a float risultato float assegnato alla Ctemp, che è float conversioni, terreno scivoloso... attenzione a quanto accade con gli unsigned ( evitarli) Puntatori e tipizzazione delle variabili puntate compilatore segnala utilizzo congiunto di puntatori a dati di tipo differente - 30 -

La costruzione incrementale dei programmi per problemi complessi difficile costruire in una sola botta programmi corretti troppi dettagli da considerare congiuntamente sintattici (notazioni del linguaggio) semantici (peculiarità del problema) tecnica adottata sviluppare diverse versioni dell algoritmo aumentando gradualmente livello di dettaglio e formalità del codice inizialmente formulazioni molto compatte e informali poi versioni più precise e dettagliate linguaggio semiformale usato nelle versioni intermedie chiamato pseudocodice adattamento alla programmazione dell antico motto divide et impera Esempio programma legge da standard input (carattere per carattere) - una parola, poi carattere $ - poi un altra parola, poi il carattere # - poi sequenza di parole separate da spazio chiusa da spazio, seguito da carattere terminatore % Scrive su standard output testo dopo il #, in cui prima parola sostituita dalla seconda Esempio rosso$giallo#il semaforo era rosso ma non si fermava nessuno % diventa in uscita Il semaforo era giallo ma non si fermava nessuno Se manca prima parola Se manca seconda parola stampa messaggio prima parola sempre cancellata - 31 -

Cosa occorre memorizzare? prime due parole lette usiamo due variabili primaparola e secondaparola Non occorre memorizzare il testo: dopo aver letto le prime due parole basta - memorizzare una parola, - confrontarla con la prima parola - scrivere la parola stessa o la seconda parola a seconda del risultato per memorizzare ogni parola letta dopo # usiamo variabile parolacorrente programma non banale: procediamo incrementalmente prima versione dell algoritmo 1. Verifica se esiste una parola prima di $ 2. Se manca stampa il messaggio MANCA LA PAROLA DA SOSTITUIRE, altrimenti... 3. Memorizza prima parola in un array di caratteri 4. Memorizza seconda parola in un altro array 5. scandisci l intero testo parola per parola (fino a carattere %) 4.1. Memorizza ogni parola in un array 4.2. Confronta parola letta con prima parola 4.3. Se le due parole coincidono, 4.3.1. scrivi nello Standard Output la seconda parola 4.3.2 altrimenti scrivi la parola appena letta - 32 -

pseudocodice con parti informali racchiuse tra quadre /* Programma SostituzioneParole */ main() char carattere; char PrimaParola[30], SecondaParola[30], ParolaCorrente[30]; scanf( %c, carattere); if (carattere == '$') printf("manca LA PAROLA DA SOSTITUIRE"); else [memorizza in PrimaParola sequenza di caratteri fino a '$']; [memorizza in SecondaParola sequenza di caratteri fino a '#']; scanf( %c, carattere); while (carattere!= '%') [memorizza in ParolaCorrente sequenza caratteri fino a spazio]; [confronta PrimaParola con ParolaCorrente]; if ([PrimaParola == ParolaCorrente]) [printf(secondaparola)]; else [printf(parolacorrente)]; printf( %c, ' '); /* in entrambi i casi scrive spazio per separare da parola successiva */ scanf( %c, carattere); /* Inizia la lettura della prossima ParolaCorrente, o legge % */ ora occorre precisare memorizzazione di una parola in un array confronto tra due parole scrittura di una parola consideriamo il meno semplice: il confronto. semplice strategia: 1. se lunghezze due parole diverse 1.1. allora parole diverse 1.2. altrimenti 1.2.1. scandisci i due array carattere per carattere fino a quando trovi due caratteri diversi o l indice dell array supera lunghezza parola 1.2.2. se trovi due caratteri diversi 1.2.2.1. allora le due parole sono diverse 1.2.2.2. altrimenti le due parole coincidono. - 33 -

NB occorre ricordare lunghezza delle parole, usiamo LungPrimaPar, LungSecPar e LunghParCorr ora è facile la codifica in C if (LunghPrimaPar == LunghParCorr) contatore = 0; while ((contatore < LunghPrimaPar) && PrimaParola[contatore] == ParolaCorrente[contatore])) contatore = contatore + 1; if (contatore >= LunghPrimaPar) [Le due parole coincidono] else [Le due parole sono diverse] else [Le due parole sono diverse] rimane codice per lettura e scrittura di parole, relativamente semplice /* Programma SostituzioneParole */ #include <stdio.h> main() char carattere; char PrimaParola[30], SecondaParola[30], ParolaCorrente[30]; int LungPrimaPar, LungSecPar, LungParCorr, contatore; scanf( %c, carattere); if (carattere == '$') printf ("MANCA LA PAROLA DA SOSTITUIRE"); else /* Memorizzazione della prima parola */ contatore = 0; while (carattere!= '$') PrimaParola[contatore] = carattere; contatore = contatore + 1; scanf( %c, carattere); LunghPrimaPar = contatore; /* Memorizzazione della seconda parola */ scanf( %c, carattere); contatore = 0; while (carattere!= '#') SecondaParola[contatore] = carattere; contatore = contatore + 1; scanf( %c, carattere); LungSecPar = contatore; /* fase di scansione del testo */ - 34 -

scanf( %c, carattere); while (carattere!= '%') /* Memorizzazione della parola corrente */ contatore = 0; while ( carattere!= ' ' ) ParolaCorrente[contatore] = carattere; contatore = contatore + 1; scanf( %c, carattere); LungParCorr = contatore; /* confronta prima parola con parola corrente */ if (LunghPrimaPar == LunghParCorr) contatore = 0; while (contatore < LunghPrimaPar && PrimaParola[contatore] == ParolaCorrente[contatore]) contatore = contatore + 1; if (contatore >= LunghPrimaPar ) /* ricopia seconda parola */ contatore = 0; while (contatore < LungSecPar) printf( %c, SecondaParola[contatore]); contatore = contatore + 1; else /* ricopia parola corrente */ contatore = 0; while (contatore < LungParCorr) printf( %c, ParolaCorrente[contatore]); contatore = contatore + 1; else /* lunghezze differenti, copia Parola corrente */ contatore = 0; while (contatore < LungParCorr) printf( %c, ParolaCorrente[contatore]); contatore = contatore + 1; printf( %c, ' '); /* in entrambi i casi scrive spazio per separare da parola successiva */ scanf( %c, carattere); /* Inizia la lettura della prossima ParolaCorrente, o legge % */ - 35 -

revisione: ogni parola ha la sua lunghezza coppia variabili parola si può usare struct con array di char per la stringa int per la sua lunghezza si possono confrontare per uguaglianza le parole-strutture attenzione: parte di array oltre la lunghezza deve essere uguale (e.g., spazi bianchi) nuova versione /* Programma SostituzioneParole */ #include <stdio.h> main() typedef char stringa[30]; typedef struct stringa s; int parola; char carattere; lun; parola PrimaParola, SecondaParola, ParolaCorrente; int contatore; scanf( %c, carattere); if (carattere == '$') printf ("MANCA LA PAROLA DA SOSTITUIRE"); else /* Memorizzazione della prima parola */ contatore = 0; while (carattere!= '$') PrimaParola.s[contatore] = carattere; contatore = contatore + 1; scanf( %c, carattere); PrimaParola.lun = contatore; /* aggiungi spazi bianchi in fondo */ while (contatore < 30 ) PrimaParola.s[contatore] = ; contatore = contatore + 1; /* Memorizzazione della seconda parola */ scanf( %c, carattere); contatore = 0; while (carattere!= '#') SecondaParola.s[contatore] = carattere; contatore = contatore + 1; scanf( %c, carattere); SecondaParola.lun = contatore; - 36 -

/* aggiungi spazi bianchi in fondo */ while (contatore < 30 ) PrimaParola.s[contatore] = ; contatore = contatore + 1; /* nella fase di scansione del testo */ scanf( %c, carattere); while (carattere!= '%') /* Memorizzazione della parola corrente */ contatore = 0; while carattere!= ' ' ParolaCorrente.s[contatore] = carattere; contatore = contatore + 1; scanf( %c, carattere); ParolaCorrente.lun = contatore; while (contatore < 30 ) ParolaCorrente.s[contatore] = ; contatore = contatore + 1; /* confronta prima parola con parola corrente */ if (PrimaParola == ParolaCorrente) /* ricopia seconda parola */ contatore = 0; while (contatore < SecondaParola.lun) printf( %c, SecondaParola.s[contatore]); contatore = contatore + 1; else /* parole differenti, copia Parola corrente */ contatore = 0; while (contatore < ParolaCorrente.lun) printf( %c, ParolaCorrente.s[contatore]); contatore = contatore + 1; printf( %c, ' '); /* in entrambi i casi scrive spazio per separare da parola successiva */ scanf( %c, carattere); /* Inizia la lettura della prossima ParolaCorrente, o legge % */ NB spesso revisioni della prima soluzione portano miglioramenti, anche di efficienza consiglio: non puntare subito a soluzione ottima meglio costruire prima versione semplice e poi migliorarla - 37 -