Problema interessante con strutture

di il
45 risposte

Problema interessante con strutture

Salve a tutti
sto scrivendo una funzione di lettura file che prenda un record da disco e lo depositi, con le dovute conversioni, in una struttura.
fin qui nulla di complicato se volessi fare una funzione specifica con una struct ben precisa.
ma siccome vorrei farla più generica possibile mi chiedevo:
1) c'è un modo per capire se la struttura e NULL?
2) c'è un sistema per capire quali siano i campi della struttura che bisogna riempire cosi da verificare che il file sia corretto?

il prototipo della funzione è int leggi_file(handle hfile,int tipo_file,char*buffer,int lrecord,struct *files);
adesso per tipo_file = 0 non c'è bisogno della struttura quindi *files=NULL
per valori diversi di tipo_file avrò una struttura diversa che non so come individuare.
non so se vi può essere d'aiuto ma i byte iniziali dei file che hanno tipo_file <> 0 sono i seguenti:
1 char riconoscimento
1 char separatore
int primo_record da gestire
1 char separatore
int lunghezza del record
1 char terminatore
ringrazio anticipatamente chiunque mi dia un idea su come risolvere il problema.

45 Risposte

  • Re: Problema interessante con strutture

    smalldragon ha scritto:


    1) c'è un modo per capire se la struttura e NULL?
    Che vuol dire? Non si può rispondere, questa domanda non è chiara...
    2) c'è un sistema per capire quali siano i campi della struttura che bisogna riempire cosi da verificare che il file sia corretto?
    Direi di no ma anche questa domanda non è chiara...

    Devi spiegare meglio la questione...

    In generale la lettura avviene come flusso di byte e il programma decide dove devono essere inseriti.
  • Re: Problema interessante con strutture

     int leggi_file(handle hfile, int tipo_file, char*buffer ,int lrecord, struct *files);
    Non è chiarissimo il problema, ma mi pare di comprendere che il discriminante della struct da utilizzare è tipo_file. Se è così ti basta discernere i vari tipo_file e riempirai la struct in maniera opportuna, passa void *files anzichè struct * files e all'interno della funzione fai gli opportuni cast.
  • Re: Problema interessante con strutture

    Grazie per le risposte
    l'idea dei cast non è da scartare anche se il problema non sarebbe risolto in quanto avrei delle struct fisse per ogni tipo di file che potrebbero generare degli errori.
    cercherò di far capire meglio il problema con un esempio.
    record letto: tipo file 1 = lista a 1 link
    l123:xxxxxxxx:20160317:yyyyyy;
    record letto: tipo file 2 = albero binario o lista a 2 link
    l123:l125:xxxxxxxx:20160317:yyyyyy;
    record letto: tipo file 3 = albero non binario
    l123:l125:l144:xxxxxxxx:20160317:yyyyyy;
    adesso se gli passo alla funzione come tipo_file = 1 ma il file e di tipo 3 il programma dovrebbe andarmi in errore.
    altro problema e che anche se uno fa la giusta associazione tra tipo_file e file le strutture possono essere diverse e in questo caso i dati si dovrebbero mettere a seconda della struct che viene passata.
    l123:xxxxxxxx:20160317:yyyyyy; è equivalente a 20160317:l123:xxxxxxxx:yyyyyy; esempio per il tipo 1
    l123:l125:xxxxxxxx:20160317:yyyyyy; è equivalente a l123:xxxxxxxx:20160317:yyyyyy:l125; esempio per il tipo 2
    adesso la soluzione ideale sarebbe quella di poter "scrutare" la struct che viene passata e confrontarla con quella dei dati del file per poter prendere la decisione più consona.
    ma non ho idea sul come fare!
    spero che adesso si capisca meglio il problema
  • Re: Problema interessante con strutture

    Non sono sicuro di aver capito bene il problema quindi spero di non dire stupidaggini.
    Supponendo che i dati nel file siano organizzati con campi a posizioni fisse, con un numero limitato di formattazioni possibili, puoi leggere la riga in un buffer temporaneo e poi con una serie di puntatori a strutture provare ad assegnare il puntatore al buffer direttamente ai vari puntatori a struttura.
    Attenzione però a considerare l'allineamento delle strutture.
  • Re: Problema interessante con strutture

    smalldragon ha scritto:


    salve a tutti
    sto scrivendo una funzione di lettura file che prenda un record da disco e lo depositi, con le dovute conversioni, in una struttura.
    fin qui nulla di complicato se volessi fare una funzione specifica con una struct ben precisa.
    ma siccome vorrei farla più generica possibile mi chiedevo:
    1) c'è un modo per capire se la struttura e NULL?
    2) c'è un sistema per capire quali siano i campi della struttura che bisogna riempire cosi da verificare che il file sia corretto?

    il prototipo della funzione è int leggi_file(handle hfile,int tipo_file,char*buffer,int lrecord,struct *files);
    adesso per tipo_file = 0 non c'è bisogno della struttura quindi *files=NULL
    per valori diversi di tipo_file avrò una struttura diversa che non so come individuare.
    non so se vi può essere d'aiuto ma i byte iniziali dei file che hanno tipo_file <> 0 sono i seguenti:
    1 char riconoscimento
    1 char separatore
    int primo_record da gestire
    1 char separatore
    int lunghezza del record
    1 char terminatore
    ringrazio anticipatamente chiunque mi dia un idea su come risolvere il problema.
    Ni.

    Quello che ti servirebbe, e che e' disponibile in linguaggi tipo Java e C# (ed altri, ovviamente) e' il supporto al reflection, cioe' alla possibilita', appunto, di conoscere come e' fatta una struttura (o una classe) direttamente da codice.

    In alternatica, supportato anche dal C++, si puo' utilizzare il concetto di serializzabile[/b]. E la serializzazione potrebbe essere fatta in binario, XML, Json, ecc.

    In ogni caso ti scontri con problemi fondamentali, che alcuni sistemi di serializzazione supportano meglio di altri:

    1) che succede se la struttura serializzata viene modificata aggiungendo o togliendo campi?

    2) che succede se la struttura contiene un puntatore e quest'ultima, a sua volta, un'altro puntatore e che, alla fine, ritorna alla struttura iniziale? Cioe' se la struttura da serializzare e' un generico grafo? Ma anche se fosse un grafo diretto aciclico il problema non scompare.

    se non sai che cosa e' un grafo o un grafo diretto aciclico, o un albero (in teoria de grafi, ovviamente ), ebbene, e' il momento di studiare

    Nativamente il C++ non supporta il reflection.

    Ma in realta' esiste, perche' e' utilizzato dal debugger.

    Quello che dovresti fare (fattibile anche se per niente semplice) e' quello di sfruttare le informazioni di debug per navigare la struttura dati.

    E qui' ti scontri con la difficolta' di ricuperare le informazioni ma, sopprattutto, di capirle

    Cerca con Google: ci sono diversi progetti interessanti, anche una proposta per aggiungerlo al C++17.

    Guarda anche Boost (http://www.boost.org)
  • Re: Problema interessante con strutture

     int leggi_file(handle hfile, int tipo_file, char*buffer ,int lrecord, void *files){
    			switch(tipo_file) // Piu tutti gli eventuali controlli
    			/*tipo 1*/
    			files=(struct tipo1*)malloc(...)
    			/* leggo il record e controllo che sia idoneo al formato struct tipo1 */
    			buffer=lettura_rigaFile....
    			/* Altrimenti esco con errore*/
    			
    			/*tipo 2*/
    			....
    
    Dovrebbe essere più semplice di quanto descritto. Se non vuoi utilizzare n struct tipo diverse puoi utilizzare un'unica union.
    L'errore eventuale di formato lo riscontri in fase di lettura, sarà lì che dirai posso immagazzinare questi file nella struct opportuna oppure c'è un errore.
    A quel punto devi gestire l'errore, vale a dire: è un solo record del file ad avere formato diverso? Lo scarto oppure fallisce la lettura di tutto il file? ecc...
  • Re: Problema interessante con strutture

    X migliorabile

    migliorabile ha scritto:


    1) che succede se la struttura serializzata viene modificata aggiungendo o togliendo campi?
    non può succedere perchè ogni tipo file può dialogare solo con lo stesso tipo file che avrà o la stessa struttura o una struttura compatibile.
    e una volta creato il file la struttura resta fissa.

    migliorabile ha scritto:


    2) che succede se la struttura contiene un puntatore e quest'ultima, a sua volta, un'altro puntatore e che, alla fine, ritorna alla struttura iniziale? Cioe' se la struttura da serializzare e' un generico grafo? Ma anche se fosse un grafo diretto aciclico il problema non scompare.
    neanche questo può succedere perchè i file avranno solo puntatori ad altri record e nel caso in cui si voglia andare oltre il limite dei 2.147.483.647 cambierà il precodice alfanumerico che corrisponderà ad un altro file.
    nei primi byte del file sarà posto il nuovo codice alfanumerico con il nome e il percorso del nuovo file da gestire che avrà una struttura compatibile con il vecchio file.
    ma credo che un caso del genere sia di raro uso.

    migliorabile ha scritto:


    Ma in realta' esiste, perche' e' utilizzato dal debugger.

    Quello che dovresti fare (fattibile anche se per niente semplice) e' quello di sfruttare le informazioni di debug per navigare la struttura dati.

    E qui' ti scontri con la difficolta' di ricuperare le informazioni ma, sopprattutto, di capirle

    se mi fornisci qualche link che tratta l'argomento sarei ben contento di approfondire l'argomento.
  • Re: Problema interessante con strutture

    candaluar ha scritto:


    Non sono sicuro di aver capito bene il problema quindi spero di non dire stupidaggini.
    Supponendo che i dati nel file siano organizzati con campi a posizioni fisse, con un numero limitato di formattazioni possibili, puoi leggere la riga in un buffer temporaneo e poi con una serie di puntatori a strutture provare ad assegnare il puntatore al buffer direttamente ai vari puntatori a struttura.
    Attenzione però a considerare l'allineamento delle strutture.
    i dati nel file hanno un carattere terminale per ogni campo al fine di poter dedurre dimensioni e tipo di ogni singolo campo e quindi la struttura.
    il problema consiste nel capire se la struttura passata alla funzione sia compatibile con quella ricavata dal record del file letto.
    se si immettere il record letto nella struttura passata alla funzione altrimenti bisogna segnalare che c'è una incompatibilità tra le 2 strutture.
  • Re: Problema interessante con strutture

    Non hai chiarito le domande (anzi le hai completamente ignorate) ma non fa niente ...

    Se nel file non ci sono elementi che possono far riconoscere una struttura (ovvero se parliamo di file binari generici, senza marcatori tra i dati), è impossibile controllare che siano compatibili con qualunque struttura ... quindi si perde solo tempo ...
  • Re: Problema interessante con strutture

    SVNiko ha scritto:


     int leggi_file(handle hfile, int tipo_file, char*buffer ,int lrecord, void *files){
    			switch(tipo_file) // Piu tutti gli eventuali controlli
    			/*tipo 1*/
    			files=(struct tipo1*)malloc(...)
    			/* leggo il record e controllo che sia idoneo al formato struct tipo1 */
    			buffer=lettura_rigaFile....
    			/* Altrimenti esco con errore*/
    			
    			/*tipo 2*/
    			....
    
    Dovrebbe essere più semplice di quanto descritto. Se non vuoi utilizzare n struct tipo diverse puoi utilizzare un'unica union.
    L'errore eventuale di formato lo riscontri in fase di lettura, sarà lì che dirai posso immagazzinare questi file nella struct opportuna oppure c'è un errore.
    A quel punto devi gestire l'errore, vale a dire: è un solo record del file ad avere formato diverso? Lo scarto oppure fallisce la lettura di tutto il file? ecc...
    purtroppo non lo è perchè col tuo metodo, se ho capito bene, si determina la struttura del record letto ma non la struttura che la funzione ha come parametro.
    inoltre, se ho capito bene, per ogni tipo file ci sono da verificare tutte le possibili strutture compatibili il che non è molto pratico.
    comunque resterebbe il problema di capire quale struttura ti è stata passata come parametro.
  • Re: Problema interessante con strutture

    Forse non mi è chiaro il problema.
    Se riuscissi ad esplicitarlo con più chiarezza, te ne sono grato e felice di apportare un contributo alla soluzione del problema.
  • Re: Problema interessante con strutture

    oregon ha scritto:


    Non hai chiarito le domande (anzi le hai completamente ignorate) ma non fa niente ...

    Se nel file non ci sono elementi che possono far riconoscere una struttura (ovvero se parliamo di file binari generici, senza marcatori tra i dati), è impossibile controllare che siano compatibili con qualunque struttura ... quindi si perde solo tempo ...
    tipo_file = 0
    il file binario verrebbe trattato come un file sequenziale visto che non ha i link hai record e quindi la struttura che verrebbe passata non verrebbe presa in considerazione.
    nel caso in cui tipo file <> 0 e il file e binario verrebbe visualizzato l'errore file incompatibile con la struttura.
  • Re: Problema interessante con strutture

    No ... non è chiaro ...

    Che sono "i link ai record" ?

    Dobbiamo usare terminologia chiara, altrimenti non ci capiamo.

    E poi non era questo il problema. Ti stavo dicendo che, nel caso di un file binario, non hai modo di capire a quale struttura si riferiscono i dati se non sono marcati in modo chiaro (con CRC, marcatori e altro).
  • Re: Problema interessante con strutture

    smalldragon ha scritto:


    il problema consiste nel capire se la struttura passata alla funzione sia compatibile con quella ricavata dal record del file letto.
    Dando momentaneamente per scontata l'integrità e l'organizzazione dei dati nei file di cui si discute, tale problema (determinazione automatica a runtime di tipo e dimensione di una variabile o aggregato di variabili) non ammette soluzione in linguaggio C, e per la cronaca neppure in subset del C++ come EC++ che non supportano l'onerosa RTTI e funzioni annesse. Anche l'idea di sfruttare le eventuali informazioni di debug è inerentemente poco praticabile, sia pure in un'applicazione strettamente per uso personale.

    L'unico approccio ingegneristicamente coerente al problema consiste nel ricorso alla memorizzazione esplicita di informazioni aggiuntive sull'aggregato (struct), codificando in modo intelligente il numero, la posizione e il tipo dei campi, ossia in ultima analisi il formato del record: il che ne consente, con ogni evidenza, una immediata convalida diretta a runtime rispetto alla medesima codifica (letta da file o calcolata al volo) del tipo record presente nel file.
Devi accedere o registrarti per scrivere nel forum
45 risposte