2010-05-04 8 views
5

Tengo un stucture:puntero de escritura para el archivo en C

typedef struct student { 
    char *name; 
    char *surname; 
    int age; 
} Student; 

tengo que escribirlo en el archivo binario.

Student *s = malloc(sizeof(*s)); 

lleno mi estructura de datos y luego escribo en el fichero:

fwrite(s, sizeof(*s), 1, fp); 

En mi archivo no lo existe un nombre y apellido, que tienen un direcciones de char *. ¿Cómo puedo escribir para archivar una palabra, no una dirección?

Respuesta

0

Necesitas eliminar la referencia s e individualmente escribir cada elemento de la estructura a escribir realmente thecontents al archivo:

size_t nameCount = strlen(s->name) + 1; 
fwrite(s->name, sizeof(char), nameCount, fp); 

size_t surnameCount = strlen(s->surname) + 1; 
fwrite(s->surname, sizeof(char), surnameCount, fp); 
+1

Esto no funcionará con la definición de estructura publicado - 'sizeof (s-> nombre)' dará la tamaño de un 'char *'. – caf

+0

Sí, tienes razón - Cambié el tamaño de strlen –

+0

así que ahora necesitas cambiarlo a strlen() * sizeof (char) ... (Bueno, sizeof (char) será 1, solo para el principio – rkellerm

10

Es necesario eliminar la referencia de su puntero y escribir las partes de la estructura. (No debe fwrite una estructura directamente, sino que codificar sus partes y escribir los:

Student *s = malloc(sizeof(*s)); 
s->name = "Jon"; 
s->surname = "Skeet"; 
s->age = 34; 

// .... 

fwrite(s->name, sizeof(char), strlen(s->name) + 1, fp); 
fwrite(s->surname, sizeof(char), strlen(s->surname) + 1, fp); 

//This one is a bit dangerous, but you get the idea. 
fwrite(&(s->age), sizeof(s->age), 1, fp); 
+0

pero tengo aproximadamente 10 campos en la estructura. Su código muy largo –

+1

Luego escribe una función que lo escribe todo, y simplemente llama eso, así: 'int fwriteStudent (Student * s, FILE * fp); ', y simplemente recuerde mantener esa función actualizada mientras modifica su definición de estructura. –

+0

@Sergey: puede encapsular estas operaciones en una sola función, por lo que no tiene que ser *" código muy largo "*. –

3

si desea escribir directamente la estructura, ya que es un archivo que se desea definir los tamaños de nombre y apellido en lugar de asignar dinámicamente ella.

typedef structure student { char name[100]; char surname[100]; int age; } 

otra cosa que tendrá que escribir cada información en la estructura de uno en uno.

+0

-1: longitudes máximas de cadena fija son, como h como se ha comentado, malo. –

+3

@Williham Totland - He dado una razón por la que harías esto. es decir, si desea escribir la estructura tal como es. no solo comenta esto a ciegas como malo. ¿Tiene alguna idea mejor, si desea escribir la estructura en una sola operación de escritura? – SysAdmin

+0

Escribir la estructura como una operación de escritura es, nuevamente como se ha comentado, una Idea Mala ™. Es casi, pero no completamente, no portátil, y no siempre produce los resultados deseados. Las cadenas desbordadas son una violación de seguridad que está por ocurrir. –

4

usted tendrá que hacer un trabajo extra para escribir los datos apuntados por la estructura elementos - probablemente solo lo escriba elemento por elemento.

cambiar su estructura alternativa a algo como esto:

typedef struct 
{ 
    char name[MAX_NAME_LEN]; 
    char surname[MAX_SURNAME_LEN]; 
    int age; 
} Student; 
+0

-1: las longitudes máximas de cadena fija son malas. Muy mal. (¿Mmmmmkay?) –

+2

@Williham: las longitudes fijas de las cuerdas están bien en ciertos casos: para un problema de tarea con un pequeño conjunto de datos, es perfectamente apropiado usarlas. Usar una representación empaquetada, pero más compleja es 'optimización prematura', que es, para usar sus palabras, *" muy malo "*. –

+0

La etiqueta [tareas] apareció mucho después de dar mi respuesta e hizo mi comentario. En cualquier caso, [tarea] no excusa el código descuidado. –

0

Tenga en cuenta que de todos modos usted no será capaz de ver los campos en una forma 'normal' ya que escribe en un archivo binario. Intente abrir el archivo sin la "b" en el argumento de modo de fopen (r + \ w \ a etc. en lugar de rb + \ wb \ ab).

Se puede ver que cuando se utiliza fread (del archivo binario, después de abrirlo en el modo de "rb" se debe conseguir los campos de la estructura como se esperaba.

0

Vas a tener que escribir los campos de forma individual, como otros han dicho. una cosa que puede ayudar a volver a leer los datos van a escribir las longitudes de cuerda antes de cada entrada, por ejemplo.

size_t len; 
len = strlen(s->name)+1; 
fwrite(&len,sizeof(len),1,stream); 
fwrite(s->name,sizeof(*(s->name)),len,stream); 
... 

lectura posterior es entonces una cuestión de

Student * s = malloc(sizeof(*s)); 
size_t len; 
fread(&len,sizeof(len),1,stream); 
s->name = malloc(len); 
fread(s->name,sizeof(*(s->name)),len,stream); 
... 
3

En C, debe serializar las estructuras (convertirlas a una serie de bytes) manualmente. Si desea que la información que usted entregue sea legible por otra máquina, debe tomar la cuenta de endianness endianness.

Aquí está un ejemplo sencillo de la serialización de su estructura (escribirlo en un archivo), sin tener en cuenta endianness/diferencias de tamaño de palabra y hacer que el código no portables:

size_t length; 

length = strlen(s->name) + 1; 
fwrite(&length, sizeof(length), 1, fp); 
fwrite(s->name, 1, length, fp); 

length = strlen(s->surname) + 1; 
fwrite(&length, sizeof(length), 1, fp); 
fwrite(s->surname, 1, length, fp); 

fwrite(&s->age, sizeof(s->age), 1, fp); 

Y para unserialize:

size_t length; 

fread(&length, sizeof(length), 1, fp); 
s->name = malloc(length); 
fread(s->name, 1, length, fp); 

fread(&length, sizeof(length), 1, fp); 
s->surname = malloc(length); 
fread(s->surname, 1, length, fp); 

fread(&s->age, sizeof(s->age), 1, fp); 

En una aplicación real, debe verificar la validez de su entrada en lugar de asumir a ciegas que la entrada es válida y confiable. Además, debe decidir qué orden de bytes usará para almacenar sus int s, size_t s, etc., y asegúrese de leerlos/escribirlos en el orden de bytes correcto mediante el cambio de bit.

Por cierto, es posible que desee ver en tpl, un simple biblioteca de serialización binaria para C.

Cuestiones relacionadas