Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Duda De Principiante En C/c++

Iniciado por Schu, 28 de Agosto de 2005, 04:34:51 PM

« anterior - próximo »

Schu

 Saludos a todos, escribo para plantear una duda como principiante que soy en este mundillo, enlazando casi casi con el post anterior :).
El caso es que me decidí por aprender C/C++ (estoy siguiendo un libro de Anaya Multimedia titulado Manual imprescindible de C/C++ que me viene muy bien) y estoy haciendo una pequeña base de datos de pilotos de F1 con estructuras estáticas (hay que ir poco a poco :D). Mi problema viene a la hora de editar una entrada de la base de datos, que no consigo que modifique la que yo quiero, ya que siempre escribe sobre la primera entrada.
Lo que hago es pedir el nombre del piloto en cuestión y si lo encuentra vuelvo a pedir los datos (inserto el código para más información):

/*Funcion que permite modificar los datos de 1 piloto*/
void EditarPiloto(struct ficha &piloto)
{
    char nombre_piloto[40];
    int i = 0;
    struct ficha FichaPiloto[300];

    /*Abrimos el archivo*/
    FILE *archivo;
    archivo = fopen("PilotManager.txt","r+");

    /*Pregunto por el nombre del piloto que hay que editar*/
    printf("Escribe el nombre del piloto que quieres editar: ");
    gets(nombre_piloto);

    /*Si no se puede abrir el archivo doy un mensaje de aviso*/
    if(archivo == NULL)
    {
               printf("ERROR: PilotManager.txt no se ha podido abrir\n");
    }
    else
    {
               /*No salimos del bucle mientras no se lea todo el archivo o bien,
                 mientras no se encuentren coincidencias con el nombre metido*/
               fread(&FichaPiloto[i],sizeof(FichaPiloto[i]),1,archivo);
               while( (feof(archivo) == 0) && (strcmp(nombre_piloto,FichaPiloto[i].nombre) != 0) )
               {
                      i++;
                      fread(&FichaPiloto[i],sizeof(FichaPiloto[i]),1,archivo);
               }
               fclose(archivo);
               archivo = fopen("PilotManager.txt","r+");
               /*Si se encuentra el nombre volvemos a meter todos los datos*/
               if(strcmp(nombre_piloto,FichaPiloto[i].nombre) == 0)
               {


                      cout << "Nombre del piloto?: ";
                      gets(FichaPiloto[i].nombre);


                      cout << "Escuderia / Motor: ";
                      gets(FichaPiloto[i].escuderia);

                      cout << "Edad?: ";
                      cin >> FichaPiloto[i].edad;

                      cout << "Titulos mundiales?: ";
                      cin >> FichaPiloto[i].titulos;

                      cout << "GPs disputados?: ";
                      cin >> FichaPiloto[i].GPs_disputados;

                      cout << "GPs ganados?: ";
                      cin >> FichaPiloto[i].GPs_ganados;

                      cout << "Pole Positions?: ";
                      cin >> FichaPiloto[i].poles;

                      cout << "\n\n\n";
                      fwrite(&FichaPiloto[i],sizeof(FichaPiloto[i]),1,archivo);


               }
               else
               {
                      cout << "ERROR: " << nombre_piloto << " no esta en la base de datos\n";

               }
               fclose(archivo);
    }
}

La verdad es que probé tantas cosas que ya no sé si eso está bien. Está claro que se me escapa algo y por más que consulto el libro etc, no acierto a saber qué es. A ver si alguien me podría ayudar y gracias por adelantado.

                                               Saludos

Zaelsius

 El problema está en que sólo escribes una entrada en el fichero(la modificada). Cuando haces un fopen( .., "r+"), te cargas todo lo que hubiese anteriormente en el fichero. Pasaría lo mismo con la opción "w".

Aunque sólo modifiques una entrada, debes volver a escribir todas las entradas en el fichero.

En el caso de *añadir* una entrada, te bastaría con un fopen( ..., "a" ) (a de append) para colocar el puntero de escritura al final del fichero nada más abrirlo.
Así sólo tendrias que escribir la nueva entrada.

referencia de fopen: http://www.cplusplus.com/ref/cstdio/fopen.html

Schu

 Entonces, si he entendido bien, lo que debo hacer es no sólo escribir la entrada que quiero modificar sino que también he de volver a escribir las ya existentes.
Por otra parte, lo que no acabo de comprender es por qué me modifica siempre la primera entrada pero muestra las demás tal y como las tenía antes si como dices, al hacer un fopen("...","r+") te cargas todo lo que había antes.
Saludos y perdón por la torpeza jeje

Zaelsius

 Me he "equivoquido" xD, seguramente "r+" no se cargue el fichero :P ... pero al abrir el fichero, el puntero de lectura/escritura se posiciona al comienzo, por eso al escribir te cargas siempre la primera entrada.

Tienes dos opciones, ir leyendo entradas hasta llegar a la que quieres modificar, y entonces escribir, o bien, escribir de nuevo todas desde el principio.

Ray

 No lo he mirado detenidamente pero quizas te sirve esto:

conociendo la posición del piloto en el archivo y siendo todos de igual tamaño:

fseek(archivo, sizeof(ficha) * PosPiloto, SEEK_SET);

fwrite(...

Schu

 Gracias Ray por tu sugerencia, simplemente con incluir esa línea de código y con otros dos pequeñísimos retoques la función ya hace lo que quiero.
Otra cosa más que se aprende :D
Saludos

ethernet

 La única posibilidad de escribir en mitad de un fichero que yo conozco es mmap, con lo cual la chapuza de posicionar el "puntero" de fichero en la posición que quieres y después escribir las modificaciones no funcionará nunca. :P

Zaelsius

 No he usado el "r+" en mi vida pero me veo esta noche probándolo yo mismo xDDD.

Es época de exámenes, tiempo para perder en los foros y escribir COTW's ;)

ethernet

Cita de: "ZaelSiuS"Es época de exámenes, tiempo para perder en los foros y escribir COTW's ;)
Espero que el verbo perder afecte solo a los foros y no al COTW! :)

Schu

 Pues la verdad es que sí que me funciona lo de apuntar a la posición que me interesa y modificarla luego  :huh:
Sea como sea el caso es que ahora todo funciona bien  :D  






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.