Duda con estructuras en C (Urgente)

Iniciado por jamatbar, 4 Enero 2014, 16:31 PM

0 Miembros y 1 Visitante están viendo este tema.

amchacon

Comprueba los datos cuando te los introduzca el usuario, después es más lioso:

- Si día es < 1 devuelves un error
- Si mes es < 1 devuelves un error
- Si anyo es < 0 devuelves un error
- Si mes > 12 devuelves un error
- Si dia > dias_del_mes devuelves un error (febrero tendrá 29 días).
- Si anyo != bisiesto, es febrero y es el día 29 devuelves un error-
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

dato000

Cita de: amchacon en  5 Enero 2014, 13:28 PM
Comprueba los datos cuando te los introduzca el usuario, después es más lioso:

- Si día es < 1 devuelves un error
- Si mes es < 1 devuelves un error
- Si anyo es < 0 devuelves un error
- Si mes > 12 devuelves un error
- Si dia > dias_del_mes devuelves un error (febrero tendrá 29 días).
- Si anyo != bisiesto, es febrero y es el día 29 devuelves un error-

Eso es, exacto, pero realmente me parece muy recargado meterle tanta cosa para un programa así, me parece que tal y como esta esta bien.

es como decir en el caso de enero, que tiene 31 días:


while(fecha.mes == 1 && fecha.dia > 0 && fecha.dia < 32)
{
    //instrucciones de ejecucion
    //validar registro
    //comparar fechas
    //determinar si es bisiesto

   if(fecha.dia < 0 || fecha.dia > 31)
   {
            printf("\nError en el registro de fecha, formato incorrecto, intentalo otra vez besta!!\n");
   }
}


Ahora, el problema es que practicamente hay que hacer un while para todos los meses, y luego realizar uno para determinar si es bisiesto en el mismo ciclo de febrero, y pues se hace muy tedioso. Claro que se puede resumir a meses que tengan una cantidad de días iguales así como ya has hecho antes, y seguro que si sacas una, sacas todas las apreciaciones para determinar la mecanica del proceso.

Aunque la verdad, yo lo dejaria hasta ahi, esta muy bien hecho... :silbar: :silbar:



jamatbar

Bueno, he puesto estructura.c así:

#include <stdio.h>
#include "fecha.h"

int main()
{
  struct fecha f1;
  struct fecha f2;
  // struct fecha *pf1;
  // struct fecha *pf2;
  int a;
  int compara;
  int bis1;
  int bis2;

while(fecha.mes == 1 && fecha.dia > 0 && fecha.dia < 32)
{
  f1 = leeFecha();
  a = compruebaFecha(&f1);

  if (a == 0)
    {
      printf("Formato de fecha incorrecto\n");
    }

  else
    {
      f2 = leeFecha();
      a = compruebaFecha(&f2);

      if (a == 0)
        {
          printf("Formato de fecha incorrecto\n");
        }

      else

        {

          compara = comparaFecha(f1, f2);

  /* Imprimir */

          imprimeFecha(f1);
          {
            if (compara > 0)

              printf(" es posterior a ");

            else if (compara == 0)

              printf(" es igual a ");

            else

              printf(" es anterior a ");
          }

          imprimeFecha(f2);

          bis1 = esBisiesto(f1);
          bis2 = esBisiesto(f2);

          {
            if (bis1 == 1 && bis2 == 0)

              printf("\nLa primera fecha es en bisiesto\n");

            else if (bis1 == 0 && bis2 == 1)

              printf("\nLa segunda fecha es en bisiesto\n");

            else if (bis1 == 1 && bis2 == 1)

              printf("\nAmbas fechas son en bisiesto\n");

            else

              printf("\nNinguna de las dos fechas es en bisiesto\n");

          }
        }
if (fecha.dia < 0 || fecha.dia > 31)
{
printf("\nFormato de fecha incorrecto\n");
}
}
    }
  return 0;
}


Pero me da errores de ejecución:

estructura.c: En la función 'main':
estructura.c:26:7: error: 'fecha' no se declaró aquí (primer uso en esta función)
estructura.c:26:7: nota: cada identificador sin declarar se reporta sólo una vez para cada función en el que aparece

El problema es que por mi lo dejaría tal como está, pero el profesor pasa un programa de comprobación del ejercicio con distintas pruebas, y la prueba esa no la pasa :S (que al poner una segunda fecha incorrecta me salga sólo el mensaje de "Formato de fecha incorrecto"). Y no se me ocurre como ponerlo para que me salga :S


dato000

Cita de: jamatbar en  5 Enero 2014, 22:47 PM
estructura.c: En la función 'main':
estructura.c:26:7: error: 'fecha' no se declaró aquí (primer uso en esta función)
estructura.c:26:7: nota: cada identificador sin declarar se reporta sólo una vez para cada función en el que aparece

El problema es que por mi lo dejaría tal como está, pero el profesor pasa un programa de comprobación del ejercicio con distintas pruebas, y la prueba esa no la pasa :S (que al poner una segunda fecha incorrecta me salga sólo el mensaje de "Formato de fecha incorrecto"). Y no se me ocurre como ponerlo para que me salga :S

Pues lo que pasa es que debes usar la variable, no el tipo de variable:

while(f1.mes == 1 && f1.dia > 0 && f1.dia < 32)

Pero de todas maneras, tu ya tienes esos datos de comprobación listos, no entiendo realmente cuando mencionas lo del formato, porque el formato de una fecha es el siguiente:

CitarDD/MM/AAAA

Entiendo tu punto de vista, pero realmente lo que necesitas es simplemente indicar si es un bisiesto o no, porque el formato de fechas es correcto, le pones un número menor a 2 digitos para el día y el mes, y un año correcto dentro del estandar de las fechas, ahora lo que debe hacerse es indicarle al usuario si la fecha es correcta o no. Lo unico que debes hacer, es que si quieres restringir en el caso de las fechas:

29/02/2000 
29/02/1900

Es que en el exclusivo caso de que se comparen años biciestos y uno no sea correcto, no por el día, no por el mes, sino porque el año no corresponde a un año biciesto es realizar la restriccion de que si se comparan fechas con meses de febrero, en el cuaĺ, si no es una fecha correcta, pues no se hace el proceso de comparar las fechas, sino simplemente arrojar el resultado que indique "no es biciesto" pero el formato de fechas si corresponde con el que se usa para una fecha, si el usuario indica una fecha en el cual no es un año biciesto, pues el mismo programa le indica, "no es un año biciesto".

Creo que la falla no esta en la programación del programa, de hecho, ya todo esta ahi, solo es reacomodarlo y restructurarlo, no se necesita más ciclos ni condiciones, ya esta todo ahi en las funciones de fecha.c


#include <stdio.h>
#include "fecha.h"

struct fecha leeFecha(void)
{
    struct fecha Fech;
    printf("Introduzca la fecha en formato dd/mm/aaaa: ");
    scanf("%d/%d/%d", &Fech.dia, &Fech.mes, &Fech.anyo);
    return Fech;
}


int compruebaFecha(struct fecha *pFecha)
{
    int compru;
    int bis;
    {
        if (pFecha->dia < 1 || pFecha->dia > 31) // por defecto los meses tienen un promedio de 31
        compru = 0;

        else if (pFecha->mes < 1 || pFecha->mes > 12) // por defecto cada año tiene 12 meses
            compru = 0;

        // Caso particular para meses:
        // Abril
        // Junio
        // Septiembre
        // Noviembre
        // Que solo poseen 30 dias
        else if ((pFecha->mes == 4 || pFecha->mes == 6 || pFecha->mes == 9 || pFecha->mes == 11) && (pFecha->dia > 30))
            compru = 0;

        // Caso Particular Febrero
        // Por defecto solo tiene 28 dìas
        // Excepto en el año biciesto
        else if (pFecha->mes == 2)
        {
            if ((bis = 1) && (pFecha->dia > 29))
                compru = 0;

            else if ((bis = 0) && (pFecha->dia > 28))
                compru = 0;
        }

        else
            compru = 1;
    }
    return compru;
}


int comparaFecha(struct fecha f1, struct fecha f2)
    /* Función comparaFecha, devuelve:
       -1 si fecha1 < fecha2
       0 si fecha1 = fecha2
       1 si fecha1 > fecha2
    */
{
    int compara;

    if (f1.anyo < f2.anyo)
        compara = -1;
    else if (f1.anyo > f2.anyo)
        compara = 1;
    else
    {
        if (f1.mes < f2.mes)
            compara = -1;

        else if (f1.mes > f2.mes)
            compara = 1;

        else
        {
            if (f1.dia < f2.dia)
                compara = -1;

            else if (f1.dia > f2.dia)
                compara = 1;

            else
                compara = 0;
        }
    }

    return compara;
}


void imprimeFecha(struct fecha f)
{
    printf("%02d/%02d/%04d", f.dia, f.mes, f.anyo);
}



// Funcion para comprobar si un año es bisiesto:
int esBisiesto(struct fecha f)
{
    int bis = 0;

    // año bisiesto: {divisible por 4 y no por 100} o {divisible por 400}
    if (((f.anyo % 4 == 0) && (f.anyo % 100 != 0)) || (f.anyo % 400 == 0))
        bis = 1;

    return bis;
}



no ha cambiado nada, solo deje claro los casos de los meses pues ya estan hechos, solo es para que tengas en cuenta de que los formatos de fecha son correcto, lo que se necesita es solo decirle  al usuario si la fecha que escribio es un año biciesto o no, no es un error de programación, es un error de sentido común, el usuario piensa que es año bisiesto, pero el programa realiza el cálculo de los modulos y los mutiplos y le indica que no es así.

Solo necesitas ajustar la perspectiva, porque todo esta bien ahi, creo yo.



jamatbar

Muchas gracias, cuando tenga tiempo lo miro ya que se ha pasado el plazo de entrega del ejercicio y como tengo los exámenes encima no tengo tiempo para ponerme ahora a hacerlo xD

Aún así, muchísimas gracias!

do-while

#15
¡Buenas!

En la función que comprueba la corrección de una fecha tienes un error muy gordo de lógica en el caso de febrero:

   else if (pFecha->mes == 2)

     {
       if ((bis = 1) && (pFecha->dia > 29))

         compru = 0;

       else if ((bis = 0) && (pFecha->dia > 28))

         compru = 0;
     }


29/2/1992 (año bisiesto):
- bis = 1: true dia> 29: false --> pasamos al else
- bis = 0: false --> pasamos al else ---> ¡NO HAY ELSE! ---> compru queda indefinido.

Supongo que tu intención no era asignar valores uno o cero a bis, sino asignar el valor de la función que evalúa si un año es o no bisiesto. Por cierto, asigna a compru el valor 1 desde el principio, ya que en tu código estás buscando los casos de error y has visto que al menos en el caso de febrero su valor queda indefinido.

Por cierto, en una función que compruebe cosas sobre datos, nunca imprimas mensajes ni pidas datos. No hagas ninguna de las dos cosas porque no sabes la interfaz que va a tener tu programa, lo mismo puede ser un entrono de ventanas que de consola que ser un código empotrado en algún sistema... si una función comprueba la validez de unos datos, si quieres indicar que algo ha salido mal, devuelve datos numéricos que indiquen el error. Así la función que haya llamado a la función de comprobación podrá saber si algo ha salido mal, y actuar en consecuencia.

¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!

jamatbar

#16
Gracias!, le echaré un ojo ;)

dato000

Cita de: do-while en  7 Enero 2014, 11:43 AM
Por cierto, en una función que compruebe cosas sobre datos, nunca imprimas mensajes ni pidas datos. No hagas ninguna de las dos cosas porque no sabes la interfaz que va a tener tu programa, lo mismo puede ser un entrono de ventanas que de consola que ser un código empotrado en algún sistema... si una función comprueba la validez de unos datos, si quieres indicar que algo ha salido mal, devuelve datos numéricos que indiquen el error. Así la función que haya llamado a la función de comprobación podrá saber si algo ha salido mal, y actuar en consecuencia.

No lo se, puede que sea una mala costumbre, pero no le veo problema pedirle datos en pantalla para comprobación de funciones, al menos, yo lo hago mientras construyo correctamente las funciones y comprobando que efectivamente si realiza la llamada a funciones de una manera que espero, al final, dejo de lado tales impresiones y realizo el retorno correspondiente, excepto en casos particulares donde es necesaria una que otra impresión, eso depende del uso, no me parece un error así macro, más bien es una costumbre adquirida o un habito que no termina que gustar en general  :P :P

Es por ello que existen excepciones no?? me gusta relacionar ese tipo de cosas para C, porque no existen excepciones (así como en una forma explicita como en C++) que se manejen de manera, como decirlo, automatica por parte del compilador o del IDE.

aunque el detalle que mencionas tienes razón, es mejor iniciar la variable para el control.   :)



do-while

#18
¡Buenas!

No lo digo porque esté mal, el código evidentemente funciona si lo haces así. Lo digo por organizar bien el código. Una función un trabajo. Esa es la filosofía, mientras puedas mantenerla, evidentemente. Lo lógico es que hagas una función para recoger los datos, esta dependerá de la interfaz que estés utilizando en cada momento, y otra que compruebe su corrección, que solo tendrás que implementarla una vez y si funciona correctamente nunca mas la tendrás que volver a tocar, y la podrás utilizar en windows, en mac en castellano en latín o incluso en chino, ya que al no depender de la interfaz ni del idioma la podrás utilizar donde y cuando te de la gana (siempre y cuando no haya dependencias de librerías ajenas al código que tu mismo facilites o hayas creado).

¡Saludos!

Acabo de ver lo de las excepciones. Hace poco volví a coger C++, con el nuevo estandar, la STL... ha cambiado muchísimo desde el primer contacto que tuve con el... y las excepciones no me gustan nada.  :xD, si tengo que decirle algo a la función llamadora, le paso un código de error y que ella lo trate como le de la gana. A lo mejor no he estudiado como debería las excepciones, pero me parece una chorrada crear una clase y bloques try, catch, para algo que se ha hecho de toda la vida (o por lo menos yo así lo he hecho) devolviendo enteros y con un switch...

¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!