Domanda Risolto allocazione dinamica con struct in un sottoprogramma

gius1805

Utente Bronze
13 Novembre 2020
42
22
0
38
Ciao a tutti,
Ho un problema con questa consegna.
Si definisca un tipo di dato strutturato libro_t per la rappresentazione di un libro in termini di codice numerico identificativo, titolo (una stringa di al più 50 caratteri), autore (una stringa di al più 50 caratteri) ed un prezzo (un valore intero per semplicità). Si definisca in seguito un altro tipo di dato strutturato libreria_t in grado di contenere le informazioni di un insieme dei libri presenti in una libreria, supponendo che essa possa contenere al massimo 100 libri. Si scriva un sottoprogramma che riceve in ingresso un array di librerie, un intero p e qualsiasi altro parametro ritenuto necessario. Il sottoprogramma restituisce un array allocato dinamicamente della dimensione strettamente necessaria per contenere tutti i dati dei soli libri con prezzo minore di p e popolato con i dati di tali libri. Nel caso l'elenco dei libri individuato sia vuoto o nel caso di errore di allocazione della memoria il sottoprogramma deve restituire NULL.

C:
#define MAX 50
#define MAX_L 100

typedef struct{
    int codice;
    char titolo[MAX];
    char autore[MAX];
    int prezzo;
}libro_t;

typedef struct{
    libro_t inf_libri[MAX_L];
}libreria_t;

libreria_t* (libreria_t array[], int p){
    int i, j, cont;
    libreria_t *pf;
    for(i=0, cont=0; i<MAX_L; i++){
        if(array[i].inf_libri.prezzo<p)
            cont++;
    }
    if(cont>0){
        pf=malloc(sizeof(libreria_t)*cont);
        if(pf){
            for(i=0, j=0; i<MAX_L;i++){
                if(array[i].inf_libri.prezzo<p){
                    (*(pf+j)).inf_libri.codice= array[i].inf_libri.codice;
                    strcpy((pf+j).inf_libri.titolo, array[i].inf_libri.titolo);
                    strcpy((pf+j).inf_libri.autore, array[i].inf_libri.autore);
                    (*(pf+j)).inf_libri.prezzo= array[i].inf_libri.prezzo;
                    j++;
                }
            }
        return pf;   
        }
        else
           return NULL;
    }
    else
        return NULL;
}
Il mio dubbio più grande è questo:
C:
 for(i=0, j=0; i<MAX_L;i++){
                if(array[i].inf_libri.prezzo<p){
                    (*(pf+j)).inf_libri.codice= array[i].inf_libri.codice;
                    strcpy((pf+j).inf_libri.titolo, array[i].inf_libri.titolo);
                    strcpy((pf+j).inf_libri.autore, array[i].inf_libri.autore);
                    (*(pf+j)).inf_libri.prezzo= array[i].inf_libri.prezzo;
                    j++;
                }
            }
Non so se è giusto anche se lo dubito fortemente. Qualcuno potrebbe consigliarmi come correggerlo?
Grazie in anticipo.
 
Il problema non si trova solo su quella parte, te ne illustro alcuni:
  1. Hai omesso il nome della funzione
  2. Se vuoi accedere ai membri del singolo libro contenuto nella libreria non puoi usare array[i].inf_libri.prezzo ma dovrai usare array->inf_libri[i].prezzo (la -> si usa per accedere all'elemento nel caso si stia utilizzando un puntatore).
  3. Quì pf=malloc(sizeof(libreria_t)*cont); stai allocando un array di puntatori su delle librerie, mentre quello che tu vuoi fare è allocare un array di libri, quindi pf = malloc(sizeof(libri_t) * cont); in fine dovrai tramutare il puntatore su questo array in una libreria.
  4. Non è un errore ma per una questione di leggibilità puoi abbreviare (*(pf + j)) in pf[j] (però è scorretto il motodo in cui ti stai iterando su quell'array).
In fine ho scritto una versione funzionante del codice (che attualmente non pubblicherò perchè è un esercizio) e mi pare proprio che nel primo ciclo for per vedere quanti libri hanno il costo inferiore hai confuso il segno di minore con maggiore.
 
  • Mi piace
Reazioni: 0xbro
C:
#define MAX 50
#define MAX_L 100

typedef struct{
    int codice;
    char titolo[MAX];
    char autore[MAX];
    int prezzo;
}libro_t;

typedef struct{
    libro_t inf_libri[MAX_L];
}libreria_t;

libro_t sottoprogramma(libreria_t array[], int p){
    int i, j, cont;
    libro_t *pf;
    for(i=0, cont=0; i<MAX_L; i++){
        if(array->inf_libri[i].prezzo<p)
            cont++;
    }
    if(cont>0){
        pf=malloc(sizeof(libro_t)*cont);
        if(pf){
            for(i=0, j=0; i<MAX_L && j<cont ;i++){
                if(array->inf_libri[i].prezzo<p){
                    (pf+j)->codice = array->inf_libri[i].codice;
                    strcpy((pf+i)->titolo, array->inf_libri[i].titolo);
                    strcpy((pf+i)->autore, array->inf_libri[i].autore);
                     (pf+j)->prezzo = array->inf_libri[i].prezzo;
                    j++;
                }
            }
        return pf;   
        }
        else
           return NULL;
    }
    else
        return NULL;
}
 
Quando pubblichi il codice illustra il problema che stai riscontrando, comunque, riguardo al discorso del maggiore o minore a meno che tu non lo abbia cambiato (oppure una mia svista? d’altronde sulla mia soluzione ho usato proprio .prezzo < p) fatto sta che è corretto così come lo hai messo.

Rileggendo la consegna ed il tuo codice, la funzione riceve un array di librerie, però nel primo codice che hai pubblicato ti iteravi solo sulle librerie e quindi ho erroneamente pensato che volessi iterarti solo sui libri di una singola libreria (che può essere considerato come un primo passo :rofl:), quindi per l'esattezza, mi confermi che il tuo codice dovrebbe scrutare TUTTI i libri contenuti in TUTTE le librerie e poi creare un array delle dimensioni esatte per contenere tutti i libri il cui costo è inferiore a p? se è cosi nei cicli for dovrai usare 2 variabili per iterarti su tutti i libri, qualcosa di questo tipo:
C:
    for (int y = 0; y < dimensioni_di_array; y++)
        for (int x = 0; x < MAX_L; x++)
            if (array[y].inf_libri[x].prezzo < p)
                cont++;
Pro tip: al posto di incrementare la variabile cont potresti salvarti la posizione x ed y in modo da tener traccia di quanti libri soddisfano la condizione prezzo < p.
 
Quando pubblichi il codice illustra il problema che stai riscontrando, comunque, riguardo al discorso del maggiore o minore a meno che tu non lo abbia cambiato (oppure una mia svista? d’altronde sulla mia soluzione ho usato proprio .prezzo < p) fatto sta che è corretto così come lo hai messo.

Rileggendo la consegna ed il tuo codice, la funzione riceve un array di librerie, però nel primo codice che hai pubblicato ti iteravi solo sulle librerie e quindi ho erroneamente pensato che volessi iterarti solo sui libri di una singola libreria (che può essere considerato come un primo passo :rofl:), quindi per l'esattezza, mi confermi che il tuo codice dovrebbe scrutare TUTTI i libri contenuti in TUTTE le librerie e poi creare un array delle dimensioni esatte per contenere tutti i libri il cui costo è inferiore a p? se è cosi nei cicli for dovrai usare 2 variabili per iterarti su tutti i libri, qualcosa di questo tipo:
C:
    for (int y = 0; y < dimensioni_di_array; y++)
        for (int x = 0; x < MAX_L; x++)
            if (array[y].inf_libri[x].prezzo < p)
                cont++;
Pro tip: al posto di incrementare la variabile cont potresti salvarti la posizione x ed y in modo da tener traccia di quanti libri soddisfano la condizione prezzo < p.
Ho effettuato le correzioni che hai detto
C:
libro_t sottoprogramma(libreria_t array[], int p, int dim_array){
    int i, j, m, cont, coord[MAX_L][1];
    libro_t *pf;

    for(i=0, m=0; i<dim_array; i++){
        for (j=0; j<MAX_L; j++){
            if (array[i].inf_libri[j].prezzo < p){
                coord[m][0]=i;
                coord[m][1]=j;
                m++;
            }
            
        }
    }
    if(m!=0){
        pf=malloc(sizeof(libro_t)*m);
        if(pf){
            for(i=0; i<m; i++){
                (pf+i)->codice = array[coord[i][0]].inf_libri[coord[i][1]].codice;
                strcpy((pf+i)->titolo, array[coord[i][0]].inf_libri[coord[i][1]].titolo);
                strcpy((pf+i)->autore, array[coord[i][0]].inf_libri[coord[i][1]].autore);
                (pf+i)->prezzo = array[coord[i][0]].inf_libri[coord[i][1]].prezzo;
                }           
        return pf;   
        }
        else
           return NULL;
    }
    else
        return NULL;
}
Per quanto riguarda
C:
.prezzo<p
. Inizialmente, quando ho pubblicato il codice era
C:
.prezzo>p
ma prima che tu inviassi il primo commento mi sono accorto dell'errore e l'ho corretto quindi si vede che avevi iniziato a correggere gli errori del codice prima che io cambiassi il maggiore con il minore.
 
Non hai risposto alla mia domanda, ma siccome hai modificato il codice in modo da gestirlo come un array bidimensionale suppongo che la risposta sia si.

La consegna non forza il fatto che la funzione debba ritornare una libreria, sennò avresti anche dei problemi nel caso i libri da copiare siano più di 100, quindi è corretta la tua idea di far ritornare un puntatore su un array di libri, per l'esattezza nel tuo codice manca l'* sul valore di ritorno, perchè così come lo hai scritto, ritorna un libro.

Ed attualmente lascia stare l'idea di salvare le posizioni dei libri nelle librerie perchè potresti trovare l'implementazione al quanto astrusa dato che stai utilizzando il C, quindi usiamo lo stesso meccanismo che hai impiegato nelle soluzioni precenti (ovvero quello di ricercare i libri molteplici volte nell'array).

Il ciclo for che hai scritto per ottenere le dimensioni dell'array allocato dinamicamente:
C:
    int i, j, m, cont, coord[MAX_L][1];
    libro_t* pf;

    for (i = 0, m = 0; i < dim_array; i++)
    {
        for (j = 0; j < MAX_L; j++)
        {
            if (array[i].inf_libri[j].prezzo < p)
            {
                coord[m][0] = i;
                coord[m][1] = j;
                m++;
            }

        }
    }

Lo semplifichi rimuovendo l'uso della variabile m, in questo modo:
C:
int i, j, cont;
    libro_t* pf;

    for (i = 0, cont = 0; i < dim_array; i++)
        for (j = 0; j < MAX_L; j++)
            if (array[i].inf_libri[j].prezzo < p)
                cont++;

Dopo averne ottenuto le dimensioni andrai ad allocare l'array, verificare che l'allocazione sia riuscita e da li dovrai copiare i libri che soddisfano la condizione prezzo < p da un array bidimensionale ad un array monodimensionale.

Da quì dovresti andare da solo, nel caso tu non abbia idea di come gestire la fase di spostamento tra i due array ti lascio un piccolo esempio (anche se penso sia superfluo):
C:
#include <stdio.h>

int main()
{
    int bidi[3][3] = {
    { 9, 9, 2 },
    { 1, 3, 9 },
    { 9, 9, 2 }};

    int mono[3 * 3] = { 0 };

    // Mettiamo caso di voler salvare nell'array
    // monodimensionale solo i valori inferiori a 5
    int i = 0;
    for (int y = 0; y < 3; y++)
        for (int x = 0; x < 3; x++)
            if (bidi[y][x] < 5)
            {
                mono[i] = bidi[y][x];
                i++;
            }

    // Qui decremento la i perchè ora sta puntando
    // su un elemento nuovo
    i--;

    // Ora mostraimo a schermo i valori copiati
    // nell'array monodimensionale
    for (; i >= 0; i--)
        printf("%d\n", mono[i]);
}
 
  • Mi piace
Reazioni: gius1805