[C con Clase] error cuando se ejecuta el programa.

Steven R. Davidson vze266ft en verizon.net
Mie Feb 27 00:43:19 CET 2008


Hola Raúl Alfonso,

Raul Alfonso Jimenez Morocho wrote:
> Buenas,
> 
> Estoy haciendo un programa de guardar datos en ficheros y cuando lo 
> depuro no me aparece ningún error, pero cuando se esta ejecutando me 
> aparece un error. Lo adjunto para que lo vean y además adjunto el código 
> haber si ven algo mal. Soy muy novato y tampoco es que me entere de mucho.
> 

Veamos el código fuente.

> #include <conio.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <math.h>
> typedef struct
> {
> 	float litroslluvia;
> 	int agreg;
> }meteo;
> 
> meteo mlluvia[12][31];
> char resp;
> 
> int pedirFich();
> int comprfech(int dia,int mes);
> void introlluvia();
> void conslluvia();
> void modiflluvia();
> void borrarlluvia();
> void miMenu();
> void guardar();
> char pedir[39];

No recomiendo, para nada, usar variables globales. Intenta rediseñar tu 
programa para no depender de este "tipo" de variables. Si tienes 
errores, es difícil detectarlos si usas variables globales.

> void main()

Si usas C, deberías indicar 'void' para la lista de parámetros.

> {
> 	system("cls");
> 	char opc;
> 
> 	if(pedirFich()==0)
> 	{
> 			do
> 			{			
> 				
> 				miMenu();
> 				opc=getch();	
> 				if(opc=='1')
> 				{
> 					introlluvia();
> 					guardar();
> 					getch();
> 				}
> 				if(opc=='2')
> 				{
> 					conslluvia();
> 					getch();
> 				}
> 				if(opc=='3')
> 				{
> 					modiflluvia();
> 					guardar();
> 					getch();
> 				}	
> 				if(opc=='4')
> 				{
> 					borrarlluvia();
> 					guardar();
> 					getch();
> 
> 				}
> 
> 				}while(opc!='5');
> 			if(opc=='5')
> 			{
> 				system("cls");
> 				printf("Pulse una tecla para finalizar");
> 
> 			}
> 	}
> 	
> }
> int pedirFich()
> {
> 	FILE* fichBuscar;
> 	int x,i;
> 
> 	system("cls");
> 	fichBuscar=fopen("lluvias.dat","rt");

No es necesario indicar "t", ya que por defecto, los ficheros son 
abiertos en modo texto.

> 
> 	if (fichBuscar==NULL)
> 	{
> 		printf("El archivo no existe");
> 		getch();
> 		x=0;
> 	}
> 	else
> 	{
> 		for (i=0;i<12;i++)
> 		{
> 		fread(mlluvia[i],sizeof(meteo),31,fichBuscar);
> 		}

No es necesario realizar 12 lecturas. Como 'mlluvia' es un array 
bidimensional, todos los elementos existen contiguamente en memoria. Por 
lo tanto, puedes hacer una sola lectura. Esto es,

fread( mlluvia, sizeof(meteo), 12*31, fichBuscar );

O incluso,

fread( mlluvia, sizeof mlluvia, 1, fichBuscar );

No hace falta ni bucles ni múltiples lecturas.

> 		x=1;
> 		
> 	}
> 	fclose(fichBuscar);

Ten cuidado al intentar cerrar el fichero, porque si 'fichBuscar' es 
nulo, podrías tener un error.

> 	getch();
> 	return x;

En lugar de retornar el valor 'x', sugiero retornar el valor directa e 
inmediatamente. Esto sería,

if( NULL == fichBuscar )
{
   ...
   return 0;
}
...
return 1;  /* O incluso: return !0; */

> }
> 
> 
> void miMenu()
> {
> 	system("cls");
> 	printf("  ------   Meteorologia  Raul Jimenez  ------  ");
> 	printf("\n\n1.-Introducir lluvia ");
> 	printf("\n2.-Consultar lluvia ");
> 	printf("\n3.-Modificar lluvia ");
> 	printf("\n4.-Borrar lluvia ");
> 	printf("\n5.-Salir");
> }
> 
> 
> void introlluvia()
> {
> 	int dia,mes,var;
> 	system("cls");
> 	printf("Introduzca dia: ");
> 	fflush(stdin);

Ten cuidado con este uso de 'fflush()', ya que no es estándar que 
funcione pra canales de entrada, sino de salida.

> 	scanf("%d",&dia);
> 	printf("\n Introduzca mes: ");
> 	fflush(stdin);
> 	scanf("%d",&mes);
> 	var=comprfech(mes,dia);
> 	if(var==0)
> 	{
> 		printf("\n Fecha incorrecta, por favor introduce una fecha correcta");
> 	}
> 	if(var==1)

Esta condición no es necesaria. Como 'comprfecha()' retornará o bien 0 
(cero) o bien 1. Por lo tanto, con una sola comprobación, podemos 
determinar el valor retornado.

En lugar de 'if', escribe 'else'. Esto sería,

if( comprfecha(...) )  // ¿comprfecha() --> 1 ?
{
   ...
}
else  // comprfecha() --> 0
{
   ...
}

Como puedes observar, tampoco es necesario usar 'var' ya que nos 
interesa el valor retornado por la función 'comprfecha()'. También date 
cuenta que el código anterior invierte la lógica del programa comparado 
con el código original, porque la condición comprueba si no es cero.

> 	{
> 		if(mlluvia[mes][dia].agreg==1)
> 		{
> 			printf("\nDatos introducidos");
> 			getch();
> 		}
> 		else
> 		{
> 			printf("\n\nIntroduzca litros: ");
> 			fflush(stdin);
> 			scanf("%f",mlluvia[mes][dia].litroslluvia);

Aquí tienes un error. Debes pasar una dirección de memoria al usar 
'scanf()' de esta manera. Posiblemente aquí tienes el error en tiempo de 
ejecución. Deberías escribir:

scanf( "%f", &mlluvia[mes][dia].litroslluvia );

> 			mlluvia [mes][dia].agreg=1;
> 		}
> 
> 
> 	}
> 	
> }
> 
> void conslluvia()
> {
> 	do
> 	{
> 		int dia,mes,var;
> 		system("cls");
> 		printf("Introduzca dia: ");
> 		fflush(stdin);
> 		scanf("%d",&dia);
> 		printf("\n Introduzca mes: ");
> 		fflush(stdin);
> 		scanf("%d",&mes);
> 		var=comprfech(mes,dia);
> 		if(var==0)
> 		{
> 			printf("\n Fecha incorrecta, por favor introduce una fecha correcta");
> 		}
> 		if(var==1)

Como mencioné anteriormente, puedes reescribir el código eliminando la 
necesidad de 'var' y usando 'if/else' para hacer una sola comprobación.

> 		{
> 			if(mlluvia[mes][dia].agreg==0)
> 			{
> 				printf("\n\tDatos no introducidos");
> 			}
> 			else
> 			{
> 				printf("\nLa cantidad de litros para este dia es de: %.2f",mlluvia[mes][dia].litroslluvia);
> 
> 			}
> 		}
> 		do
> 		{
> 			printf("\n\nDesea consultar mas dias(S/N)? ");
> 			resp = getch();
> 		}while(resp != 'S'&& resp != 's'&& resp != 'N'&& resp != 'n');
> 	}while(resp == 'S' || resp == 's');
> }
> 
> void modiflluvia()
> {
> 	int dia,mes,var;
> 	system("cls");
> 	printf("Introduzca dia: ");
> 	fflush(stdin);
> 	scanf("%d",&dia);
> 	printf("\n Introduzca mes: ");
> 	fflush(stdin);
> 	scanf("%d",&mes);
> 	var=comprfech(mes,dia);
> 	if(var==0)
> 	{
> 		printf("\n Fecha incorrecta, por favor introduce una fecha correcta");
> 	}
> 	if(var==1)

Aquí ocurre lo mismo que antes. Puedes optimizar un poco este código.

> 	{
> 		if(mlluvia[mes][dia].agreg==0)
> 		{
> 			printf("Datos no introducidos");
> 		}
> 		else
> 		{
> 			printf("La cantidad anterior es %.2f",mlluvia[mes][dia].litroslluvia);
> 			printf("\nIntroduzca nueva cantidad: ");
> 			scanf("%f",mlluvia[mes][dia].litroslluvia);

Aquí tienes el mismo error que antes. Debes pasar la dirección de 
memoria de este miembro. Esto es,

scanf( "%f", &mlluvia[mes][dia].litroslluvia );

> 		}
> 	}
> 	
> }
> 
> void borrarlluvia()
> {
> 	int dia,mes,var;
> 	char op;
> 	system("cls");
> 	printf("Introduzca dia: ");
> 	fflush(stdin);
> 	scanf("%d",&dia);
> 	printf("\n Introduzca mes: ");
> 	fflush(stdin);
> 	scanf("%d",&mes);
> 	var=comprfech(mes,dia);
> 	if(var==0)
> 	{
> 		printf("\n Fecha incorrecta, por favor introduce una fecha correcta");
> 	}
> 	if(var==1)

Nuevamente, puedes optimizar este código.

> 	{
> 		if(mlluvia[mes][dia].agreg==0)
> 		{
> 			printf("Datos no introducidos");
> 		}
> 		else
> 		{
> 			printf("La cantidad anterior es %.2f",mlluvia[mes][dia].litroslluvia);
> 			do
> 			{
> 				printf("\nDesea eliminar la cantidad anterior (S/N)");
> 				op=getch();
> 			}while(op!='s'&&op!='S'&&op!='n'&&op!='N');
> 			if(op=='s'||op=='S')
> 			{
> 
> 				mlluvia[mes][dia].litroslluvia=0;
> 				mlluvia[mes][dia].agreg=0;
> 				printf("\nDatos eliminados");
> 			}
> 			else
> 			{
> 				printf("\nNo han sido eliminados los datos");
> 			}
> 			
> 		}
> 
> 
> 	}
> 
> }
> 
> 
> 
> 
> int comprfech(int dia,int mes)
> {
> 	int var1=0;
> 	if(mes==1||mes==3||mes==5||mes==7||mes==8||mes==10||mes==12)
> 	{
> 		if(dia>31||dia<1)
> 		{
> 			var1=0;
> 		}
> 		else
> 		{
> 			var1=1;
> 		}
> 	}
> 	if(mes==4||mes==6||mes==9||mes==11)
> 	{
> 		if(dia>30||dia<1)
> 		{
> 			var1=0;
> 		}
> 		else
> 		{
> 			var1=1;
> 		}
> 	}
> 	if (mes==2)
> 	{
> 		if(dia>28 || dia<1)
> 		{
> 			var1=0;
> 		}
> 		else
> 		{
> 			var1=1;
> 		}
> 	}
> 
> 

Sugiero rediseñar el código para esta función. Aconsejo usar un array 
estático y constante con los días máximos para cada mes. No es necesario 
guardar los días mínimos ya que siempre serán 1. El código sería,

int comprfech( int dia, int mes )
{
   static const unsigned short dias_mes[12] =
                     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

   return mes < 0  || 12 > mes ? 1 <= dia&&dia <= dias_mes[mes] : !0;
}

O incluso,

if( mes < 0  || 12 > mes )  return 0;

return 1 <= dia&&dia <= dias_mes[mes];

Como no consultas el año, no comparamos el caso especial de un posible 
29 de febrero en un año bisiesto, que por cierto toca este año, dentro 
de unos días.

También nos ahorramos la variable 'var1'.

> 	return var1;
> }
> 
> 
> 
> void guardar()
> {
> 	FILE* guar;
> 	int i;
> 	for (i=0;i<12;i++)
> 		{
> 		fwrite(mlluvia[i],sizeof(meteo),31,guar);

Nuevamente, podemos obviar el bucle y usar 'fwrite()' para escribir en 
una sola sentada.

> 		}
> 	fclose(guar);
> }
> 

Aquí tienes un error, ya que no has abierto ningún fichero para 'guar'. 
Debes nivocar 'fopen()' para crear ("r+" o "w"), truncar un fichero 
existente ("w"), o agregar al final de un fichero ("a").


Espero que todo esto te ayude.

Steven






Más información sobre la lista de distribución Cconclase