Ayuda con error al grabar en disco C++

Iniciado por Dimebag94, 17 Junio 2014, 18:00 PM

0 Miembros y 1 Visitante están viendo este tema.

Dimebag94

Hola!!
Este es mi primer mensaje en el foro, les queria comentar que tengo un problema con C++ usando SDL. Estoy haciendo un juego en el que al final de una partida solicita las 3 iniciales y graba tus puntos en un archivo .DAT, para luego cuando se quiera entrar al menu de puntajes muestre los 5 mejores puntajes con sus respectivas iniciales. El problema esta en que luego de grabar el puntaje, si lo quiero leer hay una variable tipo String (que es la que muestra las 3 iniciales) que al hacer fread y guardarse en un objeto se vuelve loca y empieza a mostrar simbolos extraños en toda la consola.

Aqui estan las dos clases que manejan esto de los puntajes:

class Cadena
{
private:
   string cadena;
   SDL_Surface *nombre;
public:
   Cadena();
   ~Cadena();
   string getCadena() {return cadena;}
   void tomarIngreso();
   void Mostrar();
};

class Usuario
{
   private:
       Cadena nombre;
       int puntos;
       Tiempo juego;
       int minutos,segundos,tiempoInicial;
       bool nombreIngresado,gano;
   public:
       Usuario();
       void mostrarNombre();
       void procesarTiempoJuego();
       void mostrarTiempoJuego();
       void ingresarNombre();
       void mostrarPuntos();
       string getNombre() {nombre.getCadena();}
       void setTiempoInicial(int t) {tiempoInicial+=t;}
       int getTiempoRestante() {return tiempoInicial-juego.obtenerTiempo();}
       int getPuntos() {return puntos;}
       bool getGano() {return gano;}
       bool getNombreIngresado() {return nombreIngresado;}
       void setPuntos(int p) {puntos+=p;}
       int leerPuntaje(int);
       void pausarTiempoJuego() {juego.Pausar();}
       void reanudarTiempoJuego() {juego.sacarPausa();}
       bool grabarPuntaje();
};

Como veran la clase cadena esta dentro de las propiedades de la clase Usuario, la clase cadena es la que uso para escribir en pantalla las 3 iniciales y las guarda en un string para luego mostrarlas por pantalla en la clase Usuario. El problema llega cuando quiero hacer esto:

Usuario obj;
int pos=0;
   while(obj.leerPuntaje(pos)==1)
   {
       cout<<obj.getPuntos()<<endl; --->ESTE ANDA BIEN
       cout<<obj.getNombre()<<endl;---->ESTE ME MUESTRA SIMBOLOS EXTRAÑOS SIN PARAR Y MI PROGRAMA SE ROMPE
     
       pos++
   }

Si yo hago esto antes de grabarlo todo anda bien pero me da la sensacion de que el string no se esta grabando bien





Lo olvidaba aqui estan el leer y el grabar de la clase Usuario:

bool Usuario::grabarPuntaje()
{
    FILE *u;
    u=fopen(RUTAPUNTAJES,"ab");
    if(u==NULL)
    {
        cout<<"ERROR CON EL ARCHIVO DE PUNTAJES."<<endl;
        return false;
    }
    fwrite(this,sizeof *this,1,u);
    fclose(u);
    return true;
}

int Usuario::leerPuntaje(int pos)
{
    FILE *u;
    u=fopen(RUTAPUNTAJES,"rb");
    if(u==NULL)
    {
        cout<<"ERROR CON EL ARCHIVO DE PUNTAJES."<<endl;
        return 0;
    }
    int l;
    fseek(u,pos*sizeof *this,0);
    l=fread(this,sizeof *this,1,u);
    return l;
}

eferion

std::string es una clase que gestiona cadenas de caracteres... no es una cadena de caracteres. Internamente, la clase string utiliza un puntero para almacenar la cadena de caracteres. Si tu almacenas en el fichero las posiciones de memoria utilizadas por "Usuario" de forma literal, estarás guardando en el disco el valor del puntero, es decir, la posición de memoria a la que apunta. Al recuperar la información del disco, recuperas el valor de la posición de memoria... pero en esa memoria no vas a encontrar información útil... es basura.

Lo que tienes que hacer es guardar los strings uno a uno:

Código (cpp) [Seleccionar]

bool Usuario::grabarPuntaje()
{
    FILE *u;
    u=fopen(RUTAPUNTAJES,"ab");
    if(u==NULL)
    {
        cout<<"ERROR CON EL ARCHIVO DE PUNTAJES."<<endl;
        return false;
    }
    fwrite( cadena.c_str( ), cadena.size( ),1,u );
    // falta guardar "nombre"
    fclose(u);
    return true;
}


Para recuperar la información, tampoco puedes machacar la posición de memoria de la clase, tienes que recuperar cada valor uno a uno y actualizar las variables según proceda.

PD.: El mecanismo que has puesto en tu código únicamente funcionará si ninguna de las clases implicadas hace uso de memoria dinámica; en caso contrario tendrás errores de lo más variopintos.