Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Duda con fstream y familia.

Estas en el tema de Duda con fstream y familia. en el foro de C/C++ en Foros del Web. 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 ...
  #1 (permalink)  
Antiguo 19/04/2015, 19:03
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 10 años, 7 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.
  #2 (permalink)  
Antiguo 19/04/2015, 22:39
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Duda con fstream y familia.

Con las citas del estándar C++:
Cita:
app -> seek to end before each write
Va a posicionar el cursor al final del archivo antes de cada escritura.
En tu caso, por ejemplo, no importa a dónde quieras posicionar el cursor antes de escribir (con f.seekp(0, f.beg);) porque de todos modos, todos y cada uno de los bytes que quieran escribirse, van a ir al final del archivo.
Cita:
ate -> open and seek to end immediately after opening
Inmediatamente después de la apertura va a posicionar el cursor al final del archivo, pero a diferencia del modo app es posible escribir en cualquier posición.

Puedes usar dos modos para open, dependiendo de si el archivo existe o no. Al abrir un archivo existente, si no quieres destruir su contendido deberás abrirlo en modo in|out. Por otro lado, si el archivo no existe, al abrirlo con out crearás uno nuevo.

Última edición por lareto; 20/04/2015 a las 00:25
  #3 (permalink)  
Antiguo 20/04/2015, 02:36
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 10 años, 7 meses
Puntos: 38
Respuesta: Duda con fstream y familia.

Gracias lareto.
Hoy por enesima vez voy a ver si puedo buscar un mecanismo para eso.
  #4 (permalink)  
Antiguo 20/04/2015, 08:08
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Duda con fstream y familia.

Hola; la idea sería fijarse primero si el archivo existe. Si no existiera abrirlo (creándolo) con binary | out; mientras que si ya existiera, abrirlo con binary|in|out
  #5 (permalink)  
Antiguo 20/04/2015, 09:56
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 10 años, 7 meses
Puntos: 38
Respuesta: Duda con fstream y familia.

Ok.. Voy a probarlo y ya te comento.

Desde luego me esta fallando la lógica.

Hasta pronto.

Etiquetas: fstream, stream
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 08:24.