Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    Apr 2004
    Messaggi
    17

    [C] Perdita di valori in una struttura

    Ciao!!
    Uitlizzo una struttura ("tre") formata da diversi campi:
    indice: lista
    frequenza degli indici: double

    Uso una funzione ricorsiva che mi restituisce il risultato in una variabile di tipo struttura "tre".
    Tale funzione legge da un'altra struttura dati ("tab")raggiungibile tramite puntatori i dati che mi servono.

    Se inizializzo a 0 il campo frequenza (di "tre") tutto funziona,
    ma se inizializzo e poi cambio il valore del campo frequenza (con il valore letto e aggiornato da tab) si perdono tutti i valori.

    Per allocare "tre" utilizzo la malloc

    tat = (TRE*)malloc(sizeof(TATRE) + (n-1) *sizeof(int)
    + n *sizeof(TRE*));

    con n che riporta il numero di volte che devo effettuare la lettura dalla struttura tab (se devo leggere 4 dati da tab, la prima volta varrrà 4 poi 3 fino a 0)o in altri termini quanti dati devo aggiungere a indice.

    Qualcuno mi sa dare un consiglio che riesca a levarmi da questo pasticcio... ???? ....

  2. #2
    Mi piacerebbe aiutarti ma purtroppo non ho capito molto della speigazione del problema,dovresti postare un po più di codice che mi faccia capire ad esempio il lavoro svolto dalla funzione ricorsiva.E poi dovresti cercare di essere più chiaro.Ciao
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  3. #3
    Utente di HTML.it
    Registrato dal
    Apr 2004
    Messaggi
    17
    Ho cercato di semplificare, ma a quanto pare con un pessimo risultato.

    Il problema è che il codice è terribilmente complesso (è l'Apriori quello preso in rete) provo a spiegarmi meglio:

    io ho una serie di dati (tipo tract contenuto in taset) a cui accedo (prima ho detto lista ma non è il termine più appropriato) tramite puntatori ( (*tract)->item[posizione) e cambia da uno all'altro incrementando o decrementando tract
    (*--tract)... oppure utilizzando un indice tract[indice])) (viene passato alla funzione taset->tract)

    poi usa una variabile tat (che è un nodo di tipo tatree)

    recursivamente si costruisce questi nodi.
    In originale prendeva solo i valori presenti in tract.

    Per la mia tesi ho dovuto aggiungere nella struttura taset un campo che semplicemente (anche se il discorso totale è molto più complesso) riporta un numero double (quello che per semplicità ho chiamato frequenza e che nell’allegato invece sarà weight_tran).

    Il problema nasce dal momento in cui cerco di portare tale valore nel nodo:
    eseguendo l’assegnazione tat->weight_tran = com (variabile di comodo che memorizza il valore corretto della frequenza). L’esecuzione continua, ma i risultati sono completamente errati.
    Se io lascio tutto come prima, cioè anche con il calcolo di com, MA NON eseguo più l’assegnazione tat->weight_tran. Tutto funziona ed ottengo i risultati desiderati (ovviamente, a meno del peso!).

    In allegato metto le strutture dati utilizzate e il codice ….

    typedef struct { /* --- a transaction --- */
    double weight_tran; /*peso della transazione*/
    int cnt; /* number of items */
    int items[1]; /* item identifier vector */
    } TRACT;

    typedef struct { /* --- a transaction set --- */
    ITEMSET *itemset; /* underlying item set */
    int max; /* maximum number of items per t.a. */
    int vsz; /* size of transaction vector */
    int cnt; /* number of transactions */
    int total; /* total number of items */
    TRACT **tracts; /* transaction vector */
    } TASET;

    typedef struct _tatree { /* --- a transaction tree (node) --- */
    int cnt; /* number of transactions */
    int max; /* size of largest transaction */
    int size; /* node size (number of children) */
    int items[1]; /* next items in rep. transactions */
    double weight_tran; /*peso delle transazioni*/
    } TATREE;

    TATREE* _create (TRACT **tracts, int cnt, int index)
    { /* --- recursive part of tat_create() */
    int i, k, t; /* loop variables, buffer */
    int item, n; /* item and item counter */
    TATREE *tat; /* created transaction tree */
    TATREE **vec; /* vector of child pointers */


    double weight_com;

    assert(tracts /* check the function arguments */
    && (cnt >= 0) && (index >= 0));
    if (cnt <= 1) { /* if only one transaction left */
    n = (cnt > 0) ? (*tracts)->cnt -index : 0;
    tat = (TATREE*)malloc(sizeof(TATREE) +(n-1) *sizeof(int));
    if (!tat) return NULL; /* create a transaction tree node */
    tat->cnt = cnt; /* and initialize its fields */
    tat->size = -n;
    tat->max = n;
    (*tracts)->weight_tran= weight_com;
    while (--n >= 0) tat->items[n] = (*tracts)->items[index +n];
    return tat;
    }
    for (k = cnt; (--k >= 0) && ((*tracts)->cnt <= index); )
    tracts++; /* skip t.a. that are too short */
    n = 0; item = -1; /* init. item and item counter */
    for (tracts += i = ++k; --i >= 0; ) {
    t = (*--tracts)->items[index]; /* traverse the transactions */
    if (t != item) { item = t; n++; weight_com =(*tracts)->weight_tran;}
    } /* count the different items */

    #ifdef ARCH64 /* adapt to even item number */
    i = (n & 1) ? n : (n+1); /* so that pointer addresses are */
    #else /* multiples of 8 on 64 bit systems */
    i = n; /* on 32 bit systems, however, */
    #endif /* use the exact number of items */
    tat = (TATREE*)malloc(sizeof(TATREE) + (i-1) *sizeof(int)
    + n *sizeof(TATREE*));
    if (!tat) return NULL; /* create a transaction tree node */
    tat->cnt = cnt; /* and initialize its fields */
    tat->size = n;
    tat->max = 0;
    tat->weight_tran=0; //inizializzazione del peso della transazione
    if (n <= 0) return tat; /* if t.a. are fully captured, abort */
    vec = (TATREE**)(tat->items +i);
    item = tracts[--k]->items[index];
    weight_com = tracts[k]->weight_tran;

    for (tracts += i = k; --i >= 0; ) {
    t = (*--tracts)->items[index]; /* traverse the transactions, */
    if (t == item) continue; /* but skip those with the same item */
    tat->items[--n] = item; item = t; weight_com=(*tracts)->weight_tran;
    //tat->weight_tran=weight_com;
    vec[n] = _create(tracts+1, k-i, index+1);
    if (!vec[n]) break; /* note the item identifier */

    t = vec[n]->max +1; if (t > tat->max) tat->max = t;
    k = i; /* recursively create subtrees */
    } /* and adapt the section end index */
    if (i < 0) { /* if child creation was successful */
    tat->items[--n] = item; /* node the last item identifier */
    // tat->weight_tran=weight_com;
    vec[n] = _create(tracts, k+1, index+1);


    if (vec[n]) { /* create the last child */
    t = vec[n]->max +1; if (t > tat->max) tat->max = t;
    return tat; /* return the created */
    } /* transaction tree */
    }
    for (i = tat->size; --i > n; ) tat_delete(vec[i]);
    free(tat); /* on error delete created subtrees */
    return NULL; /* and the transaction tree node */
    } /* _create() */

  4. #4
    codice:
    double weight_com; //<------------ quì
    
    	assert(tracts /* check the function arguments */ & (cnt >= 0) && (index >= 0)); 
    	if (cnt <= 1) 
    	{ /* if only one transaction left */ 
    		n = (cnt > 0) ? (*tracts)->cnt -index : 0; 
    		tat = (TATREE*)malloc(sizeof(TATREE) +(n-1) *sizeof(int)); 
    		if (!tat) 
    			return NULL; /* create a transaction tree node */ 
    		tat->cnt = cnt; /* and initialize its fields */ 
    		tat->size = -n; 
    		tat->max = n; 
    		(*tracts)->weight_tran= weight_com;  /// <------- quì
    		while (--n >= 0) 
    			tat->items[n] = (*tracts)->items[index +n]; 
    		return tat; 
    	}
    Anche così è abbastanza difficile capire perchè le informazioni sono comunque poche, però una cosa strana l'ho notata:

    Nella riga in basso dove ho scritto "quì" fai un'assegnazione con weight_com che è stato dichiarato ma non inizializzato in alcun modo,quindi questo non può voler dire nulla di buono.Se come mi sembra di intuire il valore di (*tracts)->weight_tran lo devi calcolare in base al valore nella chiamata ricorsiva precedente,weight_com deve essere un parametro non una variabile locale.se lo lasci così qualche problema c'è di sicuro anche se non è proprio il tuo problema magari,percheè al momento dell'assegnazione weight_com contiene solo spazzatura.
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  5. #5
    Utente di HTML.it
    Registrato dal
    Apr 2004
    Messaggi
    17
    In effetti quello che mi hai indicato era un errore che purtroppo non ha risolto il probblema...

    Ho pensato ad una cosa...

    colui che ha elaborato il programma di base usa la malloc:

    tat = (TATREE*) malloc (sizeof(TATREE) +(i-1)*sizeof(int)+ n*sizeof (TATREE*))

    io ho aggiunto il campo double weight.

    Quando poi tale struttura viene riutilizzata, ad esempio per la visualizzazione, viene assegnato

    vec = (TATREE**)(tat->items +tat->size);

    Questa funziona nel caso iniziale, cioè senza introduzione del campo weight. Introducendo il campo weight, potrebbe causare uno slittamento? E quindi, non è che perde i valori, bensì non riesce ad allocare la variabile nella locazione corretta.
    Potrebbe essere...????

  6. #6
    codice:
    typedef struct { /* --- a transaction --- */ 
    double weight_tran; /*peso della transazione*/ 
    int cnt; /* number of items */ 
    int items[1]; /* item identifier vector */ 
    } TRACT; 
    
    typedef struct { /* --- a transaction set --- */ 
    ITEMSET *itemset; /* underlying item set */ 
    int max; /* maximum number of items per t.a. */ 
    int vsz; /* size of transaction vector */ 
    int cnt; /* number of transactions */ 
    int total; /* total number of items */ 
    TRACT **tracts; /* transaction vector */ 
    } TASET; 
    
    
    
    void main() 
    { 
    	TRACT *ta; 
    
    
    	taset = (TASET*) malloc (sizeof(TASET)); 
    	taset->tracts = (TRACT**)malloc(sizeof(TRACT)); //-->questo non può essere!
    
    	ta = (TRACT*)malloc(sizeof(TRACT) +(1) *sizeof(int)); //->quì il +1 viene ignorato
    	ta->cnt=2; 
    
    	ta->items[0]=0; 
    	ta->items[1]=1; 
    	ta->weight_tran=4.5; 
    
    	//ogni volta che assegno un valore a ta->weight_tran vengono
    	//modificati alcuni dei valori di tat->items 
    	//(quelli di posizione 1 e 2: sempre gli stessi)
    
    	taset->tracts[0]=ta; 
    
    }
    Credo di aver trovato l'errore,anzi gli errori,te li ho indicati nel codice.
    innanzitutto quest'istruzione va scritta così:

    codice:
    taset->tracts = (TRACT**)malloc(sizeof(TRACT*));
    Cioè con la sizeof devi indicare la dimensione di un puntatore
    a struttura di tipo TRACT non la dimensione di un'intera struttura.

    Inoltre qauesta va scritta così:
    codice:
    ta = (TRACT*)malloc((sizeof(TRACT) + 1) *sizeof(int));
    altrimenti la precedenza dell'operatore * sull'operatore +
    annulla quel + 1 che hai messo.Spero sia quello il problema.
    Comunque la strada per ottenere un aiuto nel caso non sia quello e proprio
    di isolare il problema e postare del codice,(possibilmente già funzionante
    nel senso che si compila) in cui succede la cosa anomala,infatti il codice che hai postato ora non era compilabile,mancavano le definizioni delle strutture e la dichiarazione di TASET oltre a quella di ITEMSET.fammi sapere ciao
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  7. #7
    Utente di HTML.it
    Registrato dal
    Apr 2004
    Messaggi
    17
    Chiedo venia!!!

    In effetti ero convinta di aver postato tutto il programmino...

    tra le cose: il primo errore era solo una dimenticanza di copiatura, mentre il secondo invece si vuole "lasciare lo spazio" di, in questo caso, 2 interi (nel programma principale questo 1 è il risultato di una formula, quindi una volta sarà ad 1*sizeof(int) una'altra 2*sizeof(int) etc...)

    Qui c'è l'intero programmino che compie lo stesso errore del programma originale.

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

    typedef struct {
    int cnt;
    int items[1];
    double weight_tran;
    } TRACT;


    typedef struct {
    int cnt;
    TRACT **tracts;
    } TASET;


    void load(TASET *taset);
    TASET *taset;



    void main()
    {
    TRACT *ta;


    taset = (TASET*) malloc (sizeof(TASET));
    taset->tracts = (TRACT**)malloc(sizeof(TRACT*));

    ta = (TRACT*)malloc(sizeof(TRACT) +(2) *sizeof(int));
    ta->cnt=2;

    ta->items[0]=0; ta->items[1]=1;
    ta->weight_tran=4.5;
    /*ogni volta che assegno un valore a ta->weight_tran vengono modificati alcuni dei valori di tat->items (quelli di posizione 1 e 2: sempre gli stessi)*/

    taset->tracts[0]=ta;


    }

  8. #8
    codice:
    #include <stdio.h> 
    #include <stdlib.h> 
    
    typedef struct { 
    int cnt; 
    int items[1]; 
    double weight_tran; 
    } TRACT; 
    
    
    typedef struct { 
    int cnt; 
    TRACT **tracts; 
    } TASET; 
    
    
    void load(TASET *taset); 
    TASET *taset; 
    
    
    
    void main() 
    { 
    	TRACT *ta; 
    	
    	
    	taset = (TASET*) malloc (sizeof(TASET)); 
    	taset->tracts = (TRACT**)malloc(sizeof(TRACT*)); 
    	
    	ta = (TRACT*)malloc(sizeof(TRACT) +(2) *sizeof(int)); 
    	ta->cnt=2; 
    	
    	ta->items[0]=0; ta->items[1]=3; //--->questo presuppone che items
    	                                 //sia un array di almeno 2 elementi 
    	ta->weight_tran=4.5; 
    	/*ogni volta che assegno un valore a ta->weight_tran 
        vengono modificati alcuni dei valori di tat->items 
        (quelli di posizione 1 e 2: sempre gli stessi)*/ 
    	
    	taset->tracts[0]=ta; 
    	printf("%d,%d",ta->items[0],ta->items[1]);
    }
    Guarda a me il problema sparisce se al campo items della struttura
    TRACT dai almeno una capacità di due elementi.
    In effetti non vedo il motivo di dichiarare un array di un solo elemento
    ,si farebbe prima a dichiarare una variabile intera normale.
    Comunque il problema è quello,tu dove ti ho messo la freccia
    accedi al secondo elemento dell'array items,cioè items[1],però non potresti
    perchè items l'hai dichiarato nella struttura come avente UN SOLO
    elemento.Quindi devi allocare spazio sufficiente nell'array
    semplicemente modificando il numerino tra parentesi quadre nella
    dichiarzione all'interno dell struttura TRACT.Ciao
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  9. #9
    Utente di HTML.it
    Registrato dal
    Apr 2004
    Messaggi
    17
    Certo che il problema sparisce, ma se tu utilizzassi un vettore predefinito (cioè dichiarassi una dimensione fissa per il vettore) sarebbe inutile utilizzare una malloc con parametri (vedi sopra).
    Questo è un trucchetto per poter utilizzare un vettore senza sprecare memoria e senza ricorrere all'uso di liste o alberi.

    Pensa se devi utilizzare un vettore di vettori, cioè in cui ogni posizione è un vettore (che chiameremo vett_int), tu sai a priori che la dimensione massima dio vett_int è di 300 posizioni (quindi bisognerebbe scrivere nella struttura ... int vett_int[300]; ) ma ad ogni posizione (del vettore esterno) utilizzerai un numero diverso ... se tale numero fosse compreso tra 0 e 5 ci sarebbe un po' dispreco...

    Ritornando al problema originale...
    credo che una possibile soluzione al problema potrebbe consistere nel dichiarare un "vettore fittizio" di double:

    double weight_tran[1]

    e un puntatore di interi

    int *items, allocando poi il numero esatto di interi (grazie a i o n).

    Di conseguenza dovrebbe anche cambiare la dichiarazione della variabile tat: dovrebbe esser aggiunta la dichiarazione di spazio allocato per il vettore di double.

    Vi ringrazio comunque dell'interessamento...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.