Ver Mensaje Individual
  #1 (permalink)  
Antiguo 19/04/2015, 19:03
Avatar de vangodp
vangodp
 
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 11 años, 2 meses
Puntos: 38
Pregunta Duda con fstream y familia.

Hola compañeros.
Me siento derrotado por los puñeteros streams de C++, no se que me pasa hoy.
Pido ayuda por que ya no lo entiendo nada de lo que pasa. La teoría creo que la se correctamente, pero en la practica no me funciona, o eso creo.

A ver por donde empiezo....

primero diré lo que quiero hacer y diré lo que sé o creo que sé.

Tengo una estructura llamada paciente con 4 datos, int id, char nombre[30], char apellidos[30], int edad.

Quiero poner en un fichero BINARIO un contador tipo entero al principio del fichero para que me marque la cantidad de pacientes que hay en dicho fichero. Luego se van ingrasando pacientes con la funcion write, para eso uso un fstream fichero, el problema es que tengo que escribir y leer varias veces y pretendía usar un solo puntero de entrada y salida.

Después de comer toda la red para saber que es lo que pasa con el código que os pongo a continuación, me siento vencido por los puñeteros streams.

La tarea consiste en abrir el fichero, si no existe y crearlo y poner en el el contador inicializado a cero ya que aun no hay clientes, a cada cliente que vaya añadiendo tengo que volver al principio y incrementar ese contador, pero por alguna razón no me funciona no se que hago mal.

He leído muchos lugares sobre las funciones seekg/seekp, los modos de apertura:
ios: trunc(sobrescribe), app(agrega al final), ate(posiciona al final y permite escribir en cualquier parte del fichero), in(lectura), out(escriptura)...

¿Alguien puede echarme un cable y contestar algunas preguntas al final?
Dejo mi porqueria código al que le incluyo 2 clientes y intento incrementar el contador.
Código C++:
Ver original
  1. #include <iostream>
  2. #include <fstream>
  3. #include <cstring>
  4.  
  5. using namespace std;
  6. const int TAM_CADENA = 30;
  7.  
  8. typedef char cadena[TAM_CADENA];
  9. struct paciente {
  10.     int id;
  11.     cadena nombre;
  12.     cadena apellidos;
  13.     int edad;
  14. };
  15.  
  16. int main () {
  17.     //abro para escriptura, creo que deberia ser una combinacion de out/binary/ate pero ya probe de todo ni se que hago más.
  18.     std::fstream f ( "w.dat",   std::ifstream::binary | std::ifstream::out | std::ifstream::app );
  19.     paciente p = { 222, "jose", "perez", 46 };
  20.    
  21.     //n será el contador que va al principio del fichero binario
  22.     int n = 0;
  23.     //Supuesta mente situo al principio y envio el contador al inicio del fichero con un valor de cero.
  24.     f.seekp(0, f.beg);
  25.     f.write( reinterpret_cast< char* >( &n )       , sizeof (int ) );
  26.    
  27.     //grabo la estructura p al fichero. Se supone que va a continuacion del contador. :S
  28.     f.write( reinterpret_cast< char* >( &p.id ), sizeof (int ) );
  29.     f.write( reinterpret_cast< char* >( &p.nombre ), ( sizeof (char)*30 ) );
  30.     f.write( reinterpret_cast< char* >( &p.apellidos ), ( sizeof (char)*30 ) );
  31.     f.write( reinterpret_cast< char* >( &p.edad ) , sizeof (int ) );
  32.    
  33.     //vuelvo al principio y incremento el contador
  34.     f.seekp(0, f.beg);
  35.     n++;
  36.     f.write( reinterpret_cast< char* >( &n ), sizeof (int ) );        
  37.     //cierro el fichero, para despues aprovecharlo para leer por ejemplo. Algunos piensan que seria más facil abrirlo en lectura y escriptura pero no puedo, debo reaprovecharlo =(
  38.     f.close();
  39.    
  40.     //volvemos a repetir el proceso con otro paciente
  41.     f.open ( "w.dat",   std::ifstream::binary | std::ifstream::out  | std::ifstream::app );
  42.    
  43.     f.seekp(0, f.end);
  44.     p.id = 22334;
  45.     strcpy( p.nombre, "miguel");
  46.     strcpy( p.nombre, "miguel");
  47.     p.edad = 64;
  48.    
  49.     f.write( reinterpret_cast< char* >( &p.id )       , sizeof (int ) );
  50.     f.write( reinterpret_cast< char* >( &p.nombre )   , ( sizeof (char)*30 ) );
  51.     f.write( reinterpret_cast< char* >( &p.apellidos ), ( sizeof (char)*30 ) );
  52.     f.write( reinterpret_cast< char* >( &p.edad )     , sizeof (int ) );    
  53.    
  54.     f.seekp(0, f.beg);
  55.     n = 2;
  56.     f.write( reinterpret_cast< char* >( &n )       , sizeof (int ) );    
  57.     f.close();
  58.    
  59.     return 0;
  60. }
Si pueden arreglarmelo para que lo entienda os estaría muy grato.

Y si pueden aclararme algunos puntos entonces

¿Funciona igual seekg que seekp? Se que g es get y p es put. Si he entendido bien seekp se usa para posicionar para escritura y seekg para lectura.
Uno ley que trabaja de forma parecida a fseek de C, el otro es recibe no se que la de fpos que se supone que es un long. pfff

¿Pueden explicarme como funciona seekp y seekg para dumies? =)

¿me pueden explicar las combinaciones de modos de apertura?

¿Se puede reaprovechar un objeto fstream para abrirlo en un modo diferente? Hay que llamar el destructor o como se hace?

ppfff por mi quedaria todo el dia preguntando. Encontré buenos tutoriales de explicacion, pero no se que pasa, creo que falla al tratar de intentar reaprovechar el objecto pero no se por que pasa eso. pfff

Gracias chicos, intento no molestar pero es que así son los noobs, y es que eso me tiene alquilado todo el finde. No se por que me parece mucho mejor la forma de gestionar ficheros con C que con C++, me quede con mal sabor de boca con los streams.

Suerte

PD: No puedo usar un fichero para ambas cosas Entrada/salida lo que quiero es aprovechar el fstream fichero para abrirlo en diferentes modos.