[C con Clase] Una pequeña duda con los ficheros

Steven Davidson srd4121 en njit.edu
Jue Abr 26 03:57:34 CEST 2012


Hola Marcos,

On 4/25/2012 5:45 PM, Marcos Collado Martín wrote:
> Ok gracias, pero lo que quiero es que esa función la puedan utilizar
> varias estructuras diferentes, no solo (en tu caso) stDatos. Por
> ejemplo, algo que hizo Salvador antes:
> http://paste2.org/p/1995171
>

El problema es que lo que hizo Salvador y lo que quieres hacer tú son 
cosas diferentes. La solución de Salvador se basa en leer cantidades de 
bytes de un fichero y escribir los bytes en otra parte del mismo fichero.

En tu ejemplo, quieres leer la información y luego usarla como si fuese 
una estructura en particular. Sin embargo, esto va en contra de lo que 
quieres, porque dices que te interesa que la información leída se use 
con cualquier estructura en general.

Sugiero que la función acepte un puntero a función la cual acepte un 
puntero genérico para hacer lo que quieras con tal información, sea el 
tipo que sea. Por ejemplo,

typedef void (*PF)( void * );

void Intercambia( FILE *fichero, long iz, long de, long 
bytesPorRegistro, PF pfunc )
{
   void *reg1, *reg2;

   reg1 = malloc(bytesPorRegistro);
   reg2 = malloc(bytesPorRegistro);
   ...
   pfunc( reg1 );
}

Un ejemplo de una función y estructura sería,

struct stAlgo
{
   char szCad[64];
   int num;
};

void asignar( void *pDatos )
{
   stAlgo *pReg = (stAlgo *)pDatos;

   strcpy( pReg->szCad, "hola mundo" );
   pReg->num = 10;
}

Y ahora podemos invocar 'Intercambia()' así,

Intercambia( fichero, a, b, sizeof(stAlgo), asignar );

De esta manera, 'Intercambia()' realizará su tarea además de alguna 
tarea específica, 'asignar()' en este ejemplo, que tratará la 
información como un tipo particular.


En C++, podemos usar plantillas para resolver este mismo problema. Por 
ejemplo,

template< typename T >
void Intercambia( FILE *fichero, long iz, long de )
{
   T reg;

   fseek( fi, iz*sizeof(T), SEEK_SET );
   fread( &reg, sizeof(T), 1, fi );
   ...
   reg.memfunc();
   reg.memdato = 0;
}

La usaríamos así,

Intercambia< stAlgo >( fichero, a, b );


Claro que no todos los tipos T tendrán el mismo nombre de la función 
miembro, 'memfunc()', ni tampoco el nombre del dato miembro, 'memdato'.

La solución para este problema es pasar un puntero a miembro para que 
pueda acceder a un miembro cualquiera; por ejemplo,

template< typename T >
void Intercambia( FILE *fichero, long iz, long de, void T::*pfunc() )
{
   T reg;

   fseek( fi, iz*sizeof(T), SEEK_SET );
   fread( &reg, sizeof(T), 1, fi );
   ...
   reg.*pfunc();
}

Y la usaríamos así,

Intercambia( fichero, a, b, &stAlgo::m_asignar );


Hay otras soluciones parecidas, pero este tema se complicaría un poco 
más y el correo-e sería más extenso.


Espero que esto aclare un poco más el tema.

Steven





Más información sobre la lista de distribución Cconclase