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 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
/* 4x01-Fichero_de_texto_interactivo 13/12/2011 Escribe un programa que analice el fichero de texto cuyo nombre se especifica interactivamente y muestre por pantalla la siguiente información: a. Para cada línea del fichero: • El número total de caracteres y de palabras, y la longitud media de una palabra. • La letra con que termina la primera palabra y el número de palabras que terminan con esa letra. b. Para el fichero completo: • El número total de caracteres, palabras y líneas del fichero, y la longitud media de una palabra. • El número de la línea en la que hay más palabras, junto con el número de palabras en esa línea. • El número de la línea en la que hay más palabras que acaban como la primera, junto con el número de esas palabras. Para ello se diseñarán dos procedimientos (adecuadamente parametrizados): uno para procesar una línea del fichero de texto, y otro para procesar una palabra. */ /* Notas: El final de una palabra se da al finalizar con un carácter distinto de espacio y a continuación encontrar un espacio, es decir: "Izquierda Unida se ha quedado fuera." son 6 palabras, varios espacios juntos no se tienen en cuenta. Si una palabra tiene números o caracteres intercalados, pero no espacios, sigue siendo una palabra hasta que aparezca un espacio. Si una palabra termina en punto o coma, esta terminando en punto o coma, no en numero ni letra, si no en punto o coma. Los caracteres son todo carácter que se encuentre de principio a fin salvo el carácter de salto de linea. Los espacios son caracteres. */ #include <stdio.h> /* Forma de usar las estructuras desde las funciones: Si es desde la función padre (en la que se ha inicializado la estructura) debemos de usar esta sintaxis: lin.caracteres = 2; En cambio, si la función padre le manda la estructura como puntero a otra función, esta además de recibirla como referencia, también cambiara su sintaxis teniendo dos formas diferentes, ambas hacen lo mismo: (la anterior No sirve) (*linea).caracteres = 2; linea->caracteres = 2; */ typedef struct estructura { int caracteres; // Número de caracteres. int palabras; // Número de palabras. float longMedia; // Suma de las longitudes de cada palabra y dividido al final por el Número de palabras. char ultCaracter; // Ultimo carácter de la primera palabra de la linea. int ultCarRepeticiones; // Número de palabras que terminan con ese caracter. int lineaConMasPalabrasRepeticion; // Número de linea en la que hay más palabras que finalizan con ese carácter. int lineas; // Número de lineas en total. int laLineaConMasPalabras; // Número de linea en la que hay más palabras. int numDePalabrasDeLaLineaConMasPalabras; // Número de palabras que tiene esa linea. }; void funPalabras( FILE *fichero, char *caracter, struct estructura *lin, struct estructura *tot ) { /* Precondición: Se ha de recibir la referencia a un fichero de texto. La referencia a un carácter. Y la referencia a dos estructuras de tipo estructura. Poscondición: No se devuelve nada, se modifican los datos de las estructuras. */ char carAnterior = ' '; int i; // Mientras no termine la palabra ni se termine el fichero: for( i=0; *caracter != ' ' && *caracter != '\n' && !feof(fichero); i++ ) { printf( "%c", *caracter ); // Se imprime el carácter carAnterior = *caracter; // Antes de coger un carácter nuevo se guarda el anterior (al finalizar la iteracion guardara el ultimo carácter de la palabra). fscanf( fichero, "%c", caracter ); // Se recoge el siguiente carácter. }; // Se ha terminado la primera palabra y se imprime un espacio para separarla de la siguiente: printf( " " ); // Ahora, si la variable que guarda el ultimo carácter de la primera palabra sigue en blanco, entonces se guarda en ella "carAnterior" if( lin->ultCaracter == ' ' ) lin->ultCaracter = carAnterior; // Además, si el carácter que hemos guardado, es igual que al ultimo carácter de las siguientes palabras, entonces sumamos una repetición: (lin->ultCaracter la primera vez vale -1 para contrarrestar la primera repetición por la primera palabra...) if( lin->ultCaracter == carAnterior ) lin->ultCarRepeticiones++; // Se suman los caracteres de la palabra al total de la linea +1 por el espacio: if( *caracter == ' ' ) lin->caracteres += i+1; else if( *caracter == '\n' || feof(fichero) ) lin->caracteres += i; // Se suma una palabra al total. if( carAnterior != ' ' ) lin->palabras++; // Se recoge el siguiente carácter. if( *caracter == ' ' ) fscanf( fichero, "%c", caracter ); }; void funLineas( FILE *fichero, char *caracter, struct estructura *tot ) { /* Precondición: Se ha de recibir la referencia a un fichero de texto. La referencia a un carácter. Y la referencia a una estructuras de tipo estructura. Poscondición: No se devuelve nada, se modifican los datos de la estructura. */ struct estructura lin; int i; // Puesta a cero de los contadores: lin.caracteres = 0; lin.palabras = 0; lin.ultCaracter = ' '; lin.ultCarRepeticiones = -1; // Mientras no termine la linea ni se termine el fichero: for( i=0; *caracter != '\n' && !feof(fichero); i++ ) { funPalabras( fichero, caracter, &lin, tot ); }; // Como se ha terminado la linea, se imprime un salto de linea y su resultado: lin.longMedia = (float)lin.caracteres / (float)lin.palabras; printf( "\n -> caracteres: %i, palabras: %i, longitud media: %.1f - Letra final de la primera palabra: \"%c\", palabras que terminan igual: %i\n\n", lin.caracteres, lin.palabras, lin.longMedia, lin.ultCaracter, lin.ultCarRepeticiones ); // Antes de terminar con la linea, se suman los contadores a los contadores totales: tot->caracteres += lin.caracteres; // Se suman los caracteres de la linea tot->palabras += lin.palabras; // También se suman las palabras de la linea. tot->lineas++; // Y se aumenta en 1 el contador de lineas. // Ahora se comprueba si hay mas palabras en esta linea que en la anterior almacenada en el total, si es así se actualizan los datos: if( lin.palabras > tot->numDePalabrasDeLaLineaConMasPalabras ) { tot->numDePalabrasDeLaLineaConMasPalabras = lin.palabras; tot->laLineaConMasPalabras = tot->lineas; } if( lin.ultCarRepeticiones > tot->ultCarRepeticiones ) { tot->ultCarRepeticiones = lin.ultCarRepeticiones; tot->lineaConMasPalabrasRepeticion = tot->lineas; }; // Se recoge el siguiente carácter. if( *caracter == '\n' ) fscanf( fichero, "%c", caracter ); }; main() { system("clear"); FILE *fichero; struct estructura tot; char nombreFichero[255]; char caracter; int i; // Puesta a cero de los contadores totales: tot.lineas = 0; tot.palabras = 0; tot.caracteres = 0; tot.laLineaConMasPalabras = 0; tot.numDePalabrasDeLaLineaConMasPalabras = 0; tot.lineaConMasPalabrasRepeticion = 0; tot.ultCarRepeticiones = 0; printf( "Introduzca el nombre del fichero que quiere analizar:\n" ); do { scanf( "%s", nombreFichero ); // Se solicita el nombre del fichero a analizar. fichero = fopen( nombreFichero, "r" ); // Se intenta abrir ese fichero. // En caso de no existir o no poderse abrir se muestra un error: if( fichero == NULL ) printf( "\n\nEl fichero indicado no pudo abrirse o no existe, pruebe de nuevo:\n" ); } while( fichero == NULL ); // Se resolicita de forma indefinida el nombre del fichero hasta que consiga abrirse. printf( "\n\n" ); // Se realiza la primera lectura al fichero. Si hay caracteres se cogerá el primero. fscanf( fichero, "%c", &caracter ); // Mientras queden caracteres por leer en el fichero: for( i=0; !feof(fichero); i++ ) { // Se llama a la función que se encarga de la linea, enviándole: el fichero, el carácter y la estructura linea. funLineas( fichero, &caracter, &tot ); }; fclose(fichero); tot.longMedia = (float)tot.caracteres / (float)tot.palabras; // Se imprimen los resultados totales: printf( "________________________________________________________________________\n" ); printf( "En total hay %i lineas que contienen %i palabras / %i caracteres, con una longitud media de %.1f\n", tot.lineas, tot.palabras, tot.caracteres, tot.longMedia ); printf( "La linea con mas palabras es la %i con un total de %i palabras\n", tot.laLineaConMasPalabras, tot.numDePalabrasDeLaLineaConMasPalabras ); printf( "La linea con mas palabras que cuyo ultimo caracter terminan como su primera palabra es la linea %i con %i palabras iguales.\n\n", tot.lineaConMasPalabrasRepeticion, tot.ultCarRepeticiones ); }; |