La lettura di un File in un array di Strutture in C

ancora di veramente nuovo per C, ma iniziando a ottenere il blocco di esso….

Il mio programma è in grado di creare/scrivere un file e memorizzare le informazioni da un array di strutture. Quella parte è bene. Quello che sto avendo problemi con la lettura da file in un array vuoto di strutture….

ecco la mia strutture:

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

#define MAX 100

struct Video { 
char name[1024];                //name
int ranking;                //Number of viewer hits
char url[1024];             //YouTube URL
};

struct Video Collection[MAX];

ecco il mio metodo di caricamento che legge il mio file in mio array di strutture:

void load()
{
FILE *fileName;
fileName = fopen("ranking.dbm", "rb");
if (fileName != NULL){
    fread (Collection,1,1,fileName);
}
else {
    printf("ERROR");
}   

}

anche qui è il mio metodo di scrittura:

void save()
{
FILE * pFile;
pFile = fopen ( "Ranking.dbm" , "wb" );
fwrite (Collection, 1 , sizeof(Collection), pFile );
fclose (pFile); 
}

tuttavia quando si stampa il mio array collection dopo il caricamento…. il suo vuoto… anche se posso vedere il mio file nella cartella del progetto e di aprirlo e verificare che i dati ci sono….

ho corretto pensare che non ho bisogno di un buffer, dal momento che non ho bisogno di fare qualsiasi trattamento su di esso prima di utilizzarlo?

anche perché ho già allocati staticamente spazio per la memoria…. ho corretto pensare che posso leggere direttamente nella matrice?

qui è il mio stampare il codice:

void printall()
{
int i; 

printf("\nCollections: \n"); 

for(i = 0; i < tail; i++)
{
    printf("\nVideo Name: %s", Collection[i].name);
    printf("\nRanking (Hits): %d", Collection[i].ranking);
    printf("\nURL: %s", Collection[i].url);
    printf("\n");
}
}
  • Si potrebbe verificare la fonte? Tra i Video struct e la dichiarazione di Raccolta, credo che qualcosa manca..
  • Non si desidera che il file sia in formato binario o in forma testuale? Non si cura circa la portabilità dei file di dati su architetture diverse?
  • Penso che si desidera definire: struct Video Collection[MAX];
  • P. S. non chiamare la FILE * oggetto fileName, o sarà molto confuse (dato che non è il nome di un file).
  • sì scusa è supposto per essere struct Video Collection[MAX]. modificato il post sopra
  • Cosa tail in printall?
  • tail è un’altra variabile globale che tiene traccia di quante voci sono in collection.
  • guardate come si potrebbe migliorare il vostro programma e sembra più bello : pastie.org/4867286

InformationsquelleAutor accraze | 2012-09-29

 

3 Replies
  1. 2

    Sto vedendo un paio di problemi qui.. per prima cosa, come leggere il file:

    fread (Collection,1,1,fileName); 

    Questo verrà letto in raccolta 1 byte da fileName in Collection

    Si dovrebbe controllare lo stato di ritorno di fread(), quando è successo che ti dice il numero totale di byte da leggere. (parametro 2 * parametro 3, o 1*1 nel tuo caso).

    Quando modifica di leggere un codice come questo:

    fread(Collection, sizeof(struct Video), 1, fileName);

    Non leggere correttamente il file… però hai un problema diverso ora. Diciamo che il tuo file contenuti questo:

    something 5 http://something.com
    nothing 3 http://nothing.com

    Così (credo) che è il formato di un file, un nome (ASCII), una classifica (int) e l’URL (ASCII). Ora supponiamo che il tuo main() funzione guardato come questo:

    int main ()
    {
        load();
        printall();
        return 0;
    }

    A ciò che si desidera ottenere indietro stdout sarebbe qualcosa di simile:

    Collections:
    
    Video Name: something 6 http://something.com
    nothing 3 http://nothing.com
    Ranking (Hits): 0
    URL: 

    Il motivo è perché avete dichiarato la vostra array statici (e molto grande) di elementi. Il fread() prova a leggere nel sizeof(struct Video) che è 1024+4+1024 byte, quindi a meno che non ogni uno delle linee è la dimensione esatta (1024 caratteri per il nome e l’url), allora si sta andando ad ottenere quello che sembra incasinato o di dati vuoto.

    Vorrei suggerire la lettura fino a quando si preme uno spazio, invece, e la memorizzazione di ogni valore l’elemento corretto, invece di cercare di leggere l’intero file in un array.

    EDIT:

    Se si desidera popolare l’array come:

    fread(myarray, sizeofstruct, numberofstructs, file);

    È necessario garantire la lunghezza dei dati. Nel tuo esempio dovresti dire “il nome è tuttavia molti caratteri + spazi vuoti = 1024” e lo stesso per URL. Che sembra essere un orribile spazio perditempo. La scommessa migliore è quello di compilare un array di un solo elemento:

    for(0 to last_element){
      set myarray.name = data until first space
      set myarray.ranking = (int)data until second space
      set myarray.url = data until newline
    }

    È possibile utilizzare fscanf() a leggere fino a uno spazio bianco.
    Sinceramente, se si sta andando per popolare un elemento alla volta mi basta usare i puntatori di carattere per il nome e l’url e di assegnare dinamicamente la memoria, quindi non devi enorme spreco di matrici.

    • grazie per la risposta dettagliata!c’è un modo per strutturare il mio save() metodo per scrivere il file è in un facile leggere il formato? per esempio qualcosa come fwrite (Collection, sizeof(struct YouTubeVideo) , MAX , pFile ); ?
    • E ‘ più il fatto che hai a che fare con formati non strutturati (nome & url), come si sta memorizzando. Vedere la mia modifica e fammi sapere se risponde alle tue domande.
    • impressionante la ringrazio tanto. questo è stato un grande spiegazione!!!
  2. 4

    fread è infatti progettato per leggere array di strutture da un file, ma è necessario utilizzare correttamente.

    fread‘s quattro parametri sono i seguenti:

    void * ptr, size_t size, size_t count, FILE * stream

    Il primo parametro è dove mettere i dati (nel tuo caso, Collection). Il secondo parametro è la dimensione di ogni elemento di un array: nel tuo caso, vuoi mettere sizeof(struct Video). Il terzo parametro è il numero di elementi che si desidera leggere, nel tuo caso, MAX. Il quarto parametro è il file da leggere.

    Se si desidera leggere in un array come struct Video Collection[MAX], è quindi necessario utilizzare fread(Collection, sizeof(struct Video), MAX, file). fread restituirà il numero totale di elementi di lettura, che sarà ≤ MAX.

    • sono andato avanti e ho cercato questo….tuttavia è ancora la stampa di un array vuoto. ho aggiunto il mio metodo di scrittura di codice di cui sopra…. è la scrittura di dati in un file, ma im non sicuro se è corretta.
    • Come stai la stampa array?
    • aggiunto il mio stampare il codice sopra… funziona quando si stampa l’array prima di scrivere/leggere tho…
    • Nota che fread restituisce il numero di elementi di lettura, quindi è necessario impostare tail = fread(...) per stampare il giusto numero di elementi.
  3. 1

    Prima devo presumere che si intende struct Video Collection[MAX];altro la parte superiore non è valido C.

    Secondo: stai leggendo 1 byte in Collezione.

    Provare
    fread(Collection, sizeof(struct Video), MAX, fileName);

    Questo leggerà fino a MAX volte pezzi di sizeof(struct Video)byte in Collezione.

    • quindi nel mio metodo di scrittura…. dovrebbe anche essere utilizzando sizeof(struct Video) invece di sizeof(Collection) ?
    • Idealmente sì. Il motivo è che se il buffer di scrittura non è abbastanza grande per contenere tutta la tua collezione una volta che la scrittura non riuscirà, quindi, a scrivere in struct Video pezzi è una scelta più sicura. In generale ogni volta che si usa di lettura/scrittura è sempre necessario verificare se il vostro intero buffer è stato effettivamente letti e/o scritti.

Lascia un commento