Esercizio 1 Liste: calcolo perimetro di un poligono

Transcript

Esercizio 1 Liste: calcolo perimetro di un poligono
Esercitazione Fondamenti di Informatica B
Corso di Laurea in Ingegneria Meccanica
12° Esercitazione: 28 gennaio 2005
Esercizi su liste, ricorsione, file.
Scaletta
• Esercizio
• Esercizio
• Esercizio
• Esercizio
1 Liste: calcolo perimetro di un poligono
2 Ricorsione: esercizio di analisi di un programma ricorsivo
3 File: ricerca di un record in un file binario
4 File: esercizio sull’apertura dei file in modalità append.
Esercizio 1 Liste: calcolo perimetro di un poligono
Scrivere la funzione perimetro che riceve una lista di punti nel piano cartesiano rappresentante un
poligono e restituisce:
• il perimetro del poligono se numero di punti ≥ 3;
• -1 se numero di punti <3.
Le strutture dati necessarie per definire il tipo lista sono le seguenti:
typedef struct El
{ float x, y;
struct El *next;
} ElemLista;
typedef ElemLista * Lista;
Si ricorda che, per calcolare la distanza fra due punti di coordinate (x1, y1) e (x2, y2)
rispettivamente la formula è la seguente:
• sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
Si ricorda che la libreria math.h include la funzione sqrt(val1), che esegue il calcolo della radice
quadrata del valore numerico fornito in ingresso.
Soluzione
In Pseudo-codice:
float perimetro (Lista listaVertici) {
float perim;
if ( # nodi < 3 ) return –1.0;
perim = 0.0;
/* prendi nota del primo vertice */
/* scorri tutta la lista, somma distanza da punto i a punto i+1
/* aggiungi distanza tra vertice n e primo vertice*/
return perim;
}
In linguaggio C:
#include <math.h>
#include <stdio.h>
typedef struct El
{ float x, y;
struct El *next;
} ElemLista;
typedef ElemLista * Lista;
int nElementi (Lista lis) {
int nEl = 0;
while (lis != NULL) {
nEl ++;
lis = lis->next;
}
return nEl;
}
float distanza (Lista a, Lista b)
{
float distX, distY;
distX = a -> x - b -> x;
distY = a -> y - b -> y;
return sqrt (distX * distX + distY * distY);
}
float perimetro (Lista listaVertici)
{
float perim;
Lista primoVert, corrente, successivo;
if ( nElementi (listaVertici) < 3 ) return -1.0;
perim = 0.0;
primoVert = listaVertici; /* prendi nota del primo vertice */
/* scorri tutta la lista, somma distanza da punto i a punto i+1 */
corrente = primoVert;
successivo = primoVert -> next;
while ( successivo != NULL) {
perim = perim + distanza (corrente, successivo);
corrente = corrente -> next;
successivo = successivo -> next;
}
/* aggiungi distanza tra vertice n e primo vertice*/
perim = perim + distanza (corrente, primoVert);
return perim;
}
Esercizio 2 Ricorsione: esercizio di analisi di un programma ricorsivo
Dato il seguente programma:
#include <stdio.h>
int p=1000;
int f(int x, int n);
void main()
{
printf("%d\n", f(p,100));
printf("%d\n", f(p,100));
}
int f(int x, int n)
{
if ((x%n)==0) {
p = p + 1;
return p;
}
else return f(x-1, n);
}
a) Si indichino, nel giusto ordine, i valori stampati dal programma, motivando la risposta data.
b) Si descriva l’evoluzione dinamica dello stack durante l’esecuzione del programma.
Soluzione
a) La funzione f aggiorna il valore della variabile globale p; il programma stamperà quindi:
• 1001;
• 1002.
b)
Esercizio 3 File: ricerca di un record in un file binario
Si ipotizzi di avere un file “anagrafe” in cui sono memorizzate le persone abitanti in un certo
comune. Per ogni persona, sono memorizzate le seguenti informazioni:
• Nome: una stringa che rappresenta il nome della persona.
• Cognome: una stringa che rappresenta il cognome della persona.
• Data di nascita: un insieme di tre interi che rappresenta la data di nascita.
• Luogo di nascita: una stringa che rappresenta la località di nascita.
• Indirizzo: una stringa che rappresenta l’indirizzo della persona;
• Codice Fiscale: una sequenza di 16 caratteri che individua univocamente il cittadino.
Si ipotizzi che il file in questione sia stato opportunamente riempito da un altro programma C
usando la primitiva fwrite (scrittura ‘a blocchi’).
Realizzare un programma che, dato il file “anagrafe”, ricerchi e stampi tutti gli elementi del file che
hanno cognome uguale ad una stringa C letta da standard input. Il programma deve inoltre
stampare il numero totale degli elementi del file che hanno il cognome uguale a C.
Soluzione
#include <stdio.h>
#include <string.h>
typedef struct {
int giorno;
int mese;
int anno;
} data;
typedef struct {
char nome[50];
char cognome[50];
data d_nascita;
char l_nascita[50];
char indirizzo[80];
char CF[16];
} elemento;
void stampael(elemento e);
void main()
{
FILE *f;
elemento e;
char C[50];
int k=0;
printf("Inserire il cognome da ricercare: ");
scanf("%s", C);
f=fopen("anagrafe", "rb"); /* apertura in lettura - modalità binaria */
if (f == NULL) printf("Impossibile aprire il file");
else {
while(fread(&e, sizeof(elemento), 1,f)>0)
if (!strcmp(e.cognome, C))
{
stampael(e);
k++;
}
printf("\n\nCi sono %d cittadini con il cognome \"%s\".\n",k, C);
if (fclose(f) !=0) printf("Errore nell'apertura del file");
}
}
void stampael(elemento e)
{
printf("%s\t", e.nome);
printf("%s\t", e.cognome);
printf("%d/%d/%d\t",
e.d_nascita.giorno,
e.d_nascita.mese,
e.d_nascita.anno);
printf("%s\t",e.l_nascita);
printf("%s\t", e.indirizzo);
printf("%s\n", e.CF);
}
Esercizio 4 File: esercizio sull’apertura dei file in modalità append
Scrivere un programma che legga da un file di testo ("cd.txt") dei record (definiti oltre) relativi a
CD e aggiunga in coda al file "usa.txt" i record relativi ai CD di provenienza americana.
I record sono memorizzati nel file per righe nel modo che segue:
123 20.4 ITA
419 33.1 USA
111 12.5 FRA
Il primo numero rappresenta il codice del CD, il secondo numero il suo costo e la stringa
rappresenta la sigla del paese di provenienza. Le sigle possibili sono: “ITA","USA","ENG","FRA".
Per operare il confronto tra stringhe si usi la funzione di libreria strcmp (la cui dichiarazione si trova
in string.h).
Soluzione
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int codice;
float costo;
char sigla[4];
} compactdisk;
void main() {
compactdisk cd;
FILE *fp1,*fp2;
float costo_tot=0;
if ((fp1=fopen("cd.txt","r")) == NULL) printf("Errore nell'apertura file cd.txt");
else if ((fp2=fopen("usa.txt","a")) == NULL) {
fclose(fp1);
printf("Errore nell'apertura del file usa.txt");
}
else { /* ambedue i file sono aperti correttamente */
while (fscanf(fp1,"%d%f%s",&cd.codice,&cd.costo,cd.sigla)> 0)
if (strcmp(cd.sigla,"USA")==0) {
fprintf(fp2,"%d %f %s\n",cd.codice,cd.costo,cd.sigla);
costo_tot += cd.costo;
}
printf("\nIl costo totale e' %f",costo_tot);
if (fclose(fp1)!= 0 || fclose(fp2) !=0) printf("Errore nella chiusura dei file");
}
}