Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: Schu en 28 de Agosto de 2005, 04:34:51 PM

Título: Duda De Principiante En C/c++
Publicado por: Schu en 28 de Agosto de 2005, 04:34:51 PM
 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
Título: Duda De Principiante En C/c++
Publicado por: Zaelsius en 28 de Agosto de 2005, 04:49:38 PM
 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
Título: Duda De Principiante En C/c++
Publicado por: Schu en 28 de Agosto de 2005, 05:06:47 PM
 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
Título: Duda De Principiante En C/c++
Publicado por: Zaelsius en 28 de Agosto de 2005, 05:18:09 PM
 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.
Título: Duda De Principiante En C/c++
Publicado por: Ray en 28 de Agosto de 2005, 05:44:30 PM
 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(...
Título: Duda De Principiante En C/c++
Publicado por: Schu en 28 de Agosto de 2005, 06:10:32 PM
 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
Título: Duda De Principiante En C/c++
Publicado por: ethernet en 28 de Agosto de 2005, 07:04:43 PM
 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
Título: Duda De Principiante En C/c++
Publicado por: Zaelsius en 28 de Agosto de 2005, 07:18:48 PM
 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 ;)
Título: Duda De Principiante En C/c++
Publicado por: ethernet en 28 de Agosto de 2005, 07:28:55 PM
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! :)
Título: Duda De Principiante En C/c++
Publicado por: Schu en 28 de Agosto de 2005, 08:48:00 PM
 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