Autor
|
Tema: compresor/descompresor de archivos (Leído 5,559 veces)
|
m@o_614
Desconectado
Mensajes: 389
|
Saludos Tengo el siguiente codigo que me tiene que comprimir un archivo cuando aparecen las siguientes palabras: de , para , con , desde , al ,y se tienen que sustituir con los siguientes signos: *, /, + ,- ,@ y escribir el texto comprimido(con las sustituciones) en otro archivo. El programa compila correctamente y me hace lo que le pido pero tiene algunos fallos, por ejemplo cuando utilizo sizeof() en unos for para sacar el numero de elementos me aparecen warnings, y tambien por ejemplo, yo se que el tamanio del texto que voy a comprimir es de 96 caracteres, por eso lo puse asi en los arreglos, pero si mi maestra quiere que me abra un archivo mas grande o mas chico no se si funcionara, como puedo corregir esto??como puedo hacer que funcione para cualquien tamanio de texto??ahh!! y otra duda, mi profesora nos dijo algo de que no queria que el archivo se sobreescribiera y que checaramos eso, no se bien a que se referia si alguien me pudiera ayudar tambien con eso se lo agradeceria #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 100 char ver_signos(char signo[],int i); char *comprimir_archivo(char signo[],char arreglo[]); int main() { int i,tam,ini; char nombre[MAX],archivo[MAX],arreglo[96],*palabra,*producto,car,opcion,*ptr,sig; char *p[]={" de "," para "," con "," desde "," al "}; char signo[]={'*','/','+','-','@'}; FILE *fd,*ap; printf("Dame el nombre del archivo: "); if((ptr = strchr(nombre ,'\n')) != NULL ) *ptr = '\0'; sprintf(archivo ,"F:\\%s.txt",nombre ); ap = fopen("F:\\Archivo_producto.txt","w"); if((fd = fopen(archivo ,"r"))!= NULL ) { printf("a) Comprimir archivo\n"); printf("b) Descomprimir archivo\n"); { case 'A':case'a': for(i=0;i < 5;i++) { while((car = fgetc(fd ))!= EOF ) { if(car == ' ') { palabra = (char*)malloc((tam +1)*sizeof(char)); if((strcmp(palabra ,p [i ]))== 0) { sig = ver_signos(signo,i); arreglo[ini-1] = sig; } } } } producto = comprimir_archivo(signo,arreglo); break; // me gustaria ponerle aqui el fwrite(arreglo,sizeof(char),strlen(arreglo),ap); case 'B': case 'b':/* for(i = 0;i < sizeof(signo);i++) { while((car = fgetc(ap))) } break;*/ default: printf("La opcion no existe\n"); } } else printf("No se pudo abrir el archivo"); return 0; } char ver_signos(char signo[],int i) { int j; for(j = 0;j < sizeof(signo);j++)// warning por usar sizeof { if(j == i) return(signo[j]); } } char *comprimir_archivo(char signo[],char arreglo[]) { int tam[]={4,6,5,7,4},i,j,k; char a[96]; for(i=0; i < sizeof(signo);i++)//warning por usar sizeof { for(j = 0,k = 0;j < 96;k++) { if(arreglo[j] == signo[i]) { a[k] = arreglo[j]; j = j+tam[i]; } else { a[k] = arreglo[j]; j++; } } } return arreglo; }
Estas son las unicas fallas que le encontre al codigo, alomejor hay mas que no he notado, las sugerencias para hacerlo mas eficientes son bienvenidas de antemano gracias
|
|
« Última modificación: 3 Octubre 2013, 21:33 pm por m@o_614 »
|
En línea
|
|
|
|
eferion
Desconectado
Mensajes: 1.248
|
sizeof no funciona por arte de magia. sizeof no es una función normal de c... es más como una directiva de precompilador. sizeof únicamente puede calcular el tamaño de arrays si éstos se le pasan completos, es decir: char array[20]; char *array2[] = &array; int size1 = sizeof( array ); // size1 = 20 int size2 = sizeof( array2 ); // size2 = 4... es un puntero int size3 = sizeof( *array2 ); // warning, no se puede calcular
Si necesitas conocer el tamaño del array, o bien lo tienes que pasar como parámetro, o bien, en el caso de cadenas de caracteres, terminas la cadena con '\0' y lo que haces es buscar la posición de ese carácter para determinar su tamaño... por ejemplo con strlen. Si no quieres que se sobreeescriba el fichero, utiliza un tercer fichero para descomprimir... pide el nombre o bien ponle un prefijo / sufijo al archivo que introduzca el usuario. Entonces, para comprimir pasas del fichero base al que te facilita el usuario, como hasta ahora, y para descomprimir pasas del facilitado por el usuario a este nuevo que te digo. Para comprobar el funcionamiento de tu programa con archivos más grandes prueba a crearte tus propios archivos, no tengas miedo... además es la mejor forma de comprobar si tu programa funciona correctamente en todas las circunstancias. PD.: si pones un de, para, con, desde o al al principio o al final de una línea no te va a funcionar el programa... deberías mirar eso.
|
|
|
En línea
|
|
|
|
m@o_614
Desconectado
Mensajes: 389
|
gracias eferion por tu respuesta, tienes razon estuve checando con varios archivos y si me di cuenta que tiene mas fallas, tal vez tenga que cambiar todo el algoritmo porque por ejemplo cuando tengo el texto:
El libro de Mary es para la clase de mate con la maestra Ana
el codigo va a fallar cuando llegue al 'para', porque el algoritmo cuando se encuentra un ' ' en el archivo lo que va a hacer es tomar los ese caracter vacio y los siguientes 5 caracteres en este caso,( 5 porque " para "tiene 6 caracteres), entonces ese para lo va a pasar por alto y no la va a hacer correctamente, entonces voy a tener que cambiar casi todo el algoritmo :s
|
|
|
En línea
|
|
|
|
eferion
Desconectado
Mensajes: 1.248
|
No desesperes... son cosas que pasan.
|
|
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
Tengo el siguiente codigo que me tiene que comprimir un archivo cuando aparecen las siguientes palabras: de , para , con , desde , al ,y se tienen que sustituir con los siguientes signos: *, /, + ,- ,@ y escribir el texto comprimido(con las sustituciones) en otro archivo. Leer las lineas de texto del archivo y comprimirlas son dos operaciones que deberías separar en funciones, esto para hacer mas fácil el desarrollo del programa. En la lectura del archivo sigues con algunos errores que ya te había comentado como almacenar el valor de retorno de fgetc en una variable de tipo char cuando debería ser de tipo int, si no lo haces puedes tener problemas para detectar el estado de fin de archivo. En cuanto a la compresión puedes verificar cada carácter de la linea y si este es un espacio comparar el resto utilizando la función strncmp, un programa de ejemplo: #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char linea[] = "El libro de Mary es para la clase de mate con la maestra Ana"; char *palabra[] = {" de "," para "," con "," desde "," al "}; size_t num_pals = sizeof palabra / sizeof palabra[0]; char ch[] = "*/+-@"; size_t i; size_t j; i = 0; while (linea[i] != 0){ if (linea[i] == ' ') for (j = 0; j < num_pals; j++) break; if (linea[i] == ' ' && j != num_pals){ }else } return EXIT_SUCCESS; }
También hay que considerar que la entrada puede tener alguno de los caracteres utilizados para la compresión ('*', '/', etc.), de existir lo usual es escapar el carácter agregando un carácter especial antes de este, por ejemplo en C para imprimir la diagonal invertida se debe utilizar '\\'. Un saludo
|
|
|
En línea
|
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
|
|
|
m@o_614
Desconectado
Mensajes: 389
|
muchas gracias rir3760 tratare de corregir eso ultimo y la variable de retorno del fgetc, una ultima duda, si tambien tengo que hacer el descompresor seria conveniente usar una lista doblemente ligada para almacenar cada uno de los caracteres del archivo en un nodo, y que cuando me aparezca un *, /, -, + ,cree otro nodo con la palabra completa y ya hacer los enlaces en la lista??? no se si me di a entender lo que quiero hacer, por ejemplo si tengo El libro*Mary es/la clase*mate-la maestra Ana y que despues me queden las palabras en vez de los signos. El libro de Mary es para la clase de mate con la maestra Ana saludos
|
|
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
En tu caso descomprimir es todavía mas fácil ya que solo debes verificar si el carácter se debe imprimir tal cual o en su lugar se debe imprimir una cadena. Para eso lo mas sencillo es utilizar una tabla de valores. Por ejemplo: #include <stdio.h> #include <stdlib.h> #include <limits.h> /* UCHAR_MAX */ int main(void) { char linea[] = "El libro*Mary es/la clase*mate+la maestra Ana"; char ch[UCHAR_MAX] = {0}; char set[] = "*/+-@"; char *cadena[] = {" de "," para "," con "," desde "," al "}; int i; int pos; /* Los caracteres especiales toman valores mayores que cero */ for (i = 0; set[i] != '\0'; i++) ch[set[i]] = i + 1; for (i = 0; linea[i] != '\0'; i++){ pos = ch[linea[i]]; if (pos) printf("%s", cadena [pos - 1]); else } return EXIT_SUCCESS; }
Un saludo
|
|
|
En línea
|
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
|
|
|
m@o_614
Desconectado
Mensajes: 389
|
Saludos rir3760 nunca se me hubiera ocurrido lo de la tabla de valores, lo unico que se me ocurrio fue hacer una lista doblemente ligada que es mas laboriosa, pero ps ya la empece, ahora tengo que terminarla. lo que hice fue leer el archivo al reves para que pudiera ingresar cada uno de los caracteres del archivo por la cabeza de una lista, porque si lo hubiera leido desde el principio tendria que buscar el fin de lista para ingresarle el caracter en su posicion correcta y era mas complicada por eso mejor alreves para que me ingresara en orden el problema que tengo es que en el typedef struct el dato lo tengo declarado como caracter, para ir ingresando caracter por caracter a la lista enlazada, pero despues una vez que recorro la lista busco ' *',' + ', '/ ' y lo encuentra le pido que me haga un nodo que contenga la palabra que le corresponde, por ejemplo si es * la palabra sera _de_ pero esta seria una cadena y en el typedef la tengo declarada como un solo caracter, un char, como puedo solucionar esto??? y el fgetc ya se que tiene que ser int en vez de char, pero si lo pusiera como int ya no me regresaria el caracter que le voy a enviar a la funcion de insertar_cabeza #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 100 typedef struct elemento { char dato; struct elemento *sig; struct elemento *ant; }Nodo; typedef struct pal { char *dato; struct pal *sig; struct pal *ant; }Palabra; Nodo *crear_nodo(char car); Palabra *crear_palabra(char *p[],int i); void insertar_cabeza(Nodo **cabeza,char car); void recorrer_lista(Nodo *cabeza); void buscar_elemento(char signo[],char *p[],Nodo *cabeza); int main() { int pos; Nodo *cabeza = NULL; char nombre[MAX],archivo[MAX],car,opcion,*ptr,*p[]={" de "," para "," con "," desde "," al "}; char signo[]={'*','/','+','-','@'}; FILE *ap; printf("Dame el nombre del archivo: "); if((ptr = strchr(nombre ,'\n')) != NULL ) *ptr = '\0'; sprintf(archivo ,"F:\\%s.txt",nombre ); if((fd = fopen(archivo ,"r"))!= NULL ) { printf("a) Comprimir archivo\n"); printf("b) Descomprimir archivo\n"); { case 'A':case'a': // Aqui va el compresor break; case 'B': case 'b': if((ap = fopen("F:\\Archivo_producto.txt","r"))!=NULL ) { for(pos-=1;pos >= 0;pos--) { insertar_cabeza(&cabeza,car); } buscar_elemento(signo,p,cabeza); //recorrer_lista(cabeza); } else printf("No se pudo abrir archivo"); break; default: printf("La opcion no existe\n"); } } else printf("No se pudo abrir el archivo"); return 0; } Palabra *crear_palabra(char *p[],int i) { Palabra *x; x = (Palabra *)malloc(sizeof(Palabra )); x->dato = p[i]; x->sig = x->ant = NULL; return x; } Nodo *crear_nodo(char car) { Nodo *x; x = (Nodo *)malloc(sizeof(Nodo )); x->dato = car; x->sig = x->ant = NULL; return x; } void insertar_cabeza(Nodo **cabeza,char car) { Nodo *nuevo; nuevo = crear_nodo(car); nuevo->sig = *cabeza; nuevo->ant = NULL; *cabeza = nuevo; } void recorrer_lista(Nodo *cabeza) { Nodo *indice; for(indice = cabeza;indice != NULL;indice = indice->sig) } void buscar_elemento(char signo[],char *p[],Nodo *cabeza) { int i; Nodo *indice; Palabra *ptro; for(i=0;i < 5;i++) { for(indice = cabeza;indice != NULL;indice = indice->sig) { if(indice->dato == signo[i]) { ptro = crear_palabra(p,i); /* indice->sig->ant = ptro; aqui tengo warnings ptro->ant = indice; ptro->sig = indice->sig; indice->sig = ptro;*/ } } } }
muchas gracias y disculpa las molestias por tanta preguntadera
|
|
« Última modificación: 5 Octubre 2013, 19:08 pm por m@o_614 »
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
lo unico que se me ocurrio fue hacer una lista doblemente ligada que es mas laboriosa, pero ps ya la empece, ahora tengo que terminarla. Si en tu centro de estudios te piden que lo hagas de esa manera bueno, no tienes mas mas opción que hacerlo así pero no deja de ser una solución extremadamente complicada. lo que hice fue leer el archivo al reves para que pudiera ingresar cada uno de los caracteres del archivo por la cabeza de una lista, porque si lo hubiera leido desde el principio tendria que buscar el fin de lista para ingresarle el caracter en su posicion correcta y era mas complicada por eso mejor alreves para que me ingresara en orden Ya te había comentado en otro tema que no deberías utilizar fseek para posicionarte (en la forma que lo haces) en un stream en modo texto. Soluciones realmente sencillas hay varias, supongamos que el archivo contiene los caracteres "ABCDE" y tu los insertas de la forma usual en la lista, esta contiene "EDCBA". Opciones: A) Creas una función que invierta la lista, no mas de diez lineas de código. B) Ya que la lista es de vinculo doble simplemente los procesas al revés empezando por el ultimo y terminando con el primero, para ello te mueves por la lista utilizando el puntero al nodo previo. el problema que tengo es que en el typedef struct el dato lo tengo declarado como caracter, para ir ingresando caracter por caracter a la lista enlazada, pero despues una vez que recorro la lista busco ' *',' + ', '/ ' y lo encuentra le pido que me haga un nodo que contenga la palabra que le corresponde, por ejemplo si es * la palabra sera _de_ pero esta seria una cadena y en el typedef la tengo declarada como un solo caracter, un char, como puedo solucionar esto? Estas enfocando mal el problema. Supongamos que tu lista contiene los caracteres "Casa*Jose" y se debe expandir a "Casa de Jose" ahi los pasos son: 1) Iteras por cada nodo en la lista verificando si es un carácter especial. 2) Si el carácter es especial sustituyes el nodo (siguiendo el ejemplo) '*' por los nodos ' ', 'd', 'e' y ''. En resumen no tienes que manejar distintos tipo de datos, solo expandir o contraer la lista. Un saludo
|
|
|
En línea
|
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
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
¿Existe algun Descompresor para Archivos Comprimidos con BJFnt(v1.2)?
Ingeniería Inversa
|
--<<<@u6u$t0>>>--
|
2
|
5,023
|
27 Julio 2005, 22:09 pm
por --<<<@u6u$t0>>>--
|
|
|
[SRC] Compresor de Archivos Huffman
Java
|
Amerikano|Cls
|
9
|
14,038
|
26 Junio 2009, 23:08 pm
por Amerikano|Cls
|
|
|
PeaZip 3.6.2: compresor y descompresor de archivos gratuito
Noticias
|
wolfbcn
|
0
|
1,804
|
28 Febrero 2011, 18:13 pm
por wolfbcn
|
|
|
PeaZip 3.9: Compresor y descompresor de archivos gratuito con nueva versión
Software
|
wolfbcn
|
0
|
2,283
|
2 Agosto 2011, 18:40 pm
por wolfbcn
|
|
|
CompactGUI: el compresor de archivos mágico que triplica el tamaño de tu disco..
Noticias
|
wolfbcn
|
3
|
2,560
|
15 Noviembre 2017, 10:57 am
por Bad Heaven
|
|