Esercizio 1 (14 punti)

Documenti analoghi
Esercizio 1 (6 punti)

Esercizio 1 (14 punti)

Esercizio 1 (14 punti)

Esercizio 1 (15 punti)

Esercizio 1 (15 punti)

Esercizio 1 (17 punti)

Relativamente agli esempi sopra riportati, al termine dell esecuzione della funzione il file di uscita dovrà contenere quanto riportato a lato.

Fondamenti di Informatica 2

Lab 12 Allocazione dinamica della memoria

Fondamenti di Informatica 1 - Compito A

Fondamenti di Informatica e Laboratorio T-AB Prova Pratica - 16 Giugno 2009 Compito A

Lezione 11: Liste a Puntatori e Input/Output

Fondamenti di Informatica L-A

Operazioni su file di caratteri

giapresente( ) leggi( ) char * strstr(char * cs, char * ct) NULL

Fondamenti di Informatica 2

int ninv; /* numero di inventario */

Politecnico di Milano - Dipartimento di Elettronica e informazione Prof. Mauro Negri

Lab 17 Allocazione dinamica della memoria

Gestione dei file. File di testo e binari

PROGRAMMAZIONE II canale A-D luglio 2008 TRACCIA DI SOLUZIONE

Lezione XII.III Gestione dei file Un progetto completo

Lab 09 Gestione file di testo

Esercitazioni di Fondamenti di Informatica - Lez. 5 30/10/2018

Esercizi su strutture dati

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

Es. 1. interi, li stampi a video ponendo prima i numeri pari e poi i numeri dispari. Es. 1. int readlength(file *f, int *even, int *odd)

Lab 16 Gestione file binari"

Fondamenti di Informatica 2

Laboratorio di Informatica. Lezione 8: Liste e alberi

Allocazione dinamica memoria

Laboratorio di Algoritmi e Strutture Dati Ingegneria e Scienze Informatiche - Cesena A.A

Informatica 1. Prova di recupero 21 Settembre 2001

Titolo presentazione INFORMATICA. sottotitolo A.A Milano, XX mese 20XX Laboratorio n 6 Ing. Gian Enrico Conti Dott.

Fondamenti di Informatica: Ingegneria Meccanica Prova scritta del 12 luglio 2008

Il linguaggio C Strutture

Esercizio 1 Domanda di teoria (13 punti)

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

Scrittura formattata - printf

Esercizio 1 Conta degli elementi distinti (file esercizio1.c e leggi.h/leggi.c - 15 punti)

Allocazione dinamica della memoria

/* Esempio di contenuto del file di testo: */ PaoloBellavista marzo.dat PaolaMello aprile.dat FedericoChesani marzo.dat CarloGiannelli marzo.

FONDAMENTI DI INFORMATICA. Prof. PIER LUCA MONTESSORO Ing. DAVIDE PIERATTONI. Facoltà di Ingegneria Università degli Studi di Udine

Esercizio 1. Esercizio 1 - Soluzione

Lab 11 Allocazione dinamica della memoria

Politecnico di Milano Facoltà di Ingegneria Civile, Ambientale e Territoriale. Informatica B [079904]

Puntatori. Un puntatore contiene un numero che indica la locazione di memoria dove è presente la variabile puntata

Esercizi di programmazione in linguaggio C English Dictionary

Lezione 22: Input/Output e Files

Sistemi Operativi (M. Cesati)

Opinione calcolamedia( ) Opinione inverti( )

Esercitazioni di Informatica (CIV)

Precedenza e associatività. Complementi sul C - 2. Esempi. Esempi

Scritto di Algoritmi e s.d. (1o anno) 5 Luglio 2005

- matrici - stringhe - file (lettura/scrittura, di testo/binari) - strutture, puntatori - allocazione dinamica della memoria (malloc)

Ogni parte non cancellata a penna sarà considerata parte integrante della soluzione.

Fondamenti di informatica, Sez. Ing. Informatica, Ing. Gestionale, Ing. Ambientale II prova in itinere, 29 Gennaio 2009

Esercitazioni di Fondamenti di Informatica - Lez. 8 27/11/2018

Il presente plico contiene 4 esercizi e deve essere debitamente compilato con cognome e nome, numero di matricola.

L'Allocazione Dinamica della Memoria nel linguaggio C

Esercizio 1: media di numeri reali (uso funzioni e struct)

Il presente plico contiene 4 esercizi e deve essere debitamente compilato con cognome e nome, numero di matricola.

Fondamenti di Informatica e Laboratorio T-AB Prova Pratica - 12 Dicembre 2008 Compito A

Gestione dei File. Credits Prof. Campi

C: panoramica. Violetta Lonati

Fondamenti di Informatica T-1, 2010/2011 Modulo 2. Prova d Esame 5A di Mercoledì 13 Luglio 2011 tempo a disposizione 2h

ELEMENTI DI INFORMATICA LB ESERCITAZIONE (del 09/03/2007) Files, Strutture e Liste

Corso di Fondamenti di Informatica. Puntatori e Allocazione Dinamica

Fondamenti di Informatica 1 - Compito A

Esercitazione 11. Liste semplici

Politecnico di Milano Facoltà di Ingegneria Industriale INFORMATICA B Prova in itinere del 26 Novembre 2014 COGNOME E NOME RIGA COLONNA MATRICOLA

Politecnico di Torino

Ogni parte non cancellata a penna sarà considerata parte integrante della soluzione.

Fondamenti di Informatica T-1 Modulo 2

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

Fondamenti di Informatica 2

#include <stdio.h> #include <stdlib.h> #define L 20 void Proc(char [], int); int N=L; main () { char *s; int i;

Politecnico di Milano Facoltà di Ingegneria Industriale INFORMATICA B Prova in itinere del 26 Novembre 2014 COGNOME E NOME RIGA COLONNA MATRICOLA

Politecnico di Milano Facoltà di Ingegneria Industriale INFORMATICA B Appello del 21 Luglio 2010 COGNOME E NOME RIGA COLONNA MATRICOLA

Fondamenti di Informatica T1 Prova Pratica - Luglio 2013 Compito

Programmazione di base

Esercizi. Stringhe. Stringhe Ricerca binaria

1 (4) 2 (4) 3 (12) 4 (6) 5 (6)

Sistemi Operativi (M. Cesati)

Strutture dati dinamiche in C (II)

Complementi. - Ridefinizione di tipo - - Costrutto switch - - Programmazione su più file - - Parametri della funzione main - Funzione system -

Fondamenti di Informatica II

Prova Scritta del 20/09/10

Complementi. - Ridefinizione di tipo - - Costrutto switch - - Programmazione su più file - - Parametri della funzione main - Funzione system -

Programmazione I - Laboratorio

Esercizi. La funzione swapint() primo tentativo

Esercizio. 2 i=i*2) j=j*2)

Prova Scritta del 20/09/10

FUNZIONI che operano su LISTE e TEMI d ESAME

Esercizi. Filtraggio

Transcript:

Prova scritta del 22 gennaio 2018 di Fondamenti di Informatica I (prof. Montessoro) + Fondamenti di Informatica II (prof. Di Gaspero) Per studenti di Ing. Gestionale immatricolati negli anni accademici 2016-17 e precedenti DURATA DELLA PROVA: 3 ORE A pena di annullamento immediato della prova: 1) Non è possibile consultare libri o appunti (in qualunque forma) né utilizzare calcolatrici, telefoni cellulari, ecc. 2) Non è consentito comunicare (con qualunque mezzo) 3) Non è consentito uscire dall aula Lo studente è tenuto a scrivere, correggere, compilare ed eseguire su computer (a casa o in laboratorio) gli esercizi di programmazione prima della prova orale. Alla prova orale lo studente deve portare una memory pen USB contenente i sorgenti dei programmi corretti e le stampe dei relativi file. Esercizio 1 (14 punti) Una rete di distributori automatici comunica periodicamente alla sede del gestore, tramite un collegamento internet, il numero di esemplari ancora disponibili di ciascun prodotto onde pianificare il necessario approvvigionamento. I dati vengono tutti raccolti in un file di testo il cui formato può essere dedotto dal seguente esempio: RIZZI_02 4: KITKAT 3, OREO 7, OROSAIWA 9, CHIPSCHILI 12. MANTICA_01 3: OROSAIWA 19, CHIPSTER 0, OREO 5. KOLBE_01 5: CHIPSCHILI 10, OROSAIWA 9, OREO 0, CHIPSTER 1, KITKAT 4. Si osservi che: i nomi in codice dei distributori e i nomi dei prodotti sono sempre scritti con una sola parola; il codice del distributore è seguito dal numero dei prodotti in vendita in quel distributore e poi dal carattere due punti; ogni nome di prodotto è seguito dal numero di esemplari ancora disponibili e poi dal carattere virgola o punto. Un secondo file contiene l elenco dei prodotti venduti dal gestore e, per ciascuno, il numero di esemplari di cui ogni distributore che abbia in vendita tale prodotto deve essere rifornito (cioè il numero totale di esemplari che devono trovarsi nel distributore quando è appena stato riempito). Un esempio di tale file è riportato nel riquadro a lato. Scopo dell esercizio è calcolare per ogni prodotto il numero di esemplari che devono essere caricati sul furgone che, facendo il giro di tutti i distributori elencati nel primo file, li rifornisce in base ai dati presenti nel secondo file. Per esempio, facendo riferimento agli esempi sopra riportati, il furgone dovrà caricare 33 esemplari di KITKAT: 17 per il distributore RIZZI_02 e 16 per il distributore KOLBE_01. Non è noto il massimo numero di distributori. Il massimo numero di prodotti, invece, è 500. Si assuma che tutti i prodotti dei distributori siano presenti nell elenco del secondo file. Si scriva un programma in linguaggio C che riceva sulla riga di comando i nomi di due file come sopra descritto (il primo il file che riporta lo stato attuale dei distributori, il secondo il numero di esemplari richiesto) e stampi sul monitor l elenco dei prodotti (in un ordine qualsiasi) con il numero totale di esemplari da caricare sul furgone e, per ciascuno, il numero presente nel secondo file come istruzione per l addetto al rifornimento. Relativamente agli esempi sopra riportati, il programma dovrà stampare: KITKAT 33 (riempire il distributore fino a 20) OREO 33 (riempire il distributore fino a 15) OROSAIWA 38 (riempire il distributore fino a 25) CHIPSCHILI 8 (riempire il distributore fino a 15) CHIPSTER 63 (riempire il distributore fino a 32) KITKAT 20 OREO 15 OROSAIWA 25 CHIPSCHILI 15 CHIPSTER 32

#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXPRODOTTI 500 struct prodotto char nome[32]; int q_distr_pieno; int q_carico_per_distribuzione; ; int leggi_prodotti (FILE *fp, struct prodotto prodotti[], int nmax); void calcola_carico_per_distribuzione (FILE *fpdistributori, struct prodotto prodotti[], int n_prodotti); int cerca_prodotto (struct prodotto prodotti[], int n_prodotti, char nome[]); void stampa_carico_per_distribuzione (struct prodotto prodotti[], int n_prodotti); int main (int argc, char *argv[]) FILE *fpdistributori, *fpprodotti; struct prodotto prodotti[maxprodotti]; int n_prodotti; if (argc!= 3) printf ("argomenti: <file distributori> <file prodotti>\n"); /* apri i file */ if ((fpdistributori = fopen (argv[1], "r")) == NULL) printf ("errore di apertura del file %s\n", argv[1]); if ((fpprodotti = fopen (argv[2], "r")) == NULL) printf ("errore di apertura del file %s\n", argv[2]); /* leggi il file prodotti */ n_prodotti = leggi_prodotti (fpprodotti, prodotti, MAXPRODOTTI); /* calcola il carico per la distribuzione */ calcola_carico_per_distribuzione (fpdistributori, prodotti, n_prodotti); /* stampa il carico per la distribuzione */ stampa_carico_per_distribuzione (prodotti, n_prodotti); fclose (fpprodotti); fclose (fpdistributori); return EXIT_SUCCESS; int leggi_prodotti (FILE *fpprodotti, struct prodotto prodotti[], int nmax) i = 0; while (i < MAXPRODOTTI && (fscanf (fpprodotti, "%s %d", prodotti[i].nome, &prodotti[i].q_distr_pieno)!= EOF)) prodotti[i].q_carico_per_distribuzione = 0; i++;

void calcola_carico_per_distribuzione (FILE *fpdistributori, struct prodotto prodotti[], int n_prodotti) int indice, i, num_prod, q; char nome_prodotto[32]; while (fscanf (fpdistributori, "%*s %d%*c", &num_prod)!= EOF) for (i = 0; i < num_prod; i++) fscanf (fpdistributori, "%s %d%*c", nome_prodotto, &q); indice = cerca_prodotto (prodotti, n_prodotti, nome_prodotto); if (indice == -1) printf ("prodotto %s non presente in elenco\n", nome_prodotto); prodotti[indice].q_carico_per_distribuzione += prodotti[indice].q_distr_pieno - q; return; int cerca_prodotto (struct prodotto prodotti[], int n_prodotti, char nome[]) i = 0; while (i < n_prodotti) if (strcmp (nome, prodotti[i].nome) == 0) i++; return -1; void stampa_carico_per_distribuzione (struct prodotto prodotti[], int n_prodotti) for (i = 0; i < n_prodotti; i++) printf ("%s %d (riempire il distributore fino a %d)\n", prodotti[i].nome, prodotti[i].q_carico_per_distribuzione, prodotti[i].q_distr_pieno); return;

Esercizio 2 (8 punti) Si consideri un nuovo tipo di dato astratto lista_multipla che consiste di un vettore (creato dinamicamente, ma di dimensione fissa) di liste di valori di tipo int. Il peso di ciascuna delle liste che costituiscono una lista multipla è dato dalla somma dei suoi valori. Si veda l esempio a fianco di una lista multipla che consiste di 4 liste e in cui il peso della prima lista è 4, quello della seconda 4, della terza 0 e della quarta 6. Le operazioni possibili sulle liste multiple sono le seguenti: lista_multipla crea_lista_multipla(int m): crea un vettore di m liste inizialmente vuote e imposta eventuali altre informazioni nel descrittore; inserisci_lista_multipla(lista_multipla *lm, int d): inserisce il dato d nella lista, facente parte della lista multipla lm, avente peso minore; rimuovi_lista_multipla(lista_multipla *lm, int d): rimuove tutte le occorrenze del dato d dalle liste facenti parte della lista multipla lm; elimina_lista_multipla(lista_multipla *lm): elimina la lista multipla deallocando tutti i dati allocati dinamicamente. 1. Si definisca un possibile descrittore per il tipo di dato lista multipla (in altre parole la struct _lista_multipla). 2. Si implementino in linguaggio C le operazioni di manipolazione delle liste multiple descritte in precedenza. Qualora fosse necessario si assuma l esistenza di funzioni di manipolazione delle liste adattate allo specifico tipo di informazione memorizzata nelle singole liste (ad es. aggiungi_in_testa(lista* l, int dato), nodo_lista* trova_dato(nodo_lista *t, int dato)). In tal caso, si scrivano le dichiarazioni delle funzioni utilizzate. 3. Si discuta, informalmente, la complessità temporale dell implementazione delle operazioni di manipolazione espressa in funzione di n, numero totale di elementi memorizzati in tutte le liste, e di m, numero totale di liste. #include <stdlib.h> typedef struct _nodo_lista int dato; struct _nodo_lista* succ; nodo_lista; typedef struct // una possibilità è mantenere due array, uno con il peso e l'altro con i puntatori ai nodi, oppure si potrebbe racchiudere tutto in un singolo record nodo_lista** liste; int* peso; int m; lista_multipla; // complessità O(m): dovuto al ciclo for lista_multipla crea_lista_multipla(int m) lista_multipla lm; lm.liste = (nodo_lista**)malloc(m * sizeof(nodo_lista)); lm.peso = (int*)malloc(m * sizeof(int)); assert(lm.liste!= NULL && lm.peso!= NULL); for (i = 0; i < m; i++) lm.liste[i] = NULL; lm.peso[i] = 0; lm.m = m; return lm;

// complessità O(m + n): ciclo for seguito poi dalla scansione della lista di peso minore (che però, nel caso peggiore potrebbe avere lunghezza n) void inserisci_lista_multipla(lista_multipla* lm, int d) int i, i_min = 0; nodo_lista* n; for (i = 1; i < lm->m; i++) if (lm->peso[i] < lm->peso[i_min]) i_min = i; n = (nodo_lista*)malloc(sizeof(nodo_lista)); assert(n!= NULL); n->dato = d; n->succ = lm->liste[i_min]; lm->liste[i_min] = n; lm->peso[i] += d; // complessità O(m + n): ciclo for al cui interno vi è la deallocazione degli elementi della lista con valore d (complessivamente n) void rimuovi_lista_multipla(lista_multipla* lm, int d) nodo_lista *c, *p, *n; for (i = 0; i < lm->m; i++) p = NULL; c = lm->liste[i]; while (c!= NULL) n = c->succ; if (c->dato == d) if (p == NULL) else c = n; lm->liste[i] = c->succ; p->succ = c->succ; free(c); lm->peso[i] -= d;

// complessità O(m + n): analogamente al precedente, ciclo for al cui interno vi è la deallocazione di tutti gli elementi della lista (complessivamente n) void elimina_lista_multipla(lista_multipla* lm) nodo_lista *c, *p; for (i = 0; i < lm->m; i++) c = lm->liste[i]; while (c!= NULL) p = c->succ; free(c); c = p; free(lm->liste); free(lm->peso); Esercizio 2 (8 punti) Analogamente alla rappresentazione implicita di uno heap tree, è possibile rappresentare anche un albero binario di ricerca (ABR) attraverso un opportuno array. La differenza principale è costituita dal fatto che nel caso un ABR non è necessariamente completo a sinistra, per cui alcune delle celle dell array potrebbero riferirsi a dei nodi non presenti nell albero (si veda l esempio nella figura seguente). 1. Si proponga un possibile descrittore albero_binario_in_array per memorizzare le informazioni necessarie a questo tipo di rappresentazione. 2. Si simuli l operazione di inserimento dei valori chiave = 32, dato = 0.5 nell albero e nella sua rappresentazione in array (suggerimento: che operazione è necessaria sull array nel caso di introduzione di un nuovo livello?); 3. Si discuta, informalmente, la complessità spaziale necessaria per la memorizzazione di un ABR costituito da k livelli utilizzando questa rappresentazione. 4. Si implementi in pseudocodice o in linguaggio C la funzione inserisci_albero_binario_in_array(albero_binario_in_array* a, int chiave, float dato). Qualora fosse necessario si assuma l esistenza di funzioni di manipolazione delle strutture dati utilizzate adattate allo specifico tipo di informazione memorizzata. In tal caso, si scrivano le dichiarazioni delle funzioni utilizzate.

#include <stdbool.h> #include <math.h> #include <assert.h> #include <stdlib.h> typedef struct int chiave; float dato; bool presente; nodo_albero_binario_in_array; typedef struct int k; int d; nodo_albero_binario_in_array* nodi; albero_binario_in_array; // per memorizzare un ABR costituito da k livelli sono necessari 2^k - 1 locazioni int _figlio_sx(int i) return 2 * i + 1; int _figlio_dx(int i) return 2 * i + 2; // complessità O(k), con k il numero di livelli dell'albero (sfortunatamente potrebbe essere O(n)) int dove_inserire(nodo_albero_binario_in_array* nodi, int i, int d, int chiave) // il primo caso base avviene se i è dentro le dimensioni dell'array e il dato // in posizione i non è ancora presente if (i < d &&!nodi[i].presente) // il secondo caso base avviene se i è fuori dall'array, in tal caso, ovviamente, // l'elemento a[i] non è presente e può essere inserito nella posizione i previa // estensione dell'array if (i >= d) // i casi ricorsivi, invece, si hanno quando l'elemento in posizione a[i] è già presente if (chiave < nodi[i].dato) return dove_inserire(nodi, _figlio_sx(i), d, chiave); else return dove_inserire(nodi, _figlio_dx(i), d, chiave); // complessità O(k + 2^k - 1), con k il numero di livelli dell'albero void inserisci_albero_binario_in_array(albero_binario_in_array* a, int chiave, float dato) int i = dove_inserire(a->nodi, 0, a->d, chiave), j; if (i >= a->d) // se la locazione in cui inserire è più grande di n, allora bisognerà estendere // l'albero di un livello a->d = pow(2, a->k + 1) - 1; a->k = a->k + 1; a->nodi = (nodo_albero_binario_in_array*)realloc(a->nodi, a->d * sizeof(nodo_albero_binario_in_array)); assert(a->nodi); for (j = a->d / 2; j < a->d; j++) // il numero di iterazioni è pari a 2^k - 1 a->nodi[j].presente = false; assert(!a->nodi[i].presente); // per verificare che la locazione sia effettivamente libera a->nodi[i].chiave = chiave; a->nodi[i].dato = dato;