EOF en archivo antes de su verdadero final

Iniciado por XafiloX, 29 Noviembre 2011, 19:47 PM

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

XafiloX

Hola, estoy intentando hacer un programa en C que descubra si un archivo de Word tiene un pie de página...Para ello tengo que buscar una secuencia de de caracteres en el archivo y me he montado una funcioncilla que es la siguiente:
int buscar(FILE * fp, char * cadena){
    char car;
    int longi = strlen(cadena);
    if(longi < 1)
        return -2;
    int i=0;
    int k=0;
    while((car = fgetc(fp)) != EOF){
        if(car == cadena[i]){
            k++;
            while(i+1<(longi-1) && !feof(fp) && (car=fgetc(fp)) == cadena[++i])
                k++;
            if(k == longi-1)
                return 0;
            else if(feof(fp))
                return -1;
            else
                i=k=0;   
           
        }
    }
    return -1;
   
}


La he probado con archivos de texto y funciona perfectamente...
El problema es que cuando le paso el .doc o .docx deja de buscar antes de llegar al final del archivo...he abierto el .doc con un editor hexadecimal y me he encontrado que dentro del propio archivo hay caracteres con FF y por lo tanto en cuanto se llega allí se cree que es el EOF y termina la búsqueda...
¿Hay alguna forma de detectar que no es el auténtico fin de fichero y continuar la búsqueda?

do-while

¡Buenas!

Si abres los ficheros en modo texto te puede suceder lo que cuentas. En este caso lo que tienes que hacer es abrirlo en binario y cargar el fichero en un vector dinamico de caracteres y realizar la busqueda sobre dicho vector. Estas dos funciones te ayudaran:


unsigned long flen(FILE *f)
{
   unsigned long pos, len;

   pos = ftell(f);
   fseek(f , 0 , SEEK_END);
   len = ftell(f);
   fseek(f , pos , SEEK_SET);

   return len;
}

int cargar_fichero(FILE *f, char **contenido, unsigned logn *nbytes)
{
  if(!(*contenido = (char*) malloc((*nbytes = flen(f)) * sizeof(char))))
       return 0;

   return fread(*contenido , (*nbytes) * sizeof(char) , 1 , f);
}


Ahora podras realizar las busquedas sobre el contenido del vector. Pero aunque modifiques el vector para terminar en '\0' no te aconsejo usar las funciones de manejo de cadenas, ya que tambien podria haber caracteres nulos antes del final del fichero. Puedes utilizar las de manejo de memoria con cuidado de no sobrepasar los limites del fichero...

¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!

XafiloX


XafiloX

Llevo toda la tarde intentándolo hacer funcionar, pero por algún motivo el fread parece que no funciona, porque ft no tiene el inicio del texto del archivo...
He probado todo lo que se me ha ocurrido y no he conseguido nada...fread devuelve que ha leido el número de caracteres correcto, pero luego nada, no están los caracteres que deberían estar...

Pongo aquí el código que tengo hecho (es posible que esté un poco guarrete de tanto poner printf's)...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int buscar(char * ft, char * cadena, unsigned long * bytes);
unsigned long flen(FILE *f);
int cargar_fichero(FILE *f, char *contenido, unsigned long *nbytes);

int main (int argc, char* argv[]){
    int i;
    FILE * fp;
    char * ft;
    int a;
    unsigned long bytes;
    char data[] = {0x0D, 0x0C, 0x0D, 0x0D, 0x03, 0x0D, 0x0D, 0x04, 0x0D, 0x0D, 0x03, 0x0D, 0x0D, 0x04, 0x0D, 0x0D, 0x00};
    for(i=1; i < argc; ++i){
        fp = fopen(argv[i], "rb");
        if(fp != NULL){
            if((a=cargar_fichero(fp, ft, &bytes)) == 0)
            return -1;

            if(buscar(ft, "footnotes.xml", &bytes) == 0)
                printf("%s\n", argv[i]);
            else{
                printf("\n");
                fseek ( fp , 0 , SEEK_SET ); //Devolvemos puntero al inicio
                if(buscar(ft, data, &bytes) == 0)
                    printf("%s\n", argv[i]);
            }
            return 0;
            fclose(fp);

        }else
            printf("No se ha podido abrir el archivo %s", argv[i]);

    }
    return 0;
}
/*
    Busca en el archivo la cadena indicada (imitiendo el \0)
*/
int buscar(char * ft, char * cadena, unsigned long * bytes){

    int longi = strlen(cadena);
    if(longi < 1)
        return -2;
    int i=0;
    int k=0;
    while(i < *bytes){printf("Va bien con c=%x, k=%d\n", ft[i], k);
        if(ft[i] == cadena[k]){
            k++;
            while(k < longi && ++i < *bytes && ft[i] == cadena[k])
                k++;
            if(k == longi)
                return 0;
            else if(i >= *bytes){
                return -1;
            }else{
                k=0;
            }
        }else
        ++i;

    }
    return -1;

}

unsigned long flen(FILE *f){
    unsigned long pos, len;

    pos = ftell(f);
    fseek(f , 0 , SEEK_END);
    len = ftell(f);
    fseek(f , pos , SEEK_SET);

    return len;
}

int cargar_fichero(FILE *f, char *contenido, unsigned long *nbytes){
     if((contenido = (char*) malloc((*nbytes = flen(f)) * sizeof(char))) == NULL)
        return 0;


    return fread(contenido , sizeof(char) , (*nbytes/sizeof(char)) , f);
}

do-while

¡Buenas!

Eso te pasa por modificar el codigo que puse.

El segundo parametro de la funcion cargar_fichero tiene que ser un puntero a un puntero, sino es imposible modificar un puntero exterior a la funcion (variables globales a parte...), que es lo que te hace falta. Y, por cierto, cuando acabes de usar el vector que contiene los datos tendras que liberar la memoria utilizada.

¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!

XafiloX

Jeje, esta tarde me he dado cuenta de eso...a partir de ahora seguiré la máxima de no tocarás código ajeno   ;D
He conseguido echar a andar el código pero he tenido que poner todo el código de la función cargar_fichero en el main porque no consigo llamar correctamente a la función...
La verdad es que todavía estoy intentando terminar de entender los punteros...
Yo a tu función cargar fichero la llamo más o menos así:
FILE * fp = fopen(argv[i], "rb");
char ** contenido;
unsigned long bytes;
cargar_fichero(f, contenido, &bytes);

y después a buscar le paso
buscar(*ft, cadena, &bytes)
¿Qué es lo que estoy haciendo mal con los punteros?, porque me daba un fallo de segmentación creo que en el malloc...por eso he puesto el código de la función en el main y en vez de crear contenido como un char ** lo he creado como un char * y así si que he conseguido que funcionase...

Muchas gracias por la ayuda!

rir3760

El "char **" que espera la funcion "cargar_fichero" debe ser la direccion en memoria de la variable de tipo "char *" que almacenara la direccion del bloque:
FILE *fp = fopen(argv[i], "rb");
char *contenido;
unsigned long bytes;

cargar_fichero(f, &contenido, &bytes);

Ello para que asi se puede modificar la variable "contenido" dentro de la funcion "cargar_fichero" (es la emulacion del paso por referencia en C).

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

do-while

¡Buenas!

Por cierto, me he dado cuenta de un gran error en cargar_fichero, antes de leer no sabemos en que posicion se encuentra. Lo correcto seria:


int cargar_fichero(FILE *f, char **contenido, unsigned logn *nbytes)
{
    unsigned long posicion;
    int retorno;   

    if(!(*contenido = (char*) malloc((*nbytes = flen(f)) * sizeof(char))))
        return 0;

    posicion = ftell(f);
    fseek(f , 0 , SEEK_SET);

    retorno = fread(*contenido , (*nbytes) * sizeof(char) , 1 , f);

    fseek(f , posicion , SEEK_SET);

    return retorno;
}


¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!

XafiloX

Muchas gracias a ambos! AL final el programilla que estaba haciendo no ha tenido mucha utilidad, porque no he conseguido encontrar el patrón que sigue para los .docx (si para los .doc), pero aun así me ha servido para aprender algunas cosillas gracias a vuestra ayuda.  :D
Un saludo!