Domanda

Voglio memorizzare le stringhe in un file binario, insieme a un sacco di altri dati, im utilizzando il codice qui sotto (quando lo uso per davvero saranno malloc'd le corde) posso scrivere sul file. Ive ha guardato in un editor esadecimale. Non sono sicuro im scrivendo il terminatore null correttamente (o se ho bisogno di). quando ho letto di nuovo fuori ottengo la stessa lunghezza della stringa che ho conservato, ma non la stringa. Che cosa sto facendo di sbagliato?

FILE *fp = fopen("mybinfile.ttt", "wb");

char drumCString[6] = "Hello\0";
printf("%s\n", drumCString);    
//the string length + 1 for the null terminator
unsigned short sizeOfString = strlen(drumCString) + 1;
fwrite(&sizeOfString, sizeof(unsigned short), 1, fp);

//write the string
fwrite(drumCString, sizeof(char), sizeOfString, fp);

fclose(fp);

fp = fopen("mybinfile.ttt", "rb");  

unsigned short stringLength = 0;
fread(&stringLength, sizeof(unsigned short), 1, fp);

char *drumReadString = malloc(sizeof(char) * stringLength);
int count = fread(&drumReadString, sizeof(char), stringLength, fp);

//CRASH POINT
printf("%s\n", drumReadString);

fclose(fp); 
È stato utile?

Soluzione

Si sta facendo di sbagliato durante la lettura. avete messo il & per la variabile puntatore è per questo che dà segmentation fault.

ho rimosso che funziona bene e restituisce Ciao correttamente.

int count = fread(drumReadString, sizeof(char), stringLength, fp);

Altri suggerimenti

Vedo un paio di problemi, alcuni problematico, alcuni stilistico.

  • Si dovrebbe verificare i valori di ritorno da malloc, fread e fwrite dal momento che è possibile che l'assegnazione può fallire, e nessun dato può essere letto o scritto.
  • sizeof(char) è sempre 1, non c'è bisogno di moltiplicare per essa.
  • L'array "Hello\0" personaggio è effettivamente lungo 7 byte. Non è necessario aggiungere un terminatore null superfluo.
  • Io preferisco la char x[] = "xxx"; linguaggio piuttosto che specificare una lunghezza definita (a meno che non si desidera una serie più lunga della stringa ovviamente).
  • Quando si fread(&drumReadString ..., si sta effettivamente sovrascrivere il puntatore , non la memoria a cui punta. Questa è la causa del crash. Dovrebbe essere fread(drumReadString ....

Un paio di consigli:

1

Un \0 terminazione è implicito in qualsiasi stringa doppio apice, e con l'aggiunta di un ulteriore alla fine si finisce con due. I seguenti due inizializzazioni sono identiche:

char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};

char drumReadString[] = "Hello";

è sufficiente, e specificando la dimensione della matrice è facoltativo quando viene inizializzato in questo modo, il compilatore capire la dimensione richiesta (6 byte).

2

Quando si scrive una stringa, si potrebbe altrettanto bene basta scrivere tutti i caratteri in una sola volta (invece di scrivere uno per uno carattere volte sizeOfString):

fwrite(drumCString, sizeOfString, 1, fp);

3

Anche se non così comune per un normale scenario di Personal Computer, malloc può restituire NULL e si potranno beneficiare di sviluppare un habbit di controllare sempre il risultato perché in ambienti embedded, ottenendo NULL non è un risultato improbabile.

char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
        fprintf(stderr, "drumReadString allocation failed\n");
        return;
}

Non si scrive il NUL di terminazione, non è necessario, ma poi si deve pensare di aggiungere che durante la lettura. cioè malloc StringLength + 1 char, leggere caratteri StringLength e aggiungere un \0 alla fine di quello che è stato letto.

Ora il solito avvertimento: se si sta scrivendo file binario il modo in cui si sta facendo qui, hai un sacco di ipotesi non dichiarate che rendono il formato difficile da porta, a volte anche a un'altra versione dello stesso compilatore - che ho visto allineamento predefinito nei cambiamenti struct tra le versioni del compilatore.

Alcuni di più da aggiungere alla paxdiablo e AProgrammer - se avete intenzione di usare malloc in futuro, basta farlo da ottenere andare. E 'forma migliore e significa che non sarà necessario eseguire il debug quando passare.

Inoltre non sto vedendo pienamente l'uso del corto senza segno, se si sta progettando di scrivere un file binario, ritengo che il tipo char non firmato è in genere di dimensione in byte, che rende molto conveniente per questo scopo.

È sufficiente rimuovere il vostro & drumReadString nel fread function.You semplicemente utilizzare drumReadString in quella funzione, come Ganesh mentioned.Because, drumReadString è un array.Array è simile ai puntatori che indicano l'ubicazione di memoria direttamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top