svolc2000-07-10.c

Generated by com.bluecraft.htmlize HTML-ization Utility Classes.
/* 
 * Svolgimento problema di esame del 10/7/2000
 *      (Il file sulle opere d'arte va costruito separatamente, tramite un editor) 
 *
 *      
 *
 * Il programma che segue è stato sviluppato dando particolare enfasi 
 * ai criteri per la progettazione di "buon software", quali ad esempio
 * costruzione top-down, decomposizione funzionale, uso di 
 * tipi di dato efficaci e descrittivi. 
 *
 * La soluzione proposta fa uso di array dinamici. Nella soluzione il
 * docente ha inserito vari aspetti avanzati del C (pur rimanendo nell'ambito
 * degli argomenti in programma). Si tratta dunque di un (raro) esempio di 
 *
 *                        SOLUZIONE AVANZATA
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LUNAUT 16
#define LUNOP 11
#define LUNNOMEFILE 30

typedef unsigned short int ushort;

typedef struct {
    char autore[LUNAUT],
         opera[LUNOP],
         tipoopera;
    float europrezzo;
} schedaopera;

typedef struct {
    ushort dimarray;
    schedaopera *punarray;
} arraydinamicodiopere;

/* prototipi */
    FILE *ApriFile(char *, char *);
    void *Alloca(size_t);
    void *Realloca(void *, size_t);
    void MaxTest(float , float *, ushort *);
    void TrovaMaxPrezzi(FILE *, float *, float *, ushort *, ushort *);
    void RaccogliOpereCare(schedaopera, float, schedaopera *, ushort *);
    void OpereCare(char *, arraydinamicodiopere *, arraydinamicodiopere *);
    void StampaArrayOpere(arraydinamicodiopere);
    float ValoreMassimo(char *);
    int main(void);


FILE *ApriFile(char *nome, char *modo)
{
    FILE *f;
    
    f=fopen(nome, modo);
    if(f==NULL) {
        fprintf(stderr, "Impossibile aprire \"%s\" in modalità \"%s\". Programma terminato.\n", nome, modo);
        exit(1);
    }
    return f;
}


void *Alloca(size_t numbyte)
{
    void *p;
    
    p=malloc(numbyte);
    if(p==NULL) {
        fprintf(stderr, "Impossibile allocare %lu byte. Programma terminato.\n", numbyte);
        exit(2);
    }
    return p;
}


void *Realloca(void *punblocco, size_t numbyte)
/* 
 * Viene fatto uso della funzione di libreria ANSI realloc(void *punblocco, size_t numbyte).
 * La funzione modifica la dimensione del blocco di memoria puntato da punblocco in modo
 * da ottenere un blocco di numbyte byte, valore che può essere inferiore o superiore alla
 * dimensione corrente del blocco. Il parametro punblocco deve puntare ad un blocco precedentemente
 * allocato con malloc(), realloc() o altre funzioni similari. Se numbyte è zero il blocco
 * puntato da punblocco viene deallocato. Se punblocco è NULL realloc() alloca numbyte byte.
 * Il contenuto del blocco di memoria viene preservato se il nuovo blocco è più grande del
 * precedente. Se il nuovo blocco è più piccolo i byte finali extra vengono tagliati via.
 * realloc() restituisce un puntatore al nuovo blocco se l'allocazione ha successo e se numbyte
 * è maggiore di zero; in caso di insuccesso o numbyte nullo restituisce NULL
 */
{
    void *p;
    
    p=realloc(punblocco,numbyte);
    if(p==NULL) {
        fprintf(stderr, "Impossibile reallocare %lu byte. Programma terminato.\n", numbyte);
        exit(2);
    }
    return p;
}


void MaxTest(float prezzo, float *maxprezzo, ushort *contamaxprezzo)
{
    if(prezzo > *maxprezzo) {
        *maxprezzo = prezzo;
        *contamaxprezzo = 1;
    } else if (prezzo == *maxprezzo)
        (*contamaxprezzo)++;
    return;
}


void TrovaMaxPrezzi(FILE *f, float *maxprezzoquadri, float *maxprezzosculture, ushort *contaquadrimaxprezzo, ushort *contasculturemaxprezzo)
{
    schedaopera opera;
    
    *maxprezzoquadri = *maxprezzosculture = 0;
    *contaquadrimaxprezzo = *contasculturemaxprezzo = 0;
    fscanf(f, "%s %s %c %g ", opera.autore, opera.opera, &opera.tipoopera, &opera.europrezzo);
    while(!feof(f)) {
        switch(opera.tipoopera) {
            case 'Q': MaxTest(opera.europrezzo, maxprezzoquadri, contaquadrimaxprezzo);
                      break;
            case 'S': MaxTest(opera.europrezzo, maxprezzosculture, contasculturemaxprezzo);
                      break;
            default : printf("Tipo di opera non riconosciuto.\n"); 
                      break;
        }
        fscanf(f, "%s %s %c %g ", opera.autore, opera.opera, &opera.tipoopera, &opera.europrezzo);
    }
   return;
}


void RaccogliOpereCare(schedaopera opera, float maxprezzo, schedaopera *cellaarray, ushort *i)
{
    if(opera.europrezzo == maxprezzo) {
        *cellaarray = opera; 
        (*i)++;
    }
    return;
}



void OpereCare(char *nomefile, arraydinamicodiopere *quadricari, arraydinamicodiopere *sculturecare)
/* Funzione richiesta al p.to 2 */
{
    float maxprezzoquadri, maxprezzosculture;
    FILE *f;
    schedaopera opera;
    ushort contaquadrimaxprezzo, contasculturemaxprezzo, q, s;
    
    f=ApriFile(nomefile, "r");
    TrovaMaxPrezzi(f, &maxprezzoquadri, &maxprezzosculture, &contaquadrimaxprezzo, &contasculturemaxprezzo);
    
    quadricari->dimarray=contaquadrimaxprezzo;
    quadricari->punarray=Alloca(contaquadrimaxprezzo*sizeof(schedaopera));
   
    sculturecare->dimarray=contasculturemaxprezzo;
    sculturecare->punarray=Alloca(contasculturemaxprezzo*sizeof(schedaopera));
    
    q = s = 0;
    rewind(f);
    fscanf(f, "%s %s %c %g ", opera.autore, opera.opera, &opera.tipoopera, &opera.europrezzo);
    while(!feof(f)) {
        switch(opera.tipoopera) {
            case 'Q': RaccogliOpereCare(opera, maxprezzoquadri, &((quadricari->punarray)[q]), &q);
                      break;
            case 'S': RaccogliOpereCare(opera, maxprezzosculture, &((sculturecare->punarray)[s]), &s);
                      break;
            default : printf("Tipo di opera non riconosciuto.\n"); 
                      break;
        }
        fscanf(f, "%s %s %c %g ", opera.autore, opera.opera, &opera.tipoopera, &opera.europrezzo);
    }
    fclose(f);
    return;
}

void StampaArrayOpere(arraydinamicodiopere arr)
{
    ushort i;
    schedaopera *p=arr.punarray;
    
    switch (p[0].tipoopera) {
        case 'Q':
            printf("Stampa di un array di %hu quadri:\n", arr.dimarray);
            break;
        case 'S':
            printf("Stampa di un array di %hu sculture:\n", arr.dimarray);
            break;
        default:
            printf("Tipo di opera non riconosciuto, la stampa non può aver luogo.\n"); 
            return;
    }
    
    printf("----------------------------------------------\n");
    printf("|    Autore     |  Titolo  | Tipo |  Prezzo  |\n");
    printf("|---------------|----------|------|----------|\n");
    for(i=0; i<arr.dimarray; i++)
        printf("|%-*s|%-*s|   %c  |%10g|\n", LUNAUT-1, p[i].autore, LUNOP-1, p[i].opera, p[i].tipoopera, p[i].europrezzo);
    printf("----------------------------------------------\n");
    
    return;
}


/* Visibilità: da qui in poi */

typedef struct {
    char autore[LUNAUT];
    float valoreautore;
} schedaautore;

typedef struct {
    ushort dimarray;
    schedaautore *punarray;
} arraydinamicodiautori;

/* ulteriore prototipo (che fa uso dei tipi testè definiti) */
    int AutorePresente(arraydinamicodiautori, char *, ushort *);

int AutorePresente(arraydinamicodiautori a, char *autore, ushort *i)
/*
 * Restituisce 1 se nell'array dinamico a è già presente una scheda
 * relativa all'autore autore; in tal caso restituisce tramite il
 * parametro di output i la posizione della cella crelativa ad autore.
 * In caso di assenza restituisce 0 (ed il valore di i non è rilevante)
 */
{
    for(*i=0; *i<a.dimarray; (*i)++)
        if(strcmp((a.punarray)[*i].autore, autore) == 0)
            return 1;
    return 0;
}



float ValoreMassimo(char *nomefile)
/* Funzione richiesta al p.to 3 */
{
    arraydinamicodiautori arr;
    ushort dove, i;
    float valmax;
    FILE *f;
    schedaopera opera;
    
    arr.dimarray = 0;
    arr.punarray = NULL;
    f=ApriFile(nomefile, "r");
    fscanf(f, "%s %s %c %g ", opera.autore, opera.opera, &opera.tipoopera, &opera.europrezzo);
    while(!feof(f)) {
        if(AutorePresente(arr, opera.autore, &dove))
            (arr.punarray)[dove].valoreautore += opera.europrezzo;
        else {
            arr.punarray = Realloca(arr.punarray,(arr.dimarray+1)*sizeof(schedaautore));
            strcpy((arr.punarray)[arr.dimarray].autore, opera.autore);
            (arr.punarray)[arr.dimarray].valoreautore = opera.europrezzo;
            arr.dimarray++;
        }
        fscanf(f, "%s %s %c %g ", opera.autore, opera.opera, &opera.tipoopera, &opera.europrezzo);
    }
    fclose(f);
    
    /* Cerca ora il valore massimo */
    valmax = 0;
    for(i=0; i<arr.dimarray; i++)
        if((arr.punarray)[i].valoreautore > valmax)
            valmax = (arr.punarray)[i].valoreautore;
            
    free(arr.punarray);
    
    return valmax;
}
      


int main(void)
{
    /* per array dinamici */
    arraydinamicodiopere quadricari, sculturecare; 
    
    char nomefile[LUNNOMEFILE];
    
    printf("Nome file?\n\t");
    gets(nomefile);
    
    /* chiamata funzione richiesta al p.to 2 */
    OpereCare(nomefile, &quadricari, &sculturecare);
    
    /* stampe di verifica */
    StampaArrayOpere(quadricari);          
    StampaArrayOpere(sculturecare);
    
    free(quadricari.punarray);
    free(sculturecare.punarray);
    
    /* chiamata funzione richiesta al p.to 3, con stampa di verifica */
    printf("Il valore massimo complessivo associato ad un autore è %g.\n", ValoreMassimo(nomefile));
    
    return 0;
}