INFORMATICA Esercizi
Esempio: giorni nell’anno Realizzare un programma che legga da tastiera l’anno di riferimento e la sigla del primo giorno di quell’anno (1 gennaio) composta dai primi tre caratteri del nome (ad esempio: 2003 mer) e visualizzi sul video una tabella in cui sono indicati, per ogni mese dell’anno, quante volte occorre ciacun giorno della settimana. Si rammenta che sono bisestili gli anni divisibili per 4 ma, tra quelli multipli di 100, solo quelli che sono divisibili per 400.
Esempio: giorni nell’anno Esempio di tabella in uscita: 2003 gen feb mar apr mag giu lug ago set ott nov dic lun 4 4 mar 4 4 mer 5 ecc. gio 5 ven 5 sab 4 dom 4
Esempio: giorni nell’anno Analisi Il modo più semplice per risolvere il problema è forse quello di utilizzare lo stesso algoritmo che per primo viene in mente, ovvero di contare le occorrenze giorno per giorno a partire dal 1 gennaio e fino al 31 dicembre tenedo conto dei mesi e della loro durata (con controllo se si tratta di anno bisestile). Identificheremo i vari giorni della settimana con un indice (0 per lunedì, 1 per martedì, ecc.) per cui dovremo convertire la stringa di tre caratteri di input nell’indice corrispondente (di lì comincia l’anno). La base dati sarà una matrice di interi (giorni della settimana x mesi) che riempiremo con due cicli for annidati: quello esterno controlla i mesi, quello interno la durata del mese. La durata della settimana (da 0 a 6) la controlliamo noi con un contatore da 0 a 6. Deve pertanto essere resettato a 0 ogni volta che raggiunge 7!
Esempio: giorni nell’anno #include <stdio.h> main() { int anno, data, day, mese; char giorno[4]; /* 3 caratteri + fine stringa */ /* vettore contenente la durata (numero giorni) di ogni mese */ int dur_mese[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int occ[7][12]; /* matrice risultato: giorni della settimana x mesi */ /* Input dei dati da tastiera */ printf ("\n Anno: "); scanf ("%d", &anno); printf ("\n Che giorno è il primo gennaio?: "); scanf ("%s", giorno);
Esempio: giorni nell’anno /* Controlla se è un anno bisestile */ if ((anno % 4) == 0) /* divisibile per 4? */ { if ((anno % 100) == 0) /* si, divisibile per 100? */ if ((anno % 400) == 0) /* si, divisibile per 400? */ dur_mese[1] = 29; /* si, bisestile */ } else dur_mese[1] = 29; /* divisibile per 4 e non per 100, bisestile! */
Esempio: giorni nell’anno /* Converte la sigla del primo giorno dell'anno in un indice (da 0 a 6) */ switch (giorno[0]) { case 'l': {day = 0; break;} /* lunedì */ case 'm': if (giorno[1] == 'a') {day = 1; break;} /* martedì */ else {day = 2; break;} /* mercoledì */ case 'g': {day = 3; break;} /* giovedì */ case 'v': {day = 4; break;} /* venerdì */ case 's': {day = 5; break;} /* sabato */ case 'd': day = 6; /* domenica */ }
Esempio: giorni nell’anno /* Inizializza la matrice risultato con tutti zeri */ for (mese = 0; mese < 12; mese++) for (data = 0; data < 7; data++) occ[data][mese] = 0; /* algoritmo di calcolo delle occorrenze */ for (data = 1; data <= dur_mese[mese]; data++) { occ[day][mese]++; day++; if (day == 7) day = 0; /* fine settimana, ricomincia dall’inizio */ }
Esempio: giorni nell’anno printf (" %d\n", anno); /* Stampa risultato */ printf (" gen feb mar apr mag giu lug ago set ott nov dic\n"); for (day = 0; day < 7; day++) { switch (day) { case(0): {printf ("lun "); break;} case(1): {printf ("mar "); break;} case(2): {printf ("mer "); break;} case(3): {printf ("gio "); break;} case(4): {printf ("ven "); break;} case(5): {printf ("sab "); break;} case(6): printf ("dom "); } /* fine switch */ for (mese = 0; mese < 12; mese++) printf (" %d ", occ[day][mese]); printf ("\n"); } /* fine for (day = 0; ... */ }
Esempio: codice 2 su 5 Generare tutti i codici 2 su 5 (5 bit, di cui due bit devono essere a 1 e tre bit a zero), li si memorizzi in un'opportuna base dati e li si visualizzi sul videoterminale. (Si rammenti che i codici binari possono essere visti come numeri interi (senza segno), per cui è sufficiente generare tutti i codici di 5 bit e poi scartare quelli che non soddisfano la condizione di avere 2 bit ad uno e 3 a zero.) Successivamente confrontare i codici a due a due e, per ciascuna coppia, confrontare i bit a parità di posizione, conteggiando il numero di bit diversi tra di loro (il numero di bit diversi viene detto distanza tra i codici). Il programma calcoli e stampi il massimo e il minimo della distanza tra i codici.
Esempio: codice 2 su 5 #include <stdio.h> void main() { void main() { int codOK, num, i, j, k, bitauno; int massimo, minimo, dist; int matrice[32][5]; /* calcola tutti i codici 2 su 5 e li salva in */ /* matrice scartando le combinazioni illegali */
Esempio: codice 2 su 5 codOK = 0; for (i=0; i<32; i++) { bitauno = 0; num = i; for (j=1; j<=5; j++) matrice[codOK][j] = num % 2; if (matrice[codOK][j] == 1) bitauno++; num /= 2; }
Esempio: codice 2 su 5 if (bitauno == 2) { for (j=1; j<=5; j++) printf ("%d", matrice[codOK][j]); printf ("\n"); codOK++; } /* Cerca la distanza massima e minima */
Esempio: codice 2 su 5 massimo = 0; minimo = 5; for (i = 0; i <= codOK-1; i++) { for (k=i+1; k<=codOK; k++) dist = 0; for (j=1; j<=5; j++) if (matrice[i][j] != matrice[k][j]) dist++; if (dist > massimo) massimo = dist; if (dist < minimo) minimo = dist; } printf ("massimo = %d minimo = %d \n", massimo, minimo);
Esempio: punti nel piano In un file, il cui nome va richiesto da tastiera, ci sono le coordinate X e Y di una serie di punti appartenenti a un piano cartesiano. Non si conosce a priori il numero di punti: si supponga siano meno di 100. Leggere il file, calcolare la distanza dall'origine di ogni singolo punto, quindi riordinare i punti rispetto alla distanza dall'origine (dal più vicino al più lontano). Infine visualizzarli su monitor e salvarli (un punto per riga) in un file il cui nome va anch’esso richiesto da tastiera.
Esempio: punti nel piano Ad esempio se il file dei punti si chiama PUNTI.DAT e contiene: 2 2 1 4 3 3 0 1 sul monitor dovrà apparire: Punto 1: 0.0000, 1.0000 -> 1.0000 Punto 2: 2.0000, 2.0000 -> 2.8284 Punto 3: 1.0000, 4.0000 -> 4.1231 Punto 4: 3.0000, 3.0000 -> 4.2426
Esempio: punti nel piano #include <stdio.h> #include <math.h> #define NMAX 100 typedef enum {FALSO, VERO} boolean; struct modello { double x; double y; double dist; }; /* prototipo della funzione di riordinamento */ void bubble (struct modello punti[ ], int n)
Esempio: punti nel piano main() { FILE *input, *output; int i, j, np; char nomefile[20]; struct modello punti[NMAX]; /* Legge il nome del file */ printf (“\nNome del file che contiene i punti: "); scanf ("%s", nomefile); /* Apre il file in lettura */ if ((input = fopen (nomefile,"r")) == NULL) printf ("\nErrore apertura file %s", nomefile); exit (0); }
Esempio: punti nel piano np = 0; while (!feof (input)) { fscanf (input, "%lf%lf", &punti[np].x, &punti[np].y) punti[np].dist = sqrt (punti[np].x * punti[np].x + punti[np].y * punti[np].y); np++; } fclose (input); bubble (punti, np);
Esempio: punti nel piano /* Operazioni finali: chiede il nome del file di output e lo crea */ printf (“\nNome del file di output: "); scanf ("%s", nomefile); if ((output = fopen (nomefile, “w")) == NULL) { printf ("\nErrore creazione file %s", nomefile); exit (1); } /* visualizza la sequenza di punti sul monitor e la salva nel file */ for (i = 0; i < np; i++) printf (“\nPunto %3d: %9.4lf,%9.4lf %10.4lf", i+1, punti[i].x, punti[i].y, punti[i].dist); fprintf (output, “\nPunto %3d: %9.4lf,%9.4lf %10.4lf", } fclose(output); }
Esempio: punti nel piano void bubble (struct modello punti[ ], int n) { struct modello provv; int ind; boolean ord; ord = FALSO; while (!ord) { ord = VERO; for (ind = 0; ind < n-1; ind++) if (punti[ind].dist > punti[ind+1].dist) provv = punti[ind]; punti[ind] = punti[ind+1]; punti[ind+1] = provv; ord = FALSO; } }
Prenotazione di un teatro In un file POSTI.DAT è contenuta la disposizione dei posti a sedere di un teatro, rappresentata come una matrice. Il numero di posti a sedere nel teatro è di 50 file da 30 posti ciascuna. Inizialmente, tutti i posti del teatro sono liberi. Questo è rappresentato nel file da un valore 0 in corrispondenza di ogni posto. In un secondo file PRENOT.DAT è contenuta la sequenza delle richieste di prenotazione dei posti da parte dei clienti. Il numero di tali richieste NON è noto a priori. Le richieste nel file sono specificate secondo il seguente formato: numero_fila numero_posto Le file ed i posti sono numerati a partire da 1.
Prenotazione di un teatro Scrivere un programma C che, dopo aver letto il primo file, processi le richieste di prenotazione e scriva su schermo la situazione finale dei posti a sedere, nello stesso formato del primo file (si rappresenti con 1 il posto occupato). Nel processare le richieste, si deve tenere conto del fatto che alcune richieste possono essere duplicate, perché alcuni posti potrebbero essere richiesti più frequentemente. Il programma dovrà inolte fornire su schermo il numero di posti rimasti liberi e il numero di prenotazioni non andate a buon fine.
Prenotazione di un teatro Esempio: (matrice 5x5 per semplicità): POSTI.DAT PRENOT.DAT Output 0 0 0 0 0 1 2 0 1 1 1 0 0 0 0 0 0 1 3 0 1 1 0 1 0 0 0 0 0 1 4 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 2 3 0 0 0 0 0 2 5 2 2 Numero prenotazioni fallite: 1
Prenotazione di un teatro #include <stdio.h> #include <stdlib.h> #define POSTI "POSTI.DAT" #define PRENOT "PRENOT.DAT" #define NFILE 50 #define NCOL 30 main() { int teatro[NFILE][NCOL]; FILE *in, *out; int fi, co, i, j, liberi=0, nook=0;
Prenotazione di un teatro /* Apre il file contenente il teatro */ if ((in = fopen (POSTI, "r")) == NULL) { printf ("\nErrore apertura %s ", POSTI); exit (1); } /* Legge il file contenente il teatro (1=occupato, 0=libero) */ for (i = 0; i < NFILE; i++) for (j = 0; j < NCOL; j++) if (fscanf (in, "%d", &teatro[i][j]) != 1) printf ("\nErrore lettura fila %d, posto %d\n", i+1, j+1); exit (2); fclose (in);
Prenotazione di un teatro /* Apre il file delle prenotazioni */ if ((in = fopen (PRENOT, "r")) == NULL) { printf ("\nErrore apertura %s ", PRENOT); exit (3); } /* Legge le prenotazioni: a ogni lettura controlla se il posto è libero o no. Se libero lo occupa se già occupato lo segnala sul monitor */ i = 0; while (!feof (in)) if (fscanf (in, "%d %d", &fi, &co) != 2) printf ("\nErrore lettura prenotazione numero %d\n", i+1); exit (4);
Prenotazione di un teatro i++; /* conta le righe per l’eventuale output d’errore */ if (teatro [fi-1][co-1] == 0) /* posto libero? */ teatro [fi-1][co-1] = 1; /* si, lo occupa */ else { printf ("Posto num. %d della fila %d già prenotato\n", co, fi); nook++; } } /* fine di while (!feof(in))……..*/ fclose (in);
Prenotazione di un teatro /* Operazioni finali: apre POSTI.DAT per salvare la nuova situazione prenotazioni: segnala prenotazioni mancate e posti liberi */ if ((out = fopen (POSTI, "w")) == NULL) { printf ("\nErrore apertura %s", POSTI); exit (5); } printf ("\nSituazione prenotazioni:\n"); for (i = 0; i < NFILE; i++) for (j = 0; j < NCOL; j++) printf ("%2d", teatro[i][j]); /* Visualizza sul monitor la situazione */ fprintf (out, "%2d", teatro[i][j]); /* Salva in la situazione nel file */
Prenotazione di un teatro /* Fine riga su monitor e nel file */ printf ("\n"); fprintf (out, "\n"); } fclose (out); printf("\nNumero di prenotazioni non esaudite: %d\n", nook); /* Conta il numero di posti liberi */ for (i = 0; i < NFILE; i++) for ( j = 0; j < NCOL; j++) if (teatro[i][j] == 0) liberi++; printf ("Numero posti liberi: %d\n", liberi);