Esercitazione 3 - Note

Documenti analoghi
Linguaggio C - Array. Array: tipo nome_array[num_elementi]

Non ci sono vincoli sul tipo degli elementi di un vettore Possiamo dunque avere anche vettori di

Esercitazione di Reti degli elaboratori

ARRAY DI PUNTATORI. ARRAY DI PUNTATORI Non ci sono vincoli sul tipo degli elementi di un vettore Possiamo dunque avere anche vettori di puntatori

Cicli annidati ed Array multidimensionali

Strutture dati. Operatori di incremento e decremento. Strutture di dati. Strutture di dati. ++ e -- Esempi. Vettori e matrici.

Tipi strutturati in C. Stringhe

Programmazione I - Laboratorio

Gli array. slides credit M. Poneti

Caratteri e stringhe

Caratteri e stringhe

Esercizi. Filtraggio

Lezione 8: Stringhe ed array multidimensionali

Una stringa di caratteri in C è un array di caratteri terminato dal carattere '\0' a p e \0

definisce un vettore di 4 puntatori a carattere (allocata memoria per 4 puntatori)!

Dati due punti sul piano calcolare la loro distanza

ELEMENTI DI INFORMATICA L-B. Ing. Claudia Chiusoli

Introduzione al linguaggio C Dati aggregati

Realizzare un programma che legga da input tre numeri interi e stampi a video la loro somma e la media.

Tipi di dato STRUTTURATI

I Dati Strutturati ed il Linguaggio C

Esercizio 1: parole nel testo

Esercitazione 6. Array

Array Tipi di dato semplici e strutturati strutturati array elementi omogenei numero d ordine indice lunghezza dimensione

Introduzione al C. Lez. 1 Elementi. Rossano Venturini

RICORSIONE, PUNTATORI E ARRAY. Quarto Laboratorio

C: panoramica. Violetta Lonati

Fondamenti di Informatica T1. Lab 03 Istruzioni. Lab03 1

Esercizi C su array e matrici

I tipi strutturati e i record in C++

Lab 03 Istruzioni Prima Parte"

Esercizio 1 - cicli. Esercizio 1 cicli - Soluzione

ERRATA CORRIGE. void SvuotaBuffer(void); void SvuotaBuffer(void) { if(getchar()!=10) {svuotabuffer();} }

RIPRENDIAMO I PUNTATORI

Unità Didattica 4 Linguaggio C. Vettori. Puntatori. Funzioni: passaggio di parametri per indirizzo.

Laboratorio di Informatica I

Array. Aggragati di variabili omogenee...

Lezione 6: Array e puntatori

Compito A. Compito A Sintesi (main(

Dati aggregati. Violetta Lonati

Stringhe Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Fondamenti di Informatica e Laboratorio T-AB Ingegneria Elettronica e Telecomunicazioni. Lab 05 Array. Lab06 1

Il linguaggio C Puntatori

Informatica (A-K) 14. Linguaggio C -4

Università degli Studi di Brescia. Vettori di variabili. ! Sono variabili aggregate in grado di memorizzare una collezione (organizzata) di oggetti

Soluzione/* PROGRAMMAZIONE IN C */ #include <stdio.h> #include <stdlib.h>

Linguaggio C: Stringhe Valeria Cardellini

Introduzione al C. Lez. 1 Elementi. Rossano Venturini

Linguaggi di programmazione + laboratorio a.a. 2012/2013

Laboratorio di Calcolatori 1 Corso di Laurea in Fisica A.A. 2006/2007

Fondamenti di Informatica 12. Linguaggio C -4

Esercizio 1 - Soluzione (array)

Linguaggio C: Array Valeria Cardellini

Introduzione al C. Lez. 1 Elementi

Dichiarazioni e tipi predefiniti nel linguaggio C

Array e Matrici. Perchè usare gli array?

Programmazione in C. La struttura del programma Variabili, espressioni, operazioni

Stringhe in C. Alessandra Giordani Lunedì 23 aprile 2012

Fondamenti di Informatica T-1 Modulo 2

Tipi di dato strutturati: Array

Esercizi. Stringhe. Stringhe Ricerca binaria

2 Operatori matematici e costrutto if

Primo programma in C

Alcuni esercizi. 1. Valutazione in cortocircuito 2. If e if innestati 3. Switch 4. Cicli

Linguaggio C - Stringhe

Fondamenti di Informatica T-1 Modulo 2

Fondamenti di Informatica

Tipi di dato strutturati: Array

STRINGHE: ARRAY DI CARATTERI! a p e \0

Esercizio 1: calcolo insieme intersezione

Corso sul linguaggio C

Gli array. impone al programma, in fase di esecuzione, di riservare dello spazio in memoria per 10 variabili di tipo int

Corso di Laboratorio di Sistemi Operativi A.A

Stringhe in C. Emilio Di Giacomo

T = { D, {F 1,...,F n }, {P 1,...,P m } }

Lezione 6: Funzioni di I/O avanzate

(Def. funzioni con parametri di tipo matrice)

STRINGHE: ARRAY DI CARATTERI STRINGHE: ARRAY DI CARATTERI. a p e \0

Struttura dei programmi e Variabili

Informatica 2 modulo C Massimo Callisto De Donato

Linguaggio C. tipi di dati definiti dall utente. Università degli Studi di Brescia. Docente: Massimiliano Giacomin

I/O da tastiera + Alessandra Giordani Lunedì 2 maggio

Informatica (A-K) 5. Algoritmi e pseudocodifica

Esercizio 2 (punti 7) Dato il seguente programma C: #include <stdio.h> int swap(int * nome, int length);

Fondamenti di Informatica 6. Algoritmi e pseudocodifica

Problema. Vettori e matrici. Vettori. Vettori

I Vettori (Array) Prof. Francesco Accarino IIS Altiero Spinelli Sesto San Giovanni

Informatica 1. Prova di recupero 21 Settembre 2001

Introduzione al linguaggio C Puntatori

Introduzione al linguaggio C Primi programmi

La copia di un file. contare di quanti caratteri sia composto il file (e quindi determinare la dimensione del file di origine)

Nuovi tipi di dato e. Alessandra Giordani Lunedì 26 marzo

Ingresso ed Uscita in C. Informatica 1 / 15

Array multidimensionali e stringhe

Transcript:

Esercitazione 3 - Note Ing. Michele Scandale 18-10-2012 Il materiale illustrato a lezione e in queste note contiene anche esempi di Giacomo Boracchi, Luigi Cardamone, Nicola Basilico e Nicola Vitucci. Alcune precisazioni Array In C gli array sono una struttura dati che consente di memorizzare sequenze finite di un dato tipo di dato. int arr[6]; Gli array a loro volta possono essere tipi base di un array: tramite questo meccanismo si hanno gli array multimensionali. In particolare sono frequenti array bidimensionali, ovvero matrici. int mat[2][3]; Le matrici sono array di array, sono memorizzati per righe, infatti ogni riga può essere vista come un array degli elementi del tipo base, e tutta la matrice non è altro che un array di righe. Questo fatto lo si ritrova quando si vuole inizializzare direttamente con la dichiarazione. int mat[2][3] = {{1, 2, 3, {4, 5, 6; Come detto, la struttura in memoria di una matrice è paragonabile a quella di un array di opportune dimensioni. Ad esempio int arr[6] è equivalente a int mat[2][3]: infatti entrambi contengono 6 elementi di tipo intero. Inoltre: int mat[2][3] = {1, 2, 3, 4, 5, 6; con il compilatore gcc compila riportando uno warning relativo alla mancanza di parentesi graffe. Il compilatore è in grado di proiettare sulla struttura di matrice il vettore di costanti assegnato (infatti la rappresentazione effettiva della matrice è quella di un array), ma comunque notifica debolmente il fatto che ci sia qualcosa di sospetto. ATTENZIONE: è buona norma evitare confusione, dunque se si dichiara una matrice e la si inizializza è buona norma rispettarne la struttura al momento dell inizializzazione! 1

Array vs. stringhe Le stringhe in C sono array di char zero-terminati, cioè l ultimo valore dell array è il terminatore di stringa \0. Data una stringa di lunghezza L, lo spazio occupato sarà L + 1 char, poichè il terminatore non è considerato nel conteggio della lunghezza della stringa. Essendo le stringhe degli array, è possibile accedere ai singoli caratteri che la compongono! Si ricorda che gli indici degli elementi di un array appartengono all intervallo [0, N 1], dove N è il numero degli elementi di un array. In generale, l ultimo elemento di un array arr di lunghezza N è l elemento arr[n - 1]. Per le stringhe, invece, l ultimo carattere delle stringa str (diverso dal terminatore) è dato da str[l - 1], dove L è la lunghezza della stringa stessa e che dunque non considera il terminatore! Ordinamento lessicografico L ordine lessicografico è un criterio di ordinamento di stringhe costituite da una sequenza di simboli, per i quali è già presente un ordine interno. La regola di ordinamento corrisponde a quella utilizzata nei dizionari (da cui deriva il nome), anche se estesa ad un qualunque insieme di simboli. (Cit.: wikipedia) Dalla definizione cerchiamo di capire gli aspetti fondamentali: è una relazione d ordine tra sequenze di simboli, tra i quali esiste una relazione di ordine interna, ovvero è possibile confrontare tra loro i simboli singolarmente. In matematichese : si consideri un alfabeto finito Σ = (a 1, a 2,..., a n ), con a 1 < a 2 < < a n e due sequenze di simboli I, J con I = (α 1 α 2... α r ) J = (β 1 β 2... β s ) con α i, β j Σ, allora si dice che I < J se k per cui (α 1 α 2... α k ) = (β 1 β 2... β k ) e vale una delle seguenti relazioni: α k+1 < β k+1 r = k < s Sostanzialmente: si devono confrontare i simboli da sinistra a destra (dal primo indice verso l ultimo) e alla prima coppia di simboli diversi, in base alla relazione che vale tra i due simboli (maggiore o minore) si stabilisce deduce la medesima relazione per la sequenza. Se una delle due sequenze è più corta dell altra se tutti i simboli della prima sono uguali ai corrispondenti nella seconda risulta minore la sequenza breve! In C l ordinamento lessicografico è utillizzato con le stringhe (sequenze di char): si ricorda che questo è possibile proprio perchè esiste una corrispondenza biunivoca tra singoli caratteri e codifica numerica dei caratteri (codifica ASCII): 2

Caratteri 0 1 2 3 4 5 6 7 8 9 Codifica 48 49 50 51 52 53 54 55 56 57 Caratteri A B C D E F G H I J K L M Codifica 65 66 67 68 69 70 71 72 73 74 75 75 76 Caratteri N O P Q R S T U V W X Y Z Codifica 77 78 79 80 81 82 83 84 85 86 87 88 89 Caratteri a b c d e f g h i j k l m Codifica 97 98 99 100 101 102 103 104 105 106 107 108 109 Caratteri n o p q r s t u v w x y z Codifica 110 111 112 113 114 115 116 117 118 119 120 121 122 Alcuni esempi: caso è maggiore (è successivo in ordine lessicografico) rispetto a casa, poichè i primi 3 caratteri delle parole sono uguali mentre o è maggiore di a barca è minore (è precedente in ordine lessicografico) rispetto a barcaccia, poichè barca è un prefisso di barcaccia, cioè i primi 5 caratteri di entrambe le parole coincidono, ma la seconda continua. casa è minore rispetto a casa, poichè i primi due caratteri coincidono in entrambe le parole mentre si ha che S è minore di s La funzione scanf: alcuni dettagli di funzionamento È utile approfondire ai fini di una maggiore comprensione il funzionamento della funzione scanf. int i; scanf("%d", &i); Come noto per permettere a scanf di scrivere nella variabile i, è necessario passare come parametro &i che rappresenta l indirizzo di memoria dove risiede la variabile i. Dal punto di vista di scanf, l unica cosa nota è che deve scrivere a partire dall indirizzo passato come secondo parametro. Il cosa e come dipendono dalla stringa di formato passata come primo argomento! Nell esempio, la stringa di formato (lo specificatore di formato contenuto %d) dice che si vuole salvare in memoria un numero intero. In una piattaforma per cui l intero ha dimensione 4byte, si ha che scanf scriverà 4byte a partire dall indirizzo specificato &i. char arr[4]; scanf("%d", &arr[0]); In questo esempio è possibile vedere come il tipo di spazio riservato (in questo caso è un array di char di lunghezza 4) irrilevante per scanf. Benchè funzionate, è un esempio da non seguire poichè confonde le idee ed inoltre potrebbe non funzionare su tutte le architetture (dimensioni del tipo intero diverse, vincoli di allineamento, ecc.). 3

char str[13]; scanf("%s", &str[0]); In questo esempio invece il comportamento atteso è in generale corretto, ipotizzando che la parola inserita dell utente sia al più di lunghezza 12 (ricordate il terminatore!): scanf dalla stringa di formato decodifica che deve scrivere una stringa, ovvero una sequenza di caratteri e dunque legittimamente parte dall indirizzo passato come parametro (l indirizzo della prima cella dell array) e scrive carattere per carattere gli elementi della parola letta nelle celle di memoria che seguono quella indicata. char str[13]; scanf("%12s", &str[0]); È possibile evitare il problema della lunghezza della parola utilizzando uno specificatore di formato più preciso: se ad esempio abbiamo allocato spazio per stringhe di lunghezza massima 12 (il terminatore è da riservare sempre a parte), allora con lo specificatore %12s si dà a scanf una ulteriore informazione, ovvero la lunghezza massima. In questo caso scanf nel caso di parole più lunghe della dimensione specificata effettuerà un troncamento, cioè scriverà solo un numero di caratteri pari al più al valore dichiarato nella stringa di formato. Attenzione: i caratteri in eccesso non sono scartati! Verranno utilizzati come dati inseriti dall utente per eventuali altre acquisizioni di dato. 4

Esercizio 1 Scrivere un programma che acquisisca dall utente 10 numeri reali, li salvi in una opportuna struttura dati e calcoli media e deviazione standard della sequenza di numeri. Schema risolutivo L esercizio è simile a quello presentato nella seconda esercitazione, in questo caso si ha il vantaggio di poter salvare i dati in un array e quindi non c è bisogno di tracciare quantità intermedie per rendere possibile il calcolo dei valori richiesti. La soluzione sarà quindi composta da tre parti: 1. acquisizione dei dati e salvataggio nell array 2. calcolo di media e varianza (accedendo ai dai salvati) 3. stampa a video dei risultati. Soluzione #include <stdio.h> #include <math.h> #define SIZE 10 int main() { float data[size]; printf("inserisci una sequenza di %d numeri reali: ", SIZE); int i; for (i = 0; i < SIZE; ++i) { scanf("%f", &data[i]); float mean = 0.0; for (i = 0; i < SIZE; ++i) mean += data[i] / SIZE; float var = 0.0; for (i = 0; i < SIZE; ++i) var += pow(data[i] - mean, 2) / SIZE; printf("media: %f\ndeviazione standard: %f\n", mean, sqrt(var)); return 0; 5

Commento La prima parte del programma si occupa di acquisire i dati e salvarli in un array: float data[size]; printf("inserisci una sequenza di %d numeri reali: ", SIZE); int i; for (i = 0; i < SIZE; ++i) { scanf("%f", &data[i]); Alla funzione scanf si passa l indirizzo dell elemento i-esimo dell array &data[i]. Segue poi la parte di calcolo, prima viene calcolata la media (risultato salvato nella variabile mean) e successivamente la varianza (nella variabile var) poichè questa dipende dal valore della media. float mean = 0.0; for (i = 0; i < SIZE; ++i) mean += data[i] / SIZE; float var = 0.0; for (i = 0; i < SIZE; ++i) var += pow(data[i] - mean, 2) / SIZE; Si utilizza la funzione pow per effettuare l elevamento al quadrato, il risultato è equivalente a (data[i] - mean) * (data[i] - mean). 6

Esercizio 2 Scrivere un programma che acquisisca dall utente una stringa di lunghezza massima 10 e dica se è palindroma. Schema risolutivo Si utilizza la funzione gets (anche se pericolosa poichè non vengono effettuati controlli sull effettivo spazio allocato per memorizzare l input) per acquisire la stringa in ingresso da parte dell utente. A questo punto si calcola la lunghezzza della stringa con strlen e si itera sulla prima metà dei caratteri che compongono la stringa. per ogni carattere si verifica che il suo simmetrico rispetto al centro della stringa sia uguale. Se si termina tutti i caratteri della prima metà hanno il corrispondente simmetrico uguale allora la parola è palindroma. Soluzione #include <stdio.h> #include <string.h> #define SIZE 10 int main() { char buffer[size + 1]; printf("inserisci una stringa di lunghezza massima %d: ", SIZE); gets(buffer); int l = strlen(buffer); int i; for (i = 0; i < l/2; ++i) if (buffer[i]!= buffer[l - 1 - i]) break; if (i == l/2) printf("stringa palindroma!\n"); else printf("stringa non palindroma!\n"); return 0; 7

Esercizio 3 Scrivere un programma che date due stringhe realizzi il confronto lessicografico e stampi a video il risultato (-1 minore, 0 uguale, 1 maggiore). Schema risolutivo L esercizio ha come obiettivo l implementazione dell algoritmo alla base della funzione strcmp (non si vuole usare la funzione, bensì implementare il corpo della funzione stessa). Dunque bisogna implementare un algoritmo che effettui il confronto basato sull ordinamento lessicografico! Soluzione #include <stdio.h> int main() { char str1[] = "hello World!"; char str2[] = "hello Word!"; int res, i; for (i = 0; str1[i]!= \0 && str2[i]!= \0 ; ++i) { if (str1[i]!= str2[i]) break; if (str1[i] < str2[i]) res = -1; else if (str1[i] > str2[i]) res = 1; else res = 0; printf("risultato: %d\n", res); return 0; Commento La parte da analizzare bene è quella legata al ciclo for (i = 0; str1[i]!= \0 && str2[i]!= \0 ; ++i) { if (str1[i]!= str2[i]) break; Si può uscire dal ciclo se il carattere i-esimo di str1 o di str2 è uguale al terminatore, oppure se sono diversi tra loro (il break). In altre parole si itera il corpo del ciclo fino a che i caratteri i-esimi di entrambe le stringhe sono uguali tra loro ma diversi dal terminatore: in questo modo si scorre il prefisso comune tra le due stringhe (che può essere la stringa vuota). Al di fuori del ciclo si il carattere i-esimo di entrambe le stringhe (dove i è il valore del contatore fuori dal ciclo for) e sono possibili tre casi: una delle due stringhe è più corta dell altra dunque in una delle due si è raggiunto il terminatore, dunque si confronta (< o >) un carattere con il terminatore e si deduce la risposta corretta poichè il terminatore ha il valore numerico 0; 8

entrambe le stringhe hanno la stessa lunghezza e si è raggiunto (in entrambe) il terminatore, dunque si ha che 0 = 0 e quindi sono la stessa stringa; è stato trovato un carattere diverso tra le due stringhe, i è sicuramente minore della minimo tra le lunghezze delle due stringhe, e sfruttando il confronto tra i valori numerici dei caratteri si determina se la prima stringa sia minore o maggiore rispetto alla seconda. 9

Esercizio 4 Scrivere un programma che acquisisca dall utente 5 parole di lunghezza massima 12, le salvi in una opportuna struttura dati e restituisca il numero di occorrenze di ogni vocale. Schema risolutivo L idea risolutiva è quella di memorizzare le stringhe in una matrice di dimensione 5x13 (si ricordi il terminatore di stringa): le parole verranno memorizzate nelle righe della matrice. Successivamente si scorre la matrice con due cicli innestati e si ricercano i caratteri che corrispondo alle vocali: una possibile soluzione è quella di utilizzare un array per rappresentare i contatori di occorrenze di ogni vocale. Soluzione #include <stdio.h> #define N 5 #define L 12 int main() { char data[n][l + 1]; printf("inserire %d parole di lunghezza massima %d: ", N, L); int i, j; for (i = 0; i < N; ++i) { // si passa l indirizzo della prima cella di ogni riga scanf("%s", &data[i][0]); // definisco il vettore di contatori inizializzati a zero int cnt[5] = { 0, 0, 0, 0, 0; for (i = 0; i < 5; ++i) { // è sufficiente arrivare fino al terminatore della stringa corrente! for (j = 0; data[i][j]!= \0 ; ++j) { switch (data[i][j]) { case A : case a : cnt[0] += 1; break; case E : case e : cnt[1] += 1; break; case I : case i : cnt[2] += 1; break; case O : case o : cnt[3] += 1; break; 10

case U : case u : cnt[4] += 1; break; printf("a: %d\ne: %d\ni: %d\no: %d\nu: %d\n", cnt[0], cnt[1], cnt[2], cnt[3], cnt[4]); return 0; 11