-
Notifications
You must be signed in to change notification settings - Fork 0
Home
¡Bienvenidos a la wiki de tw_E10X_2022_2023-bubalongas!
Haz clic aquí para ver el diagrama de flujo: Diagrama de flujo
Para recoger toda la información del archivo .csv nos hemos decantado por crear las siguientes estructuras:
typedef struct{
char mes[10];
int anyo;
}date;
typedef struct{
char tipo[50];
float magnitud;
date fecha;
}generacion_2122;
El nombre de la estructura principal es generacion_2122 y tiene como elementos: Una cadena de caracteres donde ira el nombre del tipo de energía, una variable real llamada magnitud donde va la cantidad de GWh generada y otra estructura llamada date que contiene una cadena con el mes y un entero con el año. Con esto creamos una matriz de la estructura con las dimensiones de la tabla Excel: Con 18 filas (tipos) y 24 columnas (meses de 2021 y 2022).
#define NUM_FILAS 18
#define NUM_COLUMNAS 24
generacion_2122 generacion[NUM_FILAS][NUM_COLUMNAS];
Para la recogida de datos nos ha sido muy útil la librería locale.h ya que el archivo a leer estaba en español. De dicha librería hemos utilizado la función setlocale(LC_CTYPE,"spanish") para leer correctamente las palabras con acento y la función setlocale(LC_NUMERIC, "spanish") para no tener problemas al leer números reales que tengan comas como separador decimal.
#include <locale.h>
setlocale(LC_CTYPE,"spanish");
setlocale(LC_NUMERIC, "spanish");
Lo primero que debemos hacer es abrir el archivo con el procedimiento habitual, cuyo nombre es "ProyectoInforREE.csv".
Para acceder a los datos que nos interesan primero tenemos que saltarnos las primeras 4 líneas ya que son títulos e información que no nos interesa, como tampoco no interesan los 6 primeros caracteres de la 5ª fila. Y lo haremos con el siguiente código:
while (fscanf(pf, "%c", &x) != EOF)
{
if (x == '\n')
++nLineas;
if (nLineas==4)
break;
}
while (i<6) // Código para saltarnos los 6 primeros caracteres de la quinta fila.
{
fscanf(pf, "%c", &x);
i++;
}
En la primera línea encontramos las fichas de los datos (mes y año) como dichos datos están de la forma "ene-21;" pondremos en el fscanf "%[^-]-%i;" de tal manera que la primera cadena, que se leerá hasta el guion, se almacenará en primera fila y la columna que corresponda de la matriz estructura de igual manera con el año almacenándolo en la parte de la estructura del año que es de tipo entero.
i=0;
while (i<24)
{
fscanf(pf, "%[^-]-%i;", generacion[0][i].fecha.mes, &generacion[0][i].fecha.anyo);
i++;
}
Una vez tenemos los datos almacenados en la primera fila de la matriz necesitamos copiarlos para las demás filas, y eso lo haremos con los siguientes bucles:
for(i=0; i<24; i++)
{
for(j=0; j<18; j++)
{
strcpy(generacion[j][i].fecha.mes, generacion[0][i].fecha.mes);
}
}
for(i=0; i<24; i++)
{
for(j=0; j<18; j++)
{
generacion[j][i].fecha.anyo = generacion[0][i].fecha.anyo;
}
}
En el resto de líneas del archivo tenemos primero el tipo de generación (lo recogeremos como una cadena) y después las magnitudes de cada mes (lo recogeremos como números reales fácilmente). Para que el programa funcione correctamente deberemos añadir un fscanf para que lea el salto de línea y no se descuadre la siguiente lectura. Aquí el código utilizado:
i=0;
while (i<18)
{
fscanf(pf, "%[^;]", generacion[i][0].tipo);
for(j=0; j<24; j++)
{
fscanf(pf, ";%f", &generacion[i][j].magnitud);
}
fscanf(pf, "%c", &x);
i++;
}
De manera similar a como lo hacíamos con las fechas tenemos que copiar en este caso los datos de los tipos de generación en el resto de columnas:
for(i=0; i<18; i++)
{
for(j=0; j<24; j++)
{
strcpy(generacion[i][j].tipo, generacion[i][0].tipo);
}
}
Para comenzar a dar un poco de forma a nuestro trabajo, comenzamos con la creación de los menús, estos permitirán al usuario decidir cómo realizar el estudio estadístico. En primer lugar se presenta un menú que permita escoger entre realizar el estudio por fecha o por tipo de generación eléctrica, se anuda con otros dos menús. Si se escoge por tipo de generación eléctrica, aparece un menú que da a escoger entre el tipo de generación. Por otro lado, si se escoge por fecha de generación, se anuda a un segundo menú en el que nos dejará elegir entre el año que queremos estudiar. Una vez escogido el año que deseamos estudiar se nos abrirá un tercer menú que nos permitirá optar entre los diferentes meses del año. Cabe destacar que todos los menús tienen la opción de volver al menú anterior o por ende terminar el estudio con la opción 'salir' en el primero de estos:
printf("ESTE PROGRAMA TIENE LA FUNCIÓN DE REALIZAR UN AMPLIO ESTUDIO ESTÍDISTICO CON RESPECTO A LOS VALORES RECOGIDOS POR LA RED ELÉCTRICA ESPAÑOLA ENTRE EL AÑO 2021 Y 2022. \n");
printf("Para comenzar con el estudio, por favor escoja entre las siguientes opciones:\n");
printf("1. Tipo de generación eléctrica.\n");
printf("2. Fecha de generación.\n");
printf("3. Salir.\n");
scanf("%d", &op);
system("cls");
switch(op){
case 1:
do{
printf("¿Qué tipo de generación desea estudiar?\n");
printf("1. Hidráulica\n");
printf("2. Turbinación bombeo\n");
printf("3. Nuclear\n");
printf("4. Carbón\n");
printf("5. Fuel+Gas\n");
printf("6. Motores Diesel\n");
printf("7. Turbnina de gas\n");
printf("8. Turbina de vapor\n");
printf("9. Ciclo combinado\n");
printf("10. Hidroeólica\n");
printf("11. Eólica\n");
printf("12. Solar fotovoltaica\n");
printf("13. Solar térmica\n");
printf("14. Otras reonvavbles\n");
printf("15. Cogeneración\n");
printf("16. Residuos no renovables\n");
printf("17. Residuos renovavles\n");
printf("18. VOLVER ATRÁS\n");
scanf("%d", &letra);
switch(letra)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
break;
case 14:
break;
case 15:
break;
case 16:
break;
case 17:
break;
case 18:
break;
default:
system("cls");
printf("Opción no válida. Por favor seleccione una opción válida.\n");
break;
}
}while(letra!=18);
break;
case 2:
do{
printf("Escoja el año que quiera estudiar:\n");
printf("1. 2021\n");
printf("2. 2022\n");
printf("3. VOLVER ATRÁS\n");
scanf("%d", &ano);
system("cls");
switch(ano){
case 1:
printf("Ahora escoja el mes en el que desea realizar el estudio\n");
printf("1. Enero\n");
printf("2. Febrero\n");
printf("3. Marzo\n");
printf("4. Abril\n");
printf("5. Mayo\n");
printf("6. Junio\n");
printf("7. Julio\n");
printf("8. Agosto\n");
printf("9. Septiembre\n");
printf("10. Octubre\n");
printf("11. Noviembre\n");
printf("12. Diciembre\n");
int mes;
scanf("%d", &mes);
switch(mes){
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
}
break;
case 2:
printf("Ahora escoja el mes en el que desea realizar el estudio\n");
printf("1. Enero\n");
printf("2. Febrero\n");
printf("3. Marzo\n");
printf("4. Abril\n");
printf("5. Mayo\n");
printf("6. Junio\n");
printf("7. Julio\n");
printf("8. Agosto\n");
printf("9. Septiembre\n");
printf("10. Octubre\n");
printf("11. Noviembre\n");
printf("12. Diciembre\n");
int mes2;
scanf("%d", &mes2);
switch(mes2){
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
}
case 3:
break;
default:
system("cls");
printf("Opción no válida. Por favor seleccione una opción válida.\n");
break;
}
}while(ano!=3);
break;
default:
system("cls");
printf("Opción no válida. Por favor seleccione una opción válida.\n");
break;
}
Los menús siguen una estructura muy simple. Muestran por pantalla las opciones a escoger para el usuario, para ello hemos utilizado la función printf(); luego recoge una variable entera (int) con la función scanf(), este dato será el encargado de escoger la opción del menú, este cuenta con una estructura switch-case, es decir, sigue una estructura switch(int)-case int. Los menús están dentro de la función do-while, esta indicará al usuario si ha introducido un dato erróneo, pidiendo al usuario que introduzca de nuevo el dato. Por último hemos utilizado la función system("cls"), está hace un clean screen (limpiar pantalla) en el terminal.
Para el último de los menús decidimos crear dos funciones void. El principal objetivo de esto fue 'la economía de líneas'. En este menú permite elegir al usuario la función estadística a realizar, que quedaría de la siguiente manera:
printf("Para comenzar con el estudio, por favor escoja entre las siguientes opciones:\n");
printf("1. Tipo de generación eléctrica.\n");
printf("3. Salir.\n");
scanf("%d", &op);
system("cls");
switch(op){
case 1:
do{
printf("¿Qué tipo de generación desea estudiar?\n");
printf("1. Hidráulica\n");
scanf("%d", &letra);
switch(letra)
{
case 1:
operacionesfilas(generacion, 0, ptranscrip);
break;
}
}
void operacionesfilas(generacion_2122 generacion[][NUM_COLUMNAS], int tipo, FILE *ptranscrip)
{
int op2;
system("cls");
do{
printf("¿Qué tipo de estudio estadístico desea hacer? \n");
printf("1. Media\n");
printf("2. Moda\n");
printf("3. Hallar maximo\n");
printf("4. Hallar minimo\n");
printf("5. Sumatorio\n");
printf("6. Mediana\n");
printf("7. Varianza\n");
printf("8. Desviación típica\n");
printf("9. Ordenar de mayor a menor\n");
printf("10. Ordenar de menor a mayor\n");
printf("11. VOLVER ATRÁS\n");
scanf("%i", &op2);
switch(op2)
{
case 1:
columnas=24;
mediatipo(generacion, tipo, columnas, ptranscrip);
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
system("cls");
break;
default:
system("cls");
printf("Opción no válida. Por favor seleccione una opción válida.\n");
break;
}
}while (op2!=11);
}
En cada uno de los casos de la función void operacionesfilas() se llama a una función que hemos introducido en una librería en un archivo.h, llamada 'LibreriaBubalongas.h'.
#include "LibreriaBubalongas.h"
esta libreria nos ha permitido ahorrar espacio en el archivo main y nos ha permitido tener un llamamiento de llamadas mas efectivo.
Nuestro programa funciona de tal manera que permite al usuario elegir si quiere hacer sus estudios estadisticos por año y mes o por tipo de energia, por lo tanto las funciones estan repetidas en la libreria pero modificadas para que pudieran operar por filas o por columnas, ya que las dimensiones no eran iguales.
A continuacion explicaremos las funciones que operaban por filas para evitar redundancia. Elegimos usar funciones que retornaban por valor para esta parte del trabajo porque inicialmente teniamos una cosa diferente en mente de como iba a funcionar la funcion: void operaciones().
Los argumentos de estas funciones son una mezcla de estructuras, variables y punteros que permiten a la funcion recibir del programa main los datos necesarios para poder operar como deberian. Los ptranscrip seran explicados mas adelante en esta wiki.
Esta funcion recopila los datos elegidos por el usuario y hace un sumatorio de dichos datos, loscual luego divide por el numero de datos para obtener una media aritmetica
float mediatipo(generacion_2122 matriz[][NUM_COLUMNAS], int filas, int columnas, FILE *ptranscrip)
{
int i;
float media = 0, suma = 0;
for(i = 0; i < columnas; i++)
{
suma += matriz[filas][i].magnitud;
}
media = suma / columnas;
printf("\nLa media en %s es %f\n\n", matriz[filas][0].tipo, media);
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip, "La media en %s es %f\n", matriz[filas][0].tipo, media);
fclose(ptranscrip);
return media;
}
Esta segunda funcion va compararando uno a uno los datos elegidos por el usuario para encontar el dato que mas veces se repita y esnseña al usuario las veces que se ha repetido este dato por pantalla.
float modatipo(generacion_2122 matriz[][NUM_COLUMNAS], int filas, int columnas, FILE *ptranscrip)
{
int i, j;
int frecuencia[24] = {0}; // Inicializar arreglo de frecuencia con ceros
float moda;
int seRepite = 0;
for (i = 0; i < columnas; i++)
{
frecuencia[i] = 1;
for (j = i + 1; j < columnas; j++)
{
if (matriz[filas][i].magnitud == matriz[filas][j].magnitud)
{
frecuencia[i]++;
seRepite = 1;
}
}
}
if (!seRepite)
{
printf("\nNo hay moda.\n\n");
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip,"\nNo hay moda.\n\n");
fclose(ptranscrip);
}
for (i = 0; i < columnas; i++)
{
if (frecuencia[i] > 1)
{
printf("\nLa moda es %f y se repite %d veces.\n\n", matriz[filas][i].magnitud, frecuencia[i]);
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip, "\nLa moda es %f y se repite %d veces.\n\n", matriz[filas][i].magnitud, frecuencia[i]);
fclose(ptranscrip);
break;
}
}
return moda;
}
En este archivo en especifico la funcion de la moda no aporta una gran valor al estudio estadistico ya que era muy improbable que un consumo se repitiera exactamente igual de un mes a otro.
Estas dos funciones implementan unas lineas de codigo y funcionalidad similar por lo que por temas de espacio e eficiencia solo explicaremos una de ellas. Estas dos funciones funcionen de una manera parecida a la moda, ya que van comparando los datos uno a uno en orden para averiguar cual es el mayor o menor de ellos dependiendo de la preferencia del usuario.
float maxtipo(generacion_2122 matriz[][NUM_COLUMNAS], int filas, int columnas, FILE *ptranscrip)
{
int i, ano=0;
float max=0;
char mes[10];
max=matriz[filas][0].magnitud;
ano=matriz[filas][0].fecha.anyo;
strcpy(mes, matriz[filas][0].fecha.mes);
for(i=1; i<columnas; i++)
{
if(matriz[filas][i].magnitud>max)
{
max=matriz[filas][i].magnitud;
ano=matriz[filas][i].fecha.anyo;
strcpy(mes, matriz[filas][i].fecha.mes);
}
}
printf("\nEl maximo en %s es %f y se dio en %s del %i\n\n", matriz[filas][0].tipo, max, mes, ano);
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip, "El maximo en %s es %f y se dio en %s del %i\n", matriz[filas][0].tipo, max, mes, ano);
fclose(ptranscrip);
return max;
}
Por temas de estetica no solo mostramos al usuario el maximo si no ademas en el fecha se dio o en que tipo se encuentra, para esto creamos variables que almacenen esos datos y usamos funciones de C como strcpy.
Como bien se puede deducir del nombre de esta funcion su funcionalidad es la de un sumatorio, lo que hace es sumar todos los datos deseados por el usuario y mostrarlos en pantalla.
float sumtipo(generacion_2122 matriz[][NUM_COLUMNAS], int filas, int columnas, FILE *ptranscrip)
{
int i;
float sum = 0;
for(i = 0; i < columnas; i++)
{
sum += matriz[filas][i].magnitud;
}
printf("\nEl sumatorio de %s es %f\n\n", matriz[filas][0].tipo, sum);
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip, "El sumatorio de %s es %f\n", matriz[filas][0].tipo, sum);
fclose(ptranscrip);
return sum;
}
La función mediana la utilizaremos con la finalidad de encontrar el valor que se encuentra en medio cuando ordenamos los datos de mayor a menor y para ello utilizaremos un comando, que sera explicado en mas detalle mas adelante, que nos sirve para ordenar los datos de mayor a menor para luego tomar el valor central de los datos obtenidos. En este caso al ordenarlo por filas habra 24 valores y no se obtendra un valor central, por lo cual hallaremos la media de los valores almacenados en el vector mayor-menor en las posiciones 13 (v[12]) y 12 (v[11]). Si fuere por columnas, la media seria el valor 9 almacenado en el vector (v[8]).
float medianatipo(generacion_2122 matriz[][NUM_COLUMNAS], int filas, int columnas, FILE *ptranscrip)
{
float mediana = 0;
int i,j,k=24, ano_mayor;
float v[24], mayor;
char cadenaaux[10];
date fechas[24];
for (i=0; i < k; i++)
{
v[i]=matriz[filas][i].magnitud;
}
for (i=0; i < k; i++)
{
fechas[i].anyo=matriz[filas][i].fecha.anyo;
strcpy(fechas[i].mes, matriz[filas][i].fecha.mes);
}
for( j=0; j<k-1; j++)
{
for (i=0; i < k-1; i++)
{
if (v[i]< v[i+1])
{
mayor = v[i];
v[i] =v[i+1];
v[i+1]=mayor;
ano_mayor = fechas[i].anyo;
fechas[i].anyo = fechas[i+1].anyo;
fechas[i+1].anyo = ano_mayor;
strcpy(cadenaaux, fechas[i].mes);
strcpy(fechas[i].mes, fechas[i+1].mes);
strcpy(fechas[i+1].mes, cadenaaux);
}
}
}
mediana = ( v[11] + v[12] ) / 2.0;
printf("\nLa mediana en %s es %f\n\n", matriz[filas][0].tipo, mediana);
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip, "La mediana en %s es %f\n", matriz[filas][0].tipo, mediana);
fclose(ptranscrip);
return mediana;
}
Esta funcion sera utilizada para calcular la varianza de los datos recopilados en la matriz. En ella se realiza primero una declaracion de variables y posteriormente se caculará la varianza a partir del calculo de la media realizado anteriormente. Mas tarde, simplemete se sutiturian los datos de la formula para calcular el parametro varianza muestral.
float varianzatipo(generacion_2122 matriz[][NUM_COLUMNAS], int filas, int columnas, FILE *ptranscrip)
{
int i;
float media = 0, suma = 0, varianza = 0, varianza_numerador = 0;
for(i = 0; i < columnas; i++)
{
suma += matriz[filas][i].magnitud;
}
media = suma / columnas;
for(i = 0; i < columnas; i++)
{
varianza_numerador += pow(matriz[filas][i].magnitud - media, 2);
}
varianza = varianza_numerador / columnas;
printf("\nLa varianza en %s es %f\n\n", matriz[filas][0].tipo, varianza);
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip, "La varianza en %s es %f\n", matriz[filas][0].tipo, varianza);
fclose(ptranscrip);
return varianza;
}
La funcion desviacion tipica tiene la misma finalidad y se realiza de manera analoga a la varianza, salvo que en esta se realiza al final una raiz cuadrada de la funcion varianza muestral.
float destipicatipo(generacion_2122 matriz[][NUM_COLUMNAS], int filas, int columnas, FILE *ptranscrip)
{
int i;
float media = 0, suma = 0, varianza = 0, varianza_numerador = 0, desviaciontipica = 0;
for(i = 0; i < columnas; i++)
{
suma += matriz[filas][i].magnitud;
}
media = suma / columnas;
for(i = 0; i < columnas; i++)
{
varianza_numerador += pow(matriz[filas][i].magnitud - media, 2);
}
varianza = varianza_numerador / columnas;
desviaciontipica = sqrt(varianza);
printf("\nLa desviacion tipica en %s es %f\n\n", matriz[filas][0].tipo, desviaciontipica);
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip, "La desviacion tipica en %s es %f\n", matriz[filas][0].tipo, desviaciontipica);
fclose(ptranscrip);
return desviaciontipica;
}
Para lograr dejar constancia de los cálculos estadísticos realizados por el programa creamos un archivo .txt en el que se guardarán estos y el cual se alojará en la misma carpeta en la que esta el proyecto, de manera que tendremos fácil acceso a él.
Para hacer esto comenzamos abriendo un archivo al que hemos llamado "TrancripcionProyecto.txt" en modo escritura "w" de esta manera:
Cerrando por supuesto el archivo.
ptranscrip = fopen("TrancripcionProyecto.txt", "w");
fprintf(ptranscrip, "Esta es la transcripción del programa:\n");
fclose(ptranscrip);
Para ir añadiendo las operaciones al archivo lo abrimos en el modo añadir "a".
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip, "La media en %s es %f\n", matriz[filas][0].tipo, media);
fclose(ptranscrip);
Por último, cuando acaba el programa escribimos en la transcripción el texto "Fin del programa" que indica que ha salido todo bien.
ptranscrip = fopen("TrancripcionProyecto.txt", "a");
fprintf(ptranscrip, "\nFin del programa.\n");
fclose(ptranscrip);