Usuario: anónimo

Usuarios en línea: 1
Invitados: 1

FAQ

Mensaje

19m
Duda con función que retorna un puntero a una estructura que no está funciona
U(Usuario) 2017-12-18 21:13:13  H Adjuntos: A 

Estimados docentes de C con Clase:

Estuve un tiempo sin seguir con las prácticas del curso de C++ y

recientemente regresé luego de hacerme un tiempo. Para hacer algo más

real, decidí comenzar un proyecto más "real" y práctico, para lo cual

elegí crear una pequeña biblioteca para leer un formato de archivo que

no sé si tiene una implementación de código abierto como tal, de forma

que se pudiera reutilizar de forma libre

(y con licencia libre) para que otras aplicaciones pudieran importar

datos de este formato, etc.  Mi idea era la de crear una biblioteca

independiente de la plataforma y dentro de lo posible, sin dependencias

adicionales, solo requiriendo al menos una versión reciente de las

bibliotecas de C, y al mismo tiempo seguir aprendiendo en el camino.

Aclaro que estoy programándola en C para que sea útil tanto en C como en

C++.

El formato de archivo es el de CARDFILE, una aplicación del antiguo

Windows 3.11. El formato de archivo no ha sido del todo bien

documentado, pero algunas especificaciones están en:

*

https://support.microsoft.com/en-us/help/99340/windows-3-1-card-file-format

* http://donaldkenney.x10.mx/CARDFILE.HTM#MGC

*

https://groups.google.com/forum/#!searchin/comp.windows.ms/cardfile;context-place=forum/comp.windows.ms

* https://en.wikipedia.org/wiki/Cardfile

Este formato es un archivo binario de extensión CRD con tres versiones,

que se las puede identificar por sus números mágicos: MGC, RRG y DKO. El

primero fue el formato inicial, el segundo añadió soporte para objetos

OLE (que se pueden manipular mediante el API de Windows) y el tercero

habría añadido soporte para Unicode 16 bits.

De forma gráfica, se trata de un archivo que contiene tarjetas o cards,

en las que se puede guardar información personal al estilo de un

fichero,  conteniendo varias tarjetas con texto, mapas de bits, objetos

OLE cada una.

Un archivo CRD se caracteriza por contener tres bloques: (1) un

encabezado o header, (2) un índice o index, y (3) los datos de las

tarjetas señaladas en el índice.

-------

(1) El encabezado se caracteriza por contener dos o tres sub-bloques

dependiendo de la implementación, con al menos un "número mágico" y un

"número de cartas".

(a) El del formato MGC es así:

[número mágico (3 bytes)="MGC"] [número de tarjetas (2 bytes, little

endian)] = 5 bytes

(b) Los formatos RRG y DKO serían así:

[número mágico (3 bytes)="RRG" o "DKO"] [último id de objeto (4 bytes,

little endian)][número de tarjetas (2 bytes, en little endian)] = 9 bytes

Al "ultimo id de objeto" no le veo demasiada utilidad por el momento. El

numero de

tarjetas sí es un dato importante para acceder al resto del archivo.

-----

(2) El índice comienza una vez termina el encabezado, la distribución de

bytes es común a todos los formatos de CRD, y puede repetirse la misma

estructura tantas veces como tarjetas haya en el archivo:

(a) [reservado (6 bytes)= 0x000000]

(b) [posición en el archivo de los datos asociados a esta entrada de

índice (4 bytes)]

(c) [flag inicial (1 byte) = 0x00]

(d) [título del índice de la tarjeta (40 bytes) = cadena de texto]

(e) [flag final  (1 byte) = 0x00]

Por ejemplo, si hay dos tarjetas, tendríamos:

[[ENCABEZADO:...]]

[[ÍNDICE:

 [reserv.] [pos. datos 1=0x39] [flag] [titulo indice 1] [flag final]

 [reserv.] [pos. datos 2=0xnn] [flag] [titulo indice 2] [flag final]

]]

[[DATOS:

  0x39-> ...

  0xnn-> ...

]]

-----

(3) La sección de datos es más compleja y su implementación depende de la

versión de archivo CRD. La más simple es la de los MGC, con la cual

estaba empezando a trabajar.

Más o menos se compone así para los MGC:

(a) [Tamaño de objeto bmp en little endian] 0x0000 (no hay objeto) u otro

valor si hay uno, del peso indicado, en little endian

(b) [OPCIONAL-objeto:

         (b.1) [ancho=2 bytes]

         (b.2) [alto=2 bytes]

         (b.3) [x=2 bytes]

         (b.4) [y=2 bytes]

         (b.5) [datos (tamaño en bytes indicado en "(a)" )]

(c) [Tamaño de texto=2 bytes little endian]

(d) [Texto=440 bytes]

En los RRG es así

(a) [Flag de objeto bmp en little endian] 0x0000 (no hay objeto) o

0x0001 (hay un objeto) en little endian

(b) [OPCIONAL-Muchos flags del objeto OLE que no enumeraré aquí...]

(c) [Tamaño de texto]

(d) [Texto=440 bytes]

---------------------

En cuanto a la implementación, recién estaba empezando, y estaba

haciendo una función que retornaba un puntero a una estructura del

índice para poder obtener los datos del índice, es decir, el título del

índice y la ubicación de los datos dentro del archivo:

PINDEX LoadCardNumberInfo (FILE *fileptr, int card_number);

PINDEX es un puntero a la estructura que hace referencia a la sección

índice del archivo.

Pero por alguna razón la función no está trabajando como debería y me da

un error al ejecutar. He intentado detectar con el depurador cómo

modificar este comportamiento, pero no tuve éxito.

La función trabaja de esta forma:

1. Externamente se abre el archivo. Dentro de la función se declara una

instancia del puntero a la estructura del índice.

2. Consulta la versión de archivo CRD para determinar cuánto debe

moverse el "cursor" con fseek, o retorna un puntero nulo en caso de ser

un tipo de archivo desconocido. Esto se debe a que como ya expliqué más

arriba, el índice comienza en posiciones distintas si se trata de un

MGC, o en otro caso, de los RRG y DKO.

3. Reserva memoria dinámica en caso de que (2) no haya tenido error.

4. Se mueve a la posición indicada en (2).

5. Abre un bucle for para recorrer secuencialmente la sección de índices:

    a. Evita el campo de 6 bytes reservados, que no nos es útil, hasta

el comienzo del campo de <posición datos>.

    b. Lee <posición datos> y lo convierte a big endian para poder

trabajar con él. Si no lo hice mal, este dato se guarda dentro de la

instancia de la estructura. No sé si en realidad debería guardar el dato

en una variable temporal.

    c. Evita el flag de comienzo del texto de la entrada de índice.

    d. Lee el texto del índice. De nuevo, no sé si no lo hice mal, este

dato se guarda dentro de la instancia de la estructura. No sé si en

realidad debería guardar el dato en una variable temporal.

    e. Evita el flag de cierre del texto de la entrada del índice, y se

repite el bucle hasta llegado el número de índice indicado.

6. Se mueve el cursor al principio del archivo y libera memoria (si

corresponde).

7. Retorna un puntero a la estructura con los datos recogidos, para

trabajar de forma externa a la función.

¿Podría Ud. ver el código y  ver en qué falla mi implementación, que

luego de haberlo analizado no logro encontrar una respuesta?

Adjunto en caso de ser necesario el código fuente actual y unos archivos

de ejemplo para probar en la línea de comandos con una implementación de

un programa de ejemplo que utiliza la biblioteca como base. Para leer

los datos binarios de los archivos CRD utilicé el editor hexadecimal

FRHED, aunque supongo que cualquier otro similar será igualmente útil.

Muchas gracias.

Saludos

_______________________________________________

Lista de correo Cconclase Cconclase@listas.conclase.net

http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net

Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ

Fichero adjunto: libcardfile.zip