1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
// 3x05: Compresión y descompresión de secuencias de caracteres /* La técnica de compresión de datos RLE (Run Length Encoding) se utiliza para reducir el tamaño de los ficheros de datos. Se basa en la sustitución de una secuencia de datos repetidos, por un dato especial (marcador) seguido del número de repeticiones y del dato que se repite. Evidentemente, dicha sustitución se realiza sólo en los casos en los que resulte favorable. Utilizando el carácter ‘\’ como marcador, un ejemplo sería partir de la secuencia “aaaaaaabbccccddde\fg.”, de la que obtendríamos “\7abb\4cddde\1\fg.”. Obsérvese que sólo se sustituye a y c porque se ahorra espacio, mientras que en el resto de los casos o no se gana nada (d) o incluso se pierde. Un caso especial se produce cuando hay caracteres marcadores, que se sustituyen siempre aunque no estén repetidos. Leyendo carácter a carácter, escribe un programa que lea de teclado una secuencia de caracteres terminada en ‘.’ y visualice la secuencia comprimida según la técnica explicada. En una segunda opción, debe permitir también realizar el paso contrario, de secuencia comprimida a descomprimida. */ /* Problemas conocidos: En el programa se ha considerado que una secuencia de caracteres solo esta compuesta de letras, por lo que si se encuentra una barra se entiende que después ha de ir un numero de uno o mas dígitos que multiplicara el siguiente carácter que será una letra. */ #include <stdio.h> main(){ enum opcciones{ secuencia=1, comprimido=2, salir=3 } opc; int eleccion, carRep, bol, i; char car, carAct, carAnt; // Repetición del programa hasta que se decida salir: do{ system("clear"); // Menú de selección: printf("Elija una de las siguientes opciones:\n"); printf(" 1. Convertir una secuencia a formato comprimido.\n"); printf(" 2. Pasar de formato comprimido a una secuencia.\n"); printf(" 3. Salir\n\v"); do{ scanf( "%i", &eleccion ); }while( eleccion < 1 || eleccion > 3 ); opc = (enum opcciones)(eleccion); bol = 1; carRep = 0; // Se pasa de secuencia a RLE: if( eleccion == secuencia ){ // Se solicita un conjunto de caracteres terminado en '.', a cada vuelta se va leyendo un carácter del buffer y se trata según convenga, cuando salga '.' se termina. printf("Introduzca la secuencia terminada en \'.\'\nEjemplo: \"aaaaaaabbccccddde.\"\n\v"); do{ // Se lee el carácter actual scanf( "%c", &carAct ); // Si es la primera vuelta, se copia el carácter actual dentro de carácter anterior: if(bol==1){ carAnt = carAct; bol=0; }; // Si carácter anterior es igual a carácter actual se suma uno en el contador: if( carAnt == carAct){ carRep++; } else{ //En caso contrario: //Si la letra se ha repetido al menos cuatro veces, se acorta: if( carRep >= 4 ){ printf("\\%i%c", carRep, carAnt ); } else{ //En caso contrario se hace un bucle que la imprime de 1 a 3 veces: for( i=1; i<=carRep; i++ ){ printf("%c", carAnt ); }; }; // Como la letra es diferente se pone el contador a 1: carRep = 1; }; // Se copia el carácter actual dentro del carácter anterior, antes de coger de nuevo un carácter del buffer: carAnt = carAct; }while( carAct != '.' ); printf("\n\v"); }; // Se pasa de RLE a secuencia: if( eleccion == comprimido ){ // Se solicita la secuencia comprimida terminada en '.' printf("Introduzca la secuencia comprimida terminada en \'.\'\nEjemplo: \"\\7abb\\4cddde.\"\n\v"); do{ // Se recoge un carácter del buffer: scanf( "%c", &carAct ); // Si el carácter leído es una contrabarra: if( carAct == '\\' ){ //Se recogen otros dos caracteres, el primero es el numero de repeticiones y el segundo es el caracter: scanf( "%i", &carRep ); scanf( "%c", &car ); //Se imprime el carácter tantas veces como marque el numero de repeticiones: for( i=1; i<=carRep; i++ ){ printf( "%c", car ); }; } else{ // En caso de el carácter no sea barra se imprime sin mas: printf( "%c", carAct ); }; }while( carAct != '.' ); printf("\n\v"); }; // Se continúa el programa después de pulsar intro: if( eleccion != salir ){ printf("Pulse intro para mostrar el menu.\n"); scanf("%c", &carAnt); do{ scanf("%c", &carAnt); }while( carAnt != '\n' ); }; }while( eleccion != salir ); system("clear"); }; |