INFORMATICA
Esercizi
Esempio: polinomi
• Realizzare un programma strutturato in linguaggio C che richieda da
tastiera il grado di due polinomi P1 e P2.
• Successivamente il programma dovrà richiedere i coefficienti dei due
polinomi.
• Infine dovrà eseguire la somma e il prodotto dei due polinomi e
visualizzare il risultato.
• Esempio:
Grado polinomio P1:
Grado polinomio P2:
3
2
© Piero Demichelis
2
Esempio: polinomi
Polinomio P1
Coefficiente
Coefficiente
Coefficiente
Coefficiente
x^0:
x^1:
x^2:
x^3:
2
-3
1
2
Polinomio P2
Coefficiente x^0:
Coefficiente x^1:
Coefficiente x^2:
-1
2
2
P1: +2x^0 -3x^1 +1x^2 +2x^3
P1: -1x^0 +2x^1 +2x^2
Somma: +1x^0 -1x^1 +3x^2 +2x^3
Prodotto: -2x^0 +7x^1 -3x^2 -6x^3
© Piero Demichelis
+6x^4
+4x^5
3
Esempio: polinomi
#include <stdio.h>
#include <stdlib.h>
#define NMAX 50
main()
{
int n, m, i, j;
float p1[NMAX], p2[NMAX];
double somma[NMAX], prodotto[2*NMAX];
/* Inizializza i due polinomi ponendo tutti i coefficienti a zero
for (i=0; i<NMAX; i++)
{
p1[i] = 0;
p2[i] = 0;
}
© Piero Demichelis
*/
4
Esempio: polinomi
/* Legge il grado dei due polinomi */
printf ("\nGrado di P1: ");
scanf ("%d", &n);
printf ("\nGrado di P2: ");
scanf ("%d", &m);
/* Test se il grado è positivo */
if (m<1 || n<1)
{
printf (“\nIl grado deve essere >= 1!");
exit(2);
}
© Piero Demichelis
5
Esempio: polinomi
/* Legge i coefficienti dei polinomi */
printf ("\nCoefficienti di P1: ");
for (i=0; i<=n; i++)
{
printf ("\nCoefficiente x^%d: ", i);
scanf ("%f", &p1[i]);
}
printf ("\nCoefficienti di P2: ");
for (i=0; i<=m; i++)
{
printf ("\nCoefficiente x^%d: ",i);
scanf ("%f", &p2[i]);
}
© Piero Demichelis
6
Esempio: polinomi
/* Calcola la somma
for (i=0; i<=max(m,n); i++)
somma[i] = p1[i] + p2[i];
/*
/*
/*
/*
*/
Calcola il prodotto: inizializza m+n coefficienti a 0. L'indice del */
vettore prodotto corrisponde al grado di quell'elemento. */
Usa gli elementi del vettore per accumulare i risultati delle */
moltiplicazioni parziali
*/
for(i=0; i<=n+m; prodotto[i++]=0);
for(i=0; i<=n; i++)
for(j=0; j<=m; j++)
prodotto[i+j] = prodotto[i+j] + (p1[i] * p2[j]);
© Piero Demichelis
7
Esempio: polinomi
/* Visualizzazione dei risultati */
printf ("\n\nPolinomio P1: ");
for (i=0; i<=n; i++)
printf ("+%fx^%d", p1[i], i);
printf ("\nPolinomio P2: ");
for (i=0; i<=m; i++)
printf ("+%fx^%d", p2[i], i);
printf ("\nSomma: ");
for(i=0; i<=max(m,n); i++)
printf ("+%6.2lfx^%d", somma[i], i);
printf ("\nProdotto: ");
for(i=0; i<=n+m; i++)
printf ("+%6.2lfx^%d", prodotto[i], i);
}
© Piero Demichelis
8
Elaborazione di una matrice
• Scrivere un programma in linguaggio C che:
- legga dal file «matrice.dat» una matrice M di numeri interi preceduta dal
numero di righe e dal numero di colonne (dimensione massima della
matrice: 20x20)
- legga da tastiera un numero intero num;
- cerchi fra gli elementi della matrice il numero num, ed ogni volta che lo
trova (anche più di una) scriva sul file «out.dat» tutte le sottomatrici che
si ottengono da M cancellando la riga e la colonna in cui si trova num.
• I formati dei due file sono specificati nell’esempio. Si osservi
che a seconda della posizione in cui si trova num, le sottomatrici
possono essere una, due o quattro.
© Piero Demichelis
9
Elaborazione di una matrice
Esempio - File «matrice.dat»:
6 7
12 -3
7 34
-3 33
-2 71
0 12
41 15
1
-5
-4
2
21
-3
15
23
16
11
-1
34
24
-7
63
95
7
16
0
11
5
-9
43
0
41
10
-6
27
10
12
Inserisci il numero: 16
© Piero Demichelis
10
Elaborazione di una matrice
File «out.dat»:
Coordinate trovate: 2 3
Sottomatrici:
12
7
-3
34
1
-5
24
-7
0
11
41
10
-2
0
41
71
12
15
2
21
-3
95
7
16
-9
43
0
27
10
12
12
7
2 -3
-2
0
41
© Piero Demichelis
-3
34
33
71
12
15
1
-5
-4
2
21
-3
3
15
23
16
11
-1
34
24
-7
63
95
7
16
0
11
5
-9
43
0
41
10
-6
27
10
12
11
Elaborazione di una matrice
Coordinate trovate: 4 5
Sottomatrici:
12
7
-3
-2
0
-3
34
33
71
12
0
11
5
-9
43
41
10
-6
27
10
1
-5
-4
2
21
15
23
16
11
-1
12
7
-3
-2
0
5 41
© Piero Demichelis
-3
34
33
71
12
15
1
-5
-4
2
21
-3
15
23
16
11
-1
34
4
24
-7
63
95
7
16
0
11
5
-9
43
0
41
10
-6
27
10
12
12
Elaborazione di una matrice
#include <stdio.h>
#include <stdlib.h>
void sotto_matr (int r_in, int r_fin, int c_in, int c_fin);
FILE *f1, *f2;
int M[20][20];
main()
{
int, num, rig, col, i, j, k, w;
/*
apre il file contenente la matrice
*/
if ((f1 = fopen (“matrice.dat”, "r")) == NULL) {
printf (“\nErrore nell'apertura del file matrice.dat");
return 1;
}
© Piero Demichelis
13
Elaborazione di una matrice
/* richiede il numero da ricercare
*/
printf (“\nInserisci un numero intero: ");
scanf ("%d", &num);
/*
crea il file di output
*/
if ((f2 = fopen (“out.dat”, “w")) == NULL)
{
printf (“\nErrore nella creazione del file out.dat");
return 2;
}
/* legge numero di righe e colonne della matrice */
fscanf (f1, "%d %d", &rig, &col);
© Piero Demichelis
14
Elaborazione di una matrice
/* legge il file e lo salva nella matrice M
*/
for (i = 0; i < rig; i++)
for (j = 0; j < col; j++)
fscanf (f1, "%d", &M[i][j]);
fclose(f1);
/*
/*
/*
/*
/*
cerca nella matrice se esiste num controllando ogni elemento */
della matrice tramite due for annidati; quando lo trova esegue la */
funzione sotto_matr per tutte le sottomatrici effettive. Ovvero */
controlla che numero di righe o colonne della sottomatrice sia */
maggiore di zero
*/
© Piero Demichelis
15
Elaborazione di una matrice
for (i = 0; i < rig; i++)
{
for (j = 0; j < col; j++)
{
if (M[i][j] == num)
{
/* trovato num: output delle coordinate */
fprintf (f2, "\nCoordinate trovate: %d %d\n\nSottomatrici:\n\n", i, j);
/* output delle matrici (se esistono)
*/
if ((i > 0) && (j > 0)) sotto_matr (0, i, 0, j);
if ((i > 0) && (j < col – 1)) sotto_matr (0, i, j+1, col);
if ((i < rig - 1) && (j > 0)) sotto_matr (i+1, rig, 0, j);
if ((i < rig -1) && (j < col – 1)) sotto_matr (i+1, rig, j+1, col);
}
}
}
fclose(f2);
}
© Piero Demichelis
16
Elaborazione di una matrice
void sotto_matr (int r_in, int r_fin, int c_in, int c_fin);
{
int riga, colonna;
/*
scrive la matrice sul file di output */
for (riga = r_in; riga < r_fin; riga++) {
for (colonna = c_in; colonna < c_fin; colonna++)
fprintf (f2, "%d ", M[riga][colonna]);
fprintf (f2, "\n");
}
fprintf (f2,"\n");
return;
}
© Piero Demichelis
17
Mappa
Sia data una mappa rettangolare contenente lettere
dell’alfabeto. Tale mappa è memorizzata in un file di testo
(il cui nome deve essere richiesto preventivamente da
tastiera) in ragione di una riga per ogni linea del file.
Si supponga che non vi siano errori di formato e che le
linee abbiano tutte la stessa lunghezza.
Le dimensioni della mappa non sono note in fase
di compilazione, ma non possono eccedere le 20 righe
per 80 colonne e devono essere dedotte dal file.
© Piero Demichelis
18
Mappa
A scopo di esempio, si riporta di seguito il formato di una
mappa 8x8:
qqAAAczz
wwwcccsb
edddCDde
dddbccQw
sssdcdww
QAAzczzE
RrRqqHHi
abcdEFGH
© Piero Demichelis
19
Mappa
Si realizzi un programma strutturato in linguaggio C in grado di
determinare quale è la sequenza di caratteri uguali disposti sulla
stessa riga o sulla stessa colonna avente lunghezza massima. Le
lettere maiuscole dovranno essere considerate equivalenti alle
minuscole (ad esempio, ‘b’ e ‘B’, ai fini del programma, devono essere
considerate la stessa lettera).
Nel caso della mappa precedente, l’output del programma dovrà
essere esattamente il seguente:
La sequenza più lunga si trova in colonna 5, da riga 2 a riga 6.
La disposizione è verticale
La lunghezza 5
Il carattere c.
© Piero Demichelis
20
Mappa
• Base dati:
- la mappa verrà memorizzata in una matrice di caratteri di nome
matr (vettore di stringhe).
- Il numero di righe e il numero di colonne (entrambi ricavati dalla
lettura del file) saranno nr e nc.
- Per poter stampare i parametri richiesti occorre costruire una
sequenza di variabili:
lmax
= lunghezza della stringa più lunga
carattere = carattere della sequenza
riga
= riga di inizio sequenza
colonna = colonna di inizio sequenza
direz
= direzione della sequenza ('o‘ oppure ‘v’)
© Piero Demichelis
21
Mappa
#include <stdio.h>
#include <string.h>
#include <conio.h>
#define N_RIGHE 21
#define N_COL 81
main()
{
int i, j, nr, nc, cont, riga, colonna, lmax;
char matr[N_RIGHE][N_COL];
FILE *leggi;
char nomefile[50], carattere, cfr, direz;
clrscr();
© Piero Demichelis
22
Mappa
printf (“\nNome file: ");
scanf ("%s", nomefile);
/* apre il file
*/
if ((leggi = fopen (nomefile, "r")) == NULL)
{
printf ("\n Errore apertura %s\n", nomefile);
exit (0);
}
/* inizializza tutta la matrice col carattere di fine stringa */
for (i = 0; i < N_RIGHE; i++)
for (j = 0; j < N_COL; j++)
matr[i][j] = '\0';
© Piero Demichelis
23
Mappa
/*
Ciclo di lettura della mappa; legge fino a EOF
*/
nr = 0;
while (!feof (leggi))
{
fscanf (leggi, "%s", &matr[nr]);
nr++;
/* in nr numero di righe lette */
}
fclose (leggi);
/* setta in nc = numero colonne matrice */
nc = strlen (matr[0]);
/* in lmax registra la lunghezza della sequenza più lunga */
lmax = 0;
© Piero Demichelis
24
Mappa
/*
Ricerca per righe: in cfr carattere campione da confrontare, in
cont numero di ripetizioni consecutive di quel carattere
*/
for (i = 0; i < nr; i++)
{
cfr = tolower (matr[i][0]); /* primo carattere campione = al primo */
cont = 1; /* carattere della riga! inoltre inizializza il contatore a 1 */
/* scandisce le colonne della riga i */
for (j = 1; j <= nc; j++)
{
if (tolower(matr[i][j]) == cfr) /* è = al carattere campione? */
cont++;
/* si, incrementa il contatore */
else
/* no, è diverso per cui è terminata una sequenza la cui lunghezza è in
cont: verifica se è la più lunga finora. Contemporaneamente col
carattere attuale è iniziata una nuova sequenza.
© Piero Demichelis
25
Mappa
{
if (cont > lmax)
/* è la sequenza più lunga? */
{
lmax = cont;
/* si, la sostituisce alla precedente */
carattere = cfr;
riga = i+1;
/* riga di inizio sequenza */
colonna = j – cont + 1; /* colonna di inizio sequenza */
direz = 'o';
/* direzione (orizzontale) */
}
cfr = tolower (matr[i][j]);
/* nuovo carattere campione */
cont = 1;
}
/* else…..
*/
}
/* for (j=1; ……
*/
}
/* for (i=0;……
*/
© Piero Demichelis
26
Mappa
/* Ricerca per colonne: blocco di istruzioni identico al caso
della ricerca per righe scambiando solamente i ruoli delle
variabili nc e nr */
for (j = 0; j <= nc; j++)
{
cfr = tolower (matr[0][j]);
cont = 1;
for (i = 1; i <= nr; i++)
{
if (tolower (matr[i][j]) == cfr)
cont++;
else
© Piero Demichelis
27
Mappa
{
if (cont > lmax)
{
lmax = cont;
carattere = cfr;
riga = i - cont + 1;
colonna = j + 1;
direz = 'v';
}
cfr = tolower(matr[i][j]);
cont = 1;
}
/* else……
*/
}
/* for (i=1;……. */
}
/* for (j=0;….. */
© Piero Demichelis
28
Mappa
/*
Visualizza i risultati
*/
printf ("\nSequenza più lunga ");
if (direz == 'v')
{
printf ("in colonna %d, da riga %d a riga %d", colonna, riga,
riga + lmax -1);
printf ("\nLa disposizione è verticale");
}
else
{
printf ("in riga %d, da colonna %d a colonna %d", riga, colonna,
colonna + lmax -1);
printf ("\nLa disposizione è orrizzontale");
}
printf ("\nLa lunghezza è %d\nIl carattere %c\n", lmax, carattere);
}
© Piero Demichelis
29
Esempio: prenotazione aerei
• All'interno di un file di testo è elencato un insieme di voli aerei. Per
ognuno di essi, su ciascuna riga del file, sono riportate (separate da
un singolo spazio) la città di partenza, quella di arrivo e la sigla (2
caratteri) della compagnia aerea che gestisce il volo. E' garantito che
il nome della città non contenga spazi (es. New York verrà scritto
New_York).
• Si scriva un programma in linguaggio C che, ricevuto come primo
argomento sulla riga di comando il nome del file e come secondo
argomento il nome di una città, produca il seguente risultato
sull'unità di output standard:
- l’elenco dei voli in partenza dalla città
- l'elenco dei voli in arrivo nella città
- l'elenco delle compagnie aeree con voli in partenza o in arrivo alla città
selezionata.
• Il numero massimo di voli in partenza da una città (o in arrivo) non
supera le 100 unità.
© Piero Demichelis
30
Esempio: prenotazione aerei
• Ad esempio, se il file VOLI.TXT contenesse i seguenti dati:
Roma Milano AZ
Milano Roma AZ
Torino Parigi AF
Parigi Torino AF
Milano Londra BA
Londra Milano BA
Milano New York AZ
Milano New York UA
New York Milano AZ
New York Milano UA
e il programma - denominato FLY - venisse attivato nel seguente
modo:
FLY VOLI.TXT Milano
© Piero Demichelis
31
Esempio: prenotazione aerei
allora dovrebbe generarsi il seguente output:
Voli in partenza da Milano:
Milano Roma AZ
Milano Londra BA
Milano New_York AZ
Milano New_York UA
Voli in arrivo a Milano:
Roma Milano AZ
Londra Milano BA
New_York Milano AZ
New_York Milano UA
Compagnie aeree:
AZ
BA
UA
© Piero Demichelis
32
Esempio: prenotazione aerei
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXVOLI 100
typedef enum{FALSO,VERO} boolean;
int main(int argc, char *argv[ ])
{
char tab_arrivi[MAXVOLI][80], compagnie[MAXVOLI][3];
int num_arrivi,num_comp,i;
char partenza[80], arrivo[80], compagnia[3], citta[20];
boolean trovato, presente;
FILE *in;
© Piero Demichelis
33
Esempio: prenotazione aerei
/*
/*
Controlli sulla correttezza del numero di parametri introdotto */
dalla linea di comando */
if (argc != 3)
{
printf ("\nErrore: imposta come parametri nome file e città\n");
exit (1);
}
/*
apre il file dei voli
*/
if ((in=fopen(argv[1],"r"))==NULL)
{
printf ("\nErrore in apertura file\n");
exit (2);
}
© Piero Demichelis
34
Esempio: prenotazione aerei
strcpy (citta, argv[2]);
num_arrivi = 0;
num_comp = 0;
/* argv[2] in citta */
printf ("\nVoli in partenza da %s:\n\n", citta);
while (!feof(in))
{
fscanf (in, "%s %s %s", partenza, arrivo, compagnia)
trovato = FALSO;
/* controlla la partenza */
if (strcmp (partenza, citta)==0)
{
printf ("%s %s %s\n", partenza, arrivo, compagnia);
trovato = VERO;
}
© Piero Demichelis
35
Esempio: prenotazione aerei
/* controlla l'arrivo
*/
if (strcmp (arrivo,citta)==0)
{
sprintf (tab_arrivi[num_arrivi], "%s %s %s",
partenza, arrivo, compagnia);
num_arrivi++;
trovato = VERO;
}
/* controlla se la compagnia è già presente nella lista */
if (trovato)
{
presente = FALSO;
for (i=0; i<num_comp; i++)
if (strcmp(compagnia, compagnie[i]) == 0)
presente = VERO;
© Piero Demichelis
36
Esempio: prenotazione aerei
if (!presente)
{
strcpy(compagnie[num_comp], compagnia);
num_comp++;
}
}
}
/* fine while */
/* Elenca i voli in arrivo e le compagnie accumulati nei vettori di */
/* stringhe tab_arrivi e compagnie in precedenza
*/
printf ("\n\nVoli in arrivo a %s:\n\n", citta);
for (i=0; i<num_arrivi; i++)
printf ("%s\n", tab_arrivi[i]);
}
printf ("\n\nCompagnie che operano a %s:\n\n", citta);
for (i=0; i<num_comp; i++)
printf ("%s\n", compagnie[i]);
© Piero Demichelis
37
Compressione di immagini
• Scrivere un programma in linguaggio C per la compressione di
immagini che:
- legga dal file «matrice.dat» una matrice di numeri reali di dimensione
30x30;
- legga da tastiera due numeri interi N e M che rappresentano le
dimensioni di una sottomatrice;
• suddivida la matrice in sottomatrici NxM a partire dall’elemento in
alto a sinistra, e costruisca una nuova matrice 30x30 di numeri reali,
in cui ogni elemento delle sottomatrici è dato dalla media degli
elementi della sottomatrice stessa (vedere esempio);
• visualizzi su video la matrice finale.
• Importante: vicino al bordo destro e inferiore è possibile che le
sottomatrici da considerare abbiamo dimensioni inferiori a NxM
(vedere esempio).
© Piero Demichelis
38
Compressione di immagini
• Esempio: Con N= 2, M=4:
File «matrice.dat» (per semplicità sia 6x6):
1 0 1 2 3 4
2 3 2 3 0 5
0 2 1 2 4 3
1 2 2 2 1 0
1 5 4 3 2 1
2 1 2 0 7 0
media = 1.75
Matrice finale :
1.75 1.75 1.75
1.75 1.75 1.75
1.5 1.5 1.5
1.5 1.5 1.5
2.25 2.25 2.25
2.25 2.25 2.25
1.75
1.75
1.5
1.5
2.25
2.25
3.0
3.0
2.0
2.0
2.5
2.5
3.0
3.0
2.0
2.0
2.5
2.5
© Piero Demichelis
39
Compressione di immagini
#include <stdio.h>
#include <stdlib.h>
#define DIM 30
main()
{
float mat[DIM][DIM], som, med;
int N, M, i, j, k, rig, col;
FILE *f1;
printf ("\nInserisci il numero di righe N: ");
scanf ("%d",&N);
printf ("\nInserisci il numero di colonne M: ");
scanf ("%d",&M);
© Piero Demichelis
40
Compressione di immagini
/* apre il file matrice.dat
*/
if ((f1 = fopen ("matrice.dat","r")) == NULL);
{
printf (“\nErrore apertura di matrice.dat\n”);
return (1);
}
/* legge il file matrice.dat ritenuto corretto, pertanto non ci sono */
/* controlli sui valori letti
*/
for (i = 0; i < DIM; i++)
for (j = 0; j < DIM; j++)
fscanf (f1, "%f", &mat[i][j]);
fclose(f1);
© Piero Demichelis
41
Compressione di immagini
/* individua riga e colonna iniziale di tutte le possibili sottomatrici */
for (rig = 0; rig < DIM; rig += N)
{
for (col = 0; col < DIM; col += M)
{
/* per ognuna calcola il valor medio */
k = 0;
som = 0;
for (i = rig; i < (N + rig) && i < DIM; i++)
{
for (j = col; j < (M + col) && j < DIM; j++)
{
k++;
som += mat[i][j];
}
/* fine “for (j = col; j < (M + col) &&....” */
}
/* fine “for (i = rig; i < (N + rig) &&....” */
© Piero Demichelis
42
Compressione di immagini
/* costruisce la nuova sottomatrice sostituendo ai valori precedenti */
/* il valor medio appena calcolato */
med = som / k;
for (i = rig; i < (N + rig) && i < DIM; i++)
for (j = col; j < (M + col) && j < DIM; j++)
mat[i][j] = med;
}
/* fine “for (col = 0; col < DIM; col += M)”
}
/* fine “for (rig = 0; rig < DIM; rig += N)” */
/*
visualizza la nuova matrice
*/
for (i = 0; i < DIM; i++)
{
for (j = 0; j < DIM; j++)
printf ("%.2f ", mat[i][j]);
printf ("\n");
}
}
© Piero Demichelis
*/
43
Gestione di un bar
• Si desidera realizzare un programma in linguaggio C che consenta di
gestire i conti dei clienti di un bar. Il programma permette di inserire
da tastiera il codice numerico di ognuna delle consumazioni di un
cliente.
• Il codice 0 indica che l’inserimento è finito e che il programma deve
stampare il conto; il conto stampato dal programma contiene la
descrizione e il costo di ognuna delle consumazioni, nonché l’importo
totale dovuto dal cliente.
• Si noti che il codice 0 non implica la fine del programma, il quale
deve invece ritornare all’inizio dell’inserimento di un nuovo conto. Il
programma termina quando viene introdotto il codice –1.
© Piero Demichelis
44
Gestione di un bar
• La corrispondenza tra il codice di una consumazione e un
articolo si trova in un primo file il cui nome viene
specificato come primo parametro sulla linea di
comando. Nel file i codici (e i relativi articoli) sono
elencati in ordine a partire dal codice 1 (vedi esempio).
• La corrispondenza tra un articolo ed il suo prezzo si trova
in un secondo file il cui nome viene specificato come
secondo parametro sulla linea di comando.
• Si facciano inoltre le seguenti assunzioni:
- Ciascun conto consiste al massimo di 10 consumazioni
- Sono previsti al massimo 100 articoli diversi.
© Piero Demichelis
45
Gestione di un bar
• Esempio:
•
1
2
3
4
5
Supponendo che il file CODICI.DAT contenga i seguenti dati:
Birra_Media
Birra_Piccola
Panino
Coca_Cola
Acqua_Minerale
e che il file PREZZI.DAT contenga i seguenti dati:
Panino
3.50
Coca_Cola
2.00
Birra_Media
4.00
Birra_Piccola
2.50
Acqua_Minerale
1.00
© Piero Demichelis
46
Gestione di un bar
• Invocando il programma di nome CONTO con il seguente comando:
CONTO CODICI.DAT PREZZI.DAT
• Inserendo i seguenti dati,
Consumazione?
Consumazione?
Consumazione?
Consumazione?
1
5
1
0
il programma produrrà il seguente output:
Birra_Media 4.00
Panino
3.50
Birra_Media 4.00
Totale 11.50 Euro.
Consumazione?
© Piero Demichelis
47
Gestione di un bar
#include <stdio.h>
typedef enum {FALSO, VERO} boolean;
typedef struct {
char articolo[30];
float costo;
} prodotti;
void stampa_output (prodotti v[], int n, float tot)
int main (int argc, char *argv[])
{
prodotti consumazione[10], articoli[101];
float totale_cons = 0.0, costo;
int i, artic = 0, codice, cod, N_articoli = 0;
char prodotto[30];
boolean trovato;
FILE *fp1, *fp2;
© Piero Demichelis
48
Gestione di un bar
if(argc != 3)
{
printf ("errore parametri\n");
return 1;
}
/* controllo argomenti */
if ((fp1 = fopen (argv[1],"r")) == NULL)
{
fprintf (stderr,"Errore nell'apertura del file %s\n", argv[1]);
return 2;
}
if ((fp2 = fopen (argv[2],"r")) == NULL)
{
fprintf (stderr,"Errore nell'apertura del file %s\n", argv[2]);
return 3;
}
© Piero Demichelis
49
Gestione di un bar
/* riempimento del vettore di strutture articoli */
while (fscanf (fp1,"%d%s", &cod, prodotto) != EOF) {
strcpy (articoli[cod].articolo, prodotto);
N_articoli++;
}
fclose (fp1);
/* Legge il costo dei prodotti e li salva nel campo di pertinenza */
while (fscanf (fp2,"%s%f", prodotto, &costo) != EOF)
{
/* cerco nel vettore di strutture */
i = 1;
trovato = FALSO;
while (!trovato && (i <= N_articoli))
{ if (strcmp (prodotto, articoli[i].articolo) == 0)
{ articoli[i].costo = costo;
trovato = VERO; }
i++; }
}
fclose(fp2);
© Piero Demichelis
50
Gestione di un bar
/*
inizio parte interattiva
printf (“\nConsumazione? ");
scanf ("%d", &codice);
*/
while (codice != -1)
{
if (codice == 0)
{
stampa_output (consumazione, artic, totale_cons);
artic = 0;
/* inizializzazioni per prossimo conto */
totale_cons = 0.0;
}
else
{
consumazione[artic] = articoli[codice]);
artic++;
totale_cons += articoli[codice].costo;
}
© Piero Demichelis
51
Gestione di un bar
printf ("\nConsumazione? ");
/* leggi un altro codice */
scanf ("%d", &codice);
}
/* fine del ciclo while (c!= -1)...... */
}
/* fine del main*/
void stampa_output (prodotti v[], int n, float tot)
{
int i;
for (i=0; i<n; i++)
printf ("%s %f\n", v[i].articolo, v[i].costo);
printf ("Totale %f\n", tot);
}
© Piero Demichelis
52
Esempio: supermercato
• Gli acquisti effettuati in un piccolo supermercato sono registrati e
memorizzati in un file di caratteri costituito da un numero di righe
indefinito. Ciascuna riga ha il seguente formato:
prodotto categoria valore
• in cui: prodotto indica il nome del prodotto acquistato, categoria
indica una suddivisione in categorie dei prodotti (e.g., alimentari,
vestiario, etc.), valore indica la cifra spesa (e.g., in lire o euro) per
l'acquisto dello stesso.
• Il prodotto e la categoria sono individuati da stringhe di caratteri
(non contenenti spazi) e di lunghezza massima uguale a 50 e 3
caratteri rispettivamente; valore è un numero intero.
© Piero Demichelis
53
Esempio: supermercato
• Si richiede la scrittura di un programma in linguaggio C che produca
un secondo file contenente delle statistiche sugli acquisti, suddivise
per categoria (i.e., ciascuna categoria deve comparire nel file una
sola volta). Ciascuna riga del file deve avere il seguente formato:
categoria numero valore-totale valore-medio
• in cui: numero indica il numero totale di acquisti per la relativa
categoria, valore-totale la somma totale dei valori per quella
categoria, e valore-medio la cifra media spesa per quella categoria
in ciascun acquisto. Tutti i valori numerici devono essere riportati
quali interi.
• I nomi dei due file devono essere letti da tastiera, il file di ingresso si
può supporre di formato corretto, il numero massimo di categorie è
uguale a 100, l'ordine di memorizzazione nel file di uscita delle varie
categorie può essere qualsiasi.
© Piero Demichelis
54
Esempio: supermercato
Esempio.
• Supponendo che il file di ingresso abbia il seguente formato
pastaXYZ ali 8000
pannolini123 mis 30000
paneAAA ali 2500
jeansBBB ves 85000
scarpeCCC ves 45000
olioXYWZ ali 12500
• occorre produrre il seguente file
ali 3 23000 7667
ves 2 130000 65000
mis 1 30000 30000
© Piero Demichelis
55
Esempio: supermercato
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
typedef enum {FALSO,VERO} boolean;
main()
{
char nomefile[80];
struct cate
{
char nome[4];
long num;
long val;
} categorie[MAX];
© Piero Demichelis
56
Esempio: supermercato
FILE *in,*out;
long ncat = 0, val, i;
boolean trovato;
char cat[4], prod[51];
/* Richiede nome file */
printf ("\nNome file aquisti: ");
scanf ("%s", nomefile);
/* Apre il file
*/
if ((in = fopen(nomefile, "r")) == NULL)
{
printf ("\nErrore open\n");
exit (1);
}
© Piero Demichelis
57
Esempio: supermercato
/* Legge il file riga per riga e cerca se la categoria è già presente */
while (!feof (in))
{
fscanf (in, "%s %s %ld", prod, cat, &val)
trovato = FALSO;
i = 0;
while (!trovato && (i < ncat))
if (strcmp(categorie[i].nome, cat) == 0)
{
/* categoria già vista prima: aggiorna i campi */
categorie[i].num++;
categorie[i].val += val;
trovato = VERO;
}
© Piero Demichelis
58
Esempio: supermercato
/* categoria nuova, aggiunge un nuovo elemento al vettore di */
/* strutture per l’output finale
*/
if (!trovato)
{
strcpy (categorie[ncat].nome, cat);
categorie[ncat].num = 1;
categorie[ncat].val = val;
ncat++;
}
}
fclose(in);
/*
Chiede il nome file di output e lo crea
*/
printf ("\nNome file output: ");
scanf ("%s", nomefile);
© Piero Demichelis
59
Esempio: supermercato
if ((out = fopen(nomefile,"w")) == NULL)
{
printf ("\nErrore open\n");
exit (3);
}
/*
Scrive sul file di output i dati richiesti */
for (i=0; i<ncat; i++)
fprintf (out,"%s %ld %ld %ld\n", categorie[i].nome,
categorie[i].num, categorie[i].val,
categorie[i].val/categorie[i].num);
fclose(out);
}
© Piero Demichelis
60
Crittografia
Si desidera realizzare un programma in linguaggio C a cui vengono
forniti come parametri sulla riga di comando due nomi di file e
un numero intero N maggiore di zero.
Il primo file contiene un testo in formato ASCII, e consiste di un
numero indefinito di righe ciascuna formata al massimo da 80
caratteri.
Il programma deve crittografare il contenuto del primo file e scriverlo
nel secondo file, anch'esso in formato ASCII.
Il metodo crittografico considerato funziona nel seguente modo:
ogni lettera maiuscola e minuscola dell'alfabeto deve essere
sostituita con la lettera dell'alfabeto stesso che si ottiene
spostandosi di N posizioni in ordine alfabetico crescente,
partendo dalla lettera che si vuole crittografare. Ad esempio se N=5
e il carattere da crittografare è il carattere “m”, il carattere
crittografato sarà “r” (5 posizioni nell’ordine alfabetico dopo la “m”).
© Piero Demichelis
61
Crittografia
Lo spostamento deve essere effettuato in modo
“circolare”: Se nello spostamento, dalla lettera considerata, si
supera la fine dell'alfabeto, si deve ripartire a contare
dall’inizio. Ad esempio, se N=1, e il carattere da crittografare è
"z" il carattere da scrivere nel secondo file sarà il carattere "a".
A sostituzione avvenuta, la riga crittografata deve essere
scritta invertita nel secondo file (cioè l'ultimo carattere diventa
il primo, il penultimo diventa il secondo e così via).
Tutti gli altri caratteri (punteggiatura, spaziatura) rimangono
inalterati.
NOTE:
- Si consiglia di processare un carattere per volta usando le
opportune funzioni di interrogazione dell’insieme dei caratteri
ASCII.
© Piero Demichelis
62
Crittografia
Esempio di esecuzione:
Supponendo di avere N=1 e che il contenuto del file di
input sia:
Questo compito e’ facilissimo!
Vero?
Nel file di output dovrà esserci scritto:
!pnjttjmdbg ‘f pujpnpd putfvR
?psfW
© Piero Demichelis
63
Crittografia
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define DIM 80
/* prototipo */
void inverti (char s[]);
/* main */
int main (int argc, char *argv[])
{
FILE *fin, *fout;
int i, N, val;
char lineain[DIM], lineaout[DIM];
© Piero Demichelis
64
Crittografia
if (argc != 4)
{
printf ("Errore di formato dei parametri!\n");
exit (0);
}
if ((fin = fopen (argv[1], "r")) == NULL)
{
printf ("Errore nell'apertura del file %s\n", argv[1]);
exit (0);
}
if ((fout = fopen (argv[2], "w")) == NULL)
{
printf ("Errore nell'apertura del file %s\n", argv[2]);
exit (0);
}
© Piero Demichelis
65
Crittografia
N = atoi (argv[3]);
/* legge una linea alla volta e poi inverte la stringa crittografata
*/
while (fgets (lineain, DIM, fin) != NULL)
{
/*
ora processa carattere per carattere */
for (i=0; i<strlen (lineain); i++)
{
/* processa solo i caratteri alfabetici */
if (isalpha (lineain[i]))
{
/*
devo sommare N al codice ASCII */
if (islower(lineain[i]))
val = lineain[i]-'a';
else
val = lineain[i]-'A';
val = ((val + N) % 26); /* somma 'circolare‘: ci sono 26 caratteri */
/*
ritrasformo 'val' in un carattere ASCII
*/
if (islower(lineain[i]))
lineaout[i] = val + 'a';
else
lineaout[i] = val + 'A';
/*
NOTA: non e' l'unico modo per sommare N !
*/
}
© Piero Demichelis
66
Crittografia
/*
else
non è un carattere alfabetico, quindi lo scrive invariato
lineaout[i] = lineain[i];
/* chiusura di
for (i=0; i<strlen (lineain);…..
*/
/* finito il processamento della linea 'lineain‘, ora la inverto e la
/* scrivo sul file 'fout'. Prima pero' devo aggiungere il NULL se no
/* non e' una stringa!
lineaout[i] = '\0';
inverti (lineaout);
puts (lineaout);
/* visualizza anche sul monitor (non richiesto)
fputs (lineaout, fout);
fprintf (fout, “\n”);
}
/* chiusura di
while (fgets(lineain, DIM, fin)……
*/
*/
*/
}
}
*/
*/
*/
fclose (fin);
fclose (fout);
© Piero Demichelis
67
Crittografia
void inverti (char s[])
{
int i, len = strlen(s);
char tmp;
for (i=0; i < len/2; i++)
{
/*
scambio i valori i e N-i-1
tmp = s[i];
s[i] = s[len-i-1];
s[len-i-1] = tmp;
}
/* nota: s viene passata per indirizzo (e' un vettore) e pertanto
/* viene ritornata al main modificata
}
© Piero Demichelis
*/
*/
*/
68
Import / Export
• Sono dati tre file di testo contenenti le informazioni sulle operazioni di una
ditta di import/export, che ha relazioni commerciali con società appartenenti
a vari stati.
• Un primo file (il cui nome è STATI.DAT) contiene l’elenco degli stati (al
massimo 100) con cui esistono relazioni commerciali, nel seguente
formato:
<codice_stato> <nome_stato>
dove <codice_stato> è un codice numerico progressivo (un numero
intero: 0 per il primo stato, 1 per il secondo, …), mentre <nome_stato> è
il nome dello stato, privo di spazi.
Esempio:
0 Stati_Uniti
1 Corea
2 Giappone
3 Francia
4 Germania
© Piero Demichelis
69
Import / Export
• Un secondo file (il cui nome DITTE.DAT) contiene l’elenco delle
ditte (al massimo 1000) , con cui esistono relazioni commerciali,
nel seguente formato:
<codice_stato> <nome_societa>
dove <codice_stato> è il codice dello stato cui appartiene la
società, <nome_societa> è il nome della società.
Esempio:
1 Kia
4 BMW
4 Mercedes
3 Peugeot
3 Citroen
2
2
0
0
0
© Piero Demichelis
Honda
Mitsubishi
Chrysler
General_Motors
Chevrolet
70
Import / Export
• Un terzo file (il cui nome è TRANSAZIONI.DAT) contiene le informazioni su un certo
numero di transazioni commerciali, ognuna delle quali viene rappresentata, su una
riga del file, secondo il formato:
<nome_societa> <importo> <data>
dove <nome_società> è il nome della società, <importo> è un intero, che
rappresenta l’importo della transazione (valore negativo per importazione, positivo per
esportazione), <data> è la data della transazione (formato gg/mm/aaaa).
Esempio:
Mitsubishi 101 21/01/2004
Chrysler -30 01/02/2004
General_Motors -2000 10/02/2004
Chevrolet 50 04/03/2004
Kia 500 12/03/2004
BMW -1200 15/04/2004
Mercedes -400 23/04/2004
BMW -1000 22/06/2004
Mercedes 300 23/06/2004
Peugeot 403 02/07/2004
General_Motors 1124 05/07/2004
Chevrolet 350 10/08/2004
Citroen -325 11/08/2004
Honda -670 30/08/2004
Peugeot -768 21/09/2004
Kia -800 23/09/2004
© Piero Demichelis
71
Import / Export
• Si scriva un programma in linguaggio C che legga
ed elabori i dati secondo le richieste seguenti.
• Calcoli il numero totale delle transazioni e i bilanci
complessivi delle transazioni di importazione e
esportazione (somma degli importi relativi,
rispettivamente, a importazioni ed esportazioni), che
vanno stampati su video.
• Calcoli per ogni stato, il bilancio complessivo commerciale
di import/export (cioé la sommatoria, per ogni stato, degli
importi relativi a tutte le società appartenenti allo stato).
Per ogni stato vanno stampati su video il nome e il
bilancio totale.
© Piero Demichelis
72
Import / Export
• Sulla base di questi dati, l’output del programma sarà il seguente:
Numero transazioni: 16
Totale importazioni: -7193
Totale esportazioni: 2828
STATO:
STATO:
STATO:
STATO:
STATO:
Stati_Uniti BILANCIO:
-506
(ottenuto come: -30-2000+50+1124+350)
Corea
BILANCIO:
-300
(ottenuto come: 500-800)
Giappone
BILANCIO:
-569
(ottenuto come: 101-670)
Francia
BILANCIO:
-690
(ottenuto come: 403-325-768)
Germania
BILANCIO:
-2300
(ottenuto come: -1200-400-1000+300)
© Piero Demichelis
73
Import / Export
Per semplicità non devono essere eseguiti controlli di errore sul
formato dei file, sugli argomenti al main, sull'apertura corretta dei
file.
La soluzione proposta prevede due tipi struct (t_stato e t_societa)
per le informazioni relative, rispettivamente, a stati e società.
I primi due file vengono infatti letti caricando i dati un due vettori di
struct (tabella_stati e tabella_societa). Il codice di uno stato non
viene inserito nella struttura t_stato in quanto coincide con l'indice
dello stato stesso nel vettore (0 per il primo stato, 1 per il secondo,
...).
Per i dati nel terzo file non sono previste tabelle, in quanto non è
necessario disporre di tutte le informazioni (su tutte le transazioni)
contemporaneamente: il file viene letto riga per riga aggiornando le
statistiche sulle transazioni (globali e per stato) mediante i dati
appena letti: le date vengono lette ma ignorate, in quanto non
necessarie alla soluzione del problema.
© Piero Demichelis
74
Import / Export
#include <stdio.h>
/* tipi struct per stato e societa' */
typedef struct {
char nome[30];
int bilancio;
} t_stato;
typedef struct {
char nome[30];
int codice_stato;
} t_societa;
/* prototipo di funzione */
int cercaCodiceStato (t_societa tabella_societa[], int n, char nome[]);
© Piero Demichelis
75
Import / Export
int main (void)
{
FILE *fp;
int i, nst, nsoc;
int codice_stato, importo;
int nt, si, se;
/* num. trans., importazioni, esportazioni */
char nome[30];
t_stato tabella_stati[100];
t_societa tabella_societa[1000];
/* lettura file stati.dat: tabella stati */
fp = fopen ("stati.dat","r");
© Piero Demichelis
76
Import / Export
nst=0;
while (fscanf(fp,"%d%s", &codice_stato, nome)!=EOF) {
nst++;
strcpy (tabella_stati[codice_stato].nome,nome);
tabella_stati[codice_stato].bilancio = 0;
}
fclose(fp);
/* lettura file ditte.dat: tabella societa' */
fp = fopen ("ditte.dat", "r");
nsoc = 0;
while (fscanf(fp,"%d%s", &codice_stato, nome) != EOF) {
strcpy (tabella_societa[nsoc].nome, nome);
tabella_societa[nsoc].codice_stato = codice_stato;
nsoc++;
}
fclose(fp);
© Piero Demichelis
77
Import / Export
/* Lettura transazioni.dat ed elaborazione dei dati. Per ogni riga del file
transazioni.dat, letti nome della societa e importo, si aggiornano gli importi
totali e di import/export. Si calcola quindi il codice dello stato (mediante la
funzione cercaCodiceStato, quindi si aggiorna la statistica di bilancio totale
relativa allo stato. */
fp = fopen ("transazioni.dat", "r");
nt = si = se = 0;
while (fscanf (fp,"%s%d%*s", nome, &importo) != EOF) {
nt++;
if (importo > 0)
se += importo;
else
si += importo;
i = cercaCodiceStato (tabella_societa, nsoc, nome);
tabella_stati[i].bilancio += importo;
}
fclose(fp);
© Piero Demichelis
78
Import / Export
/* stampa statistiche globali */
printf ("Numero transazioni: %d\n", nt);
printf ("Totale importazioni: %d\n", si);
printf ("Totale esportazioni: %d\n\n", se);
/* stampa statistiche per stato */
for (i=0; i<nst; i++)
printf ("STATO: %-30s BILANCIO: %8d\n",
tabella_stati[i].nome, tabella_stati[i].bilancio);
}
© Piero Demichelis
79
Import / Export
/* funzione che cerca il codice dello stato cui appartiene una societa',
dato il nome di quest'ultima. La ricerca viene fatta nella tabella delle
societa'. */
int cercaCodiceStato ( t_societa tabella_societa[], int n, char nome[])
{
int i;
for (i=0; i<n; i++)
{
if (strcmp (tabella_societa[i].nome, nome) == 0)
index = tabella_societa[i].codice_stato;
}
return (index);
}
© Piero Demichelis
80
Scarica

Esercizi_3