[C con Clase] problemas con la posicion del puntero en un fichero, funciones fread, frwite, fseek etc.

Oscar Alberto Barnett Contreras obarnettc en gmail.com
Mar Mar 6 02:26:35 CET 2012


Hola Albert Montolio, interesante tu ejemplo. Lo he incorporado en un
proyecto Netbeans e hice minimos retoques, tomando en cuenta la
sugerencias de Salvador Pozo y funciona perfectamente. te remito el
*.cpp y el *.dat con el cual SI MUESTRA DESDE LA PALABRA INICIAL Y NO
REPITE LA ULTIMA PALABRA.
Espero te ayude. Saludos.
PD:_ No tengo claro el objetivo de los campos contador, pero creo que
tu problema es lo que he resaltado en mayusculas.


El 05/03/12, Albert Montolio <albert.montolio en gmail.com> escribió:
> Hola Salvador, he aplicado el cambio que me has dicho, y sigue pasando lo
> mismo, no lee la primera palabra, lee la segunda, y la ultima palabra la
> escribe dos veces :S
> la i esta inicializada a 0, y con la funcion fseek deberia ponerse el
> contador al principio de todo, para leer la primera palabra, xo nose xk no
> lo hace, me lee la segunda. y luego la ultima me la vuelve a repetir :S
> gracias por las ideas para optimizarlo, una vez consiga k funcione me
> dedicare a mejorarlo
>
> #include <stdio.h>
> #include <string.h>
>
>
> struct t_palabra {                      // t_palabra es una estructura que
> contiene castellano ingles y contadores de aciertos y fallos
>        char castellano[30];
>        char ingles[30];
>        int cont_aciertos;
>        int cont_errores;
>        };
>
>
> int main (void)
>
> {
>     FILE *fichero;                       // apunta al fichero donde se
> guardaran las palabras y sus aciertos/fallos
>     struct t_palabra palabra;            // definim la variable paraula.
>     char respuesta[50];                  // l'usuari entra la seva resposta
>     int i;                               // recorrer el ficher
>
> struct t__virt_palabra {                    // l'utilitzo per augmentar els
> contadors cada cop k l'usuari practica 1 paraula. (nose una altre manera de
> fer-ho)
>        char virt_castellano[30];
>        char virt_ingles[30];
>        int virt_cont_aciertos;
>        int virt_cont_errores;
>        };
> struct t__virt_palabra virt_palabra;        // definim la variable
> virt_palabra
>
>     fichero = fopen ("datos.dat", "rb+");              // s'obre el ficher
> datos.dat. rb+ es correcte????? al ficher hi ha tant caracters
>                                                        // castellano,
> ingles, com enters (els contadors) x tant te que ser binari, no?
>
>     if (fichero == NULL)                                 // salta en cas
> que no existeixi l ficher datos.dat
>        printf ("Error: No se ha podido abrir el fichero datos.dat.");
>
>     else
>     {
>         i=0;
>         strcpy (respuesta, "hola");
>         virt_palabra.virt_cont_aciertos = 0;
>         virt_palabra.virt_cont_errores = 0;
>
>         fseek(fichero, i*sizeof(struct t_palabra), SEEK_SET); // se pone el
> cursor al inicio de todo xk i=0
>
>         while (!feof(fichero))                        // preguntar al
> usuari paraules, fins k sarrivi a la ultima paraula,
>         {                                                     // despres
> d'aquesta tindria que parar!!!!! i no ho fa :s, tornar a preguntar
>                                                               // sempre la
> ultima :(
>             if(fread(&palabra, sizeof(palabra), 1, fichero)) {
>
>             //fread(&palabra, sizeof(palabra), 1, fichero);     // en la
> primera iteracio, llegirm la primera paraula gracies a i=0
>             printf ("\nEscribe la traduccion de...: ");       // preguntem
> la paraula
>             printf ("\n%s: ", palabra.castellano);
>             gets(respuesta);                                  // l'usuari
> entra la paraula
>
>             // analitzar si l'usuari la encertat, o fallat, i incrementar
> els contadors corresponents x cada paraula
>                             if (strcmp(respuesta, palabra.ingles) == 0)  //
> compara resposta amb palabra.ingles si es correcte...
>                             {
>                             printf ("\nCorrecto!");           // felicitem
> al usuari x cortesia, tenim que incrementar el contador d'encerts
>
>                                    // com que no es pot modificar nomes 1
> apartat de la estructura paraula, tenim que introduir de nou tot...
>                                    // copiem a la variable virtual (nomes
> serveix x traspar informacio) la paraula i la seva traduccio
>                                    strcpy (virt_palabra.virt_castellano,
> palabra.castellano);
>                                    strcpy (virt_palabra.virt_ingles,
> palabra.ingles);
>                                    // incrementem el contador una unitat
>                                    //palabra.cont_aciertos a la primera
> iteració val 0 (aixi sa inicialitzat)
>                                    // i ho guardem a la virtual tb, x tal d
> copiar tot again.
>                                    virt_palabra.virt_cont_aciertos =
> palabra.cont_aciertos + 1;
>
>                                    // important: com que hem utilitzat
> fread, el curso esta darrera la paraula llegida ara!!
>                                    // la variable virtual conte les noves
> dades, es a dir, amb el contador incrementat,
>                                    // x tant, tenim que ficar el cursor al
> inici de la paraula k estavem treballant, xk
>                                    // escrigui la informacio just a sobre
> de la paraula antiga
>                                    // ara la i estava a la posicio dspres
> de size of (equivalent a i=0), es a dir, dspres de la primera paraula
>                                    // en la primera iteració, ja que la i
> val 0, amb aquesta comanda tornem a la posicio inical
>
>                                    fseek(fichero, i*sizeof(struct
> t_palabra), SEEK_SET);
>
>                                    strcpy (palabra.castellano,
> virt_palabra.virt_castellano);
>                                    strcpy (palabra.ingles,
> virt_palabra.virt_ingles);
>                                    palabra.cont_aciertos =
> virt_palabra.virt_cont_aciertos;
>
>                                    // i podem sobreescriure la paraula que
> voliem
>
>                                    fwrite (&palabra, sizeof(palabra), 1,
> fichero);
>                                    // important, el cursor torna a estar
> darrera de la primera paraula (en primera iteracio)
>
>
>                             }      // sino es correcte...
>
>
>                             else
>                                 {
>
>                                 printf ("\nIncorrecto.");
>
>
>                                    virt_palabra.virt_cont_errores =
> palabra.cont_errores + 1; // mateixa estrategia
>                                    strcpy (virt_palabra.virt_castellano,
> palabra.castellano);
>                                    strcpy (virt_palabra.virt_ingles,
> palabra.ingles);
>
>                                    fseek(fichero, i*sizeof(struct
> t_palabra), SEEK_SET);
>
>                                    strcpy (palabra.castellano,
> virt_palabra.virt_castellano);
>                                    strcpy (palabra.ingles,
> virt_palabra.virt_ingles);
>                                    palabra.cont_errores =
> virt_palabra.virt_cont_errores;
>
>
>
>                                    fwrite (&palabra, sizeof(palabra), 1,
> fichero);
>                                    // important, ara el cursor esta despres
> de la paraula treballada
>
>                                 }
>
>             // hem acabat la primera iteracio
>
>
>             i++; // incrementem la i, per tal danar a la propera paraula.
>             fseek(fichero, i*sizeof(struct t_palabra), SEEK_SET);   //
> coloquem el cursor a la seguent posicio, es a dir, a la posicio 1,
>                                                                     // es a
> dir, a la segona paraula. nem cap a dalt, ja que al ficher
>                                                                     //
> encara hi ha paraules, i tooorneeem a fer el while.
>             }
>             else {
>                  printf ("\nfin!");
>                  }
>             }
>
>
>         fclose (fichero);
>
>
>         }
>
>
> fflush(stdin);
> printf("\n\nPulse Intro para finalizar...");
> getchar();
>
>
>
> }
>
>
> El 5 de marzo de 2012 23:12, Salvador Pozo <salvador en conclase.net> escribió:
>
>> El pasado 2012-03-05 21:30:06, Albert_Munich escribió:
>>
>> A> Hola, he intentado siguiendo tus indicaciones solucionar el problema,
>> he
>> A> creado un contador, que recorre el fichero, y ahora lee todo ordenador,
>> a
>> A> mas con la funcion feof nueva ya no se va hasta el infinito. el
>> problema
>> A> ahora esta en la primera palabra que lee y la ultima.
>> A> la primera palabra no la lee, va directo a la segunda, y la ultima
>> palabra
>> A> no la repite infinitamente, xo la repite 1 vez mas, es decir, la pone
>> dos
>> A> veces. no se como solucionarlo, ya que el contador con i=0 indica
>> clarament
>> A> que lea la primera palabra, y con la funcion feof, en teoria, no
>> tendria k
>> A> volver a entrar en el while, por tanto, no entiendo porque repite la
>> ultima
>> A> palabra antes de acabar.
>>
>> Hola:
>>
>> Esta vez es más fácil. El error está aquí:
>> ----8<------
>>         if(fread(&palabra, sizeof(palabra), 1, fichero)) {
>>            fread(&palabra, sizeof(palabra), 1, fichero);
>> ...
>> ----8<------
>>
>> El fallo es leer dos veces la palabra, con la lectura del interior del
>> "if" es suficiente. En la primera iteración, la segunda lectura anula la
>> lectura de la primera palabra, por eso no sale la primera.
>>
>> En la última iteración la segunda lectura falla, pero se mantiene la
>> palabra leída en la primera (la del if).
>>
>> Puedes compactar mucho tu programa:
>> - No necesitas la estructura t__virt_palabra para nada. Ya que lees una
>> estructura "palabra" desde el fichero, para actualizar el fichero bastará
>> con incrementar palabra.errores o palabra.aciertos, y volver a usar la
>> misma "palabra" para escribirla en el fichero, en la posición en la que
>> estaba. Esto te evita asignar valores que no cambian: las palabras y el
>> contador que no modificas.
>> - Evita repetir el código, por ejemplo, cuando verificas si el usuario ha
>> acertado o no la respuesta, muchas de las sentencias son comunes tanto al
>> if como al else, saca esas sentencias del bloque if..else.
>> - No necesitas asignar un valor inicial a la respuesta, ya que la primera
>> vez que se evalúa es después de leerla desde el teclado.
>> - Evita usar la función gets, en su lugar usa fgets, por ejemplo,
>> fgets(respuesta, 30, stdin);
>>
>> Hasta pronto.
>>
>> --
>> Salvador Pozo (Administrador)
>> mailto:salvador en conclase.net
>> _______________________________________________
>> Lista de correo Cconclase Cconclase en listas.conclase.net
>> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
>> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>>
>


-- 
Ing. Oscar Alberto Barnett Contreras
Docente Informatica -  UNMSM
Cel. 99867-6932
------------ próxima parte ------------
A non-text attachment was scrubbed...
Name: aporte.cpp
Type: text/x-c++src
Size: 3848 bytes
Desc: no disponible
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20120305/bacdc13d/attachment-0001.bin>
------------ próxima parte ------------
A non-text attachment was scrubbed...
Name: datos.dat
Type: application/octet-stream
Size: 204 bytes
Desc: no disponible
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20120305/bacdc13d/attachment-0001.obj>


Más información sobre la lista de distribución Cconclase