Pasar string a time. Número de días entre dos fechas

Iniciado por capitandelpanel, 9 Mayo 2015, 12:56 PM

0 Miembros y 2 Visitantes están viendo este tema.

capitandelpanel

Buenas!

Necesito un programa que me calcule el número de días que faltan desde una fecha (que introduce el usuario por teclado) a la fecha actual. Por ahora lo que llevo echo es que me diga el día del año en el que estamos:

int main()
{
time_t tiempo,puntero;
char ,diaano[80],
int aux;
struct tm *tmPtr;

tiempo = time(NULL);
tmPtr = localtime(&tiempo);

strftime( diaano, 80, "%j", tmPtr);

printf("El dia del año es: %s\n", diaano );

aux = atoi( diaano );

return 0;
}


Ahora necesito hacer el mismo proceso con la fecha que introduce el usuario y luego restar estos dos números. Lo que no doy conseguido es pasar un string(la fecha que introduce el usuario) a un dato tipo time.

Asi mismo el programa también me tiene que saltar un aviso si la fecha que introducimos es anterior a la fecha actual.

¿alguna solución?

gracias

rir3760

Para obtener la diferencia (en segundos) de dos fechas puedes utilizar la función difftime, esta requiere dos argumentos de tipo time_t, el primero es la fecha actual y la obtienes mediante una llamada a la función time.

La segunda fecha la introduce el usuario, aquí puedes obtener directamente los valores de dia, mes y año para una estructura tipo "struct tm" y a partir de esta obtener uno de tipo time_t con mktime. Mas o menos así:
struct tm d = {0};
time_t b;

puts("Introduce la fecha (aaaa mm dd):");
if (scanf("%d %d %d", &d.tm_year, &d.tm_mon, &d.tm_mday) != 3)
   return EXIT_FAILURE;
d.tm_year -= 1900; /* 0 == 1900, 100 == 2000, etc. */
d.tm_mon--; /* 0 == Enero, 1 == Febrero, etc. */

/* Validacion de los campos tm_year, tm_mon y tm_mday */

b = mktime(&d);

/* ... */


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Peregring-lk

#2

#include "stdio.h"
#include "time.h"

#define SEGS_DIA 86400

int main()
{
 struct tm fecha = {}; // Inicializamos la estructura a 0.

 // Asumimos que el formato de fecha introducido por el usuario es correcto.
 printf("Introduce la fecha: ");
 scanf("%u%u%u", &fecha.tm_mday, &fecha.tm_mon, &fecha.tm_year);

 --fecha.tm_mon; // La estructura tm numera los meses del 0 al 11.
 fecha.tm_year -= 1900; // Los annos comienzan en 1900.

 // No utilizo difftime porque devuelve un `double` y me da coraje.
 int diff = (mktime(&fecha) - time(NULL)) / SEGS_DIA;

 printf("\nLa diferencia es: %d\n", diff);

 return 1;
}


Si quisiéramos comprobar el formato de entrada mejor, el `scanf` sería algo más "complejo":


char truco;

int leidos = scanf("%2u%2u%4u%c", &fecha.tm_mday, &fecha.tm_mon, &fecha.tm_year, &truco);

if (leidos != 3)
 exit(EXIT_FAILURE);

if (tm_year < 1000) // Asumimos que el anno debe tener al menos 4 digitos.
 exit(EXIT_FAILURE);


Los numeritos (el 2 o el 4) son para indicar el "ancho" máximo que tendrá cada campo. El otro "truco" (la `%c` final) sirve para evitar que el usuario introduzca cadenas más largas de la cuenta; por ejemplo: "24 11 19900asd". El formato de entrada sería correcto para `scanf`, porque los cuatro primeros dígitos del campo "año" se guardan correctamente.

El problema es que `scanf` deja de "leer" e ignora el resto de la cadena, así que lo forzamos a leer al menos uno más, y si ha recuperado 4, es que la cadena era demasiado larga.

rir3760

Cita de: Peregring-lk en 17 Mayo 2015, 01:47 AMEl otro "truco" (la `%c` final) sirve para evitar que el usuario introduzca cadenas más largas de la cuenta; por ejemplo: "24 11 19900asd".
El especificador "%c" al igual que "%[]" no descartan el espacio blanco inicial, por ello una linea que consista de los tres numeros (validos) para la fecha seguida del avance de linea (lo usual) resultara en la función scanf retornando cuatro.

La aproximación mas sencilla (en este caso) es utilizar scanf para leer y validar los tres números, a continuación se utiliza un bucle con getchar para verificar que el resto solo sea espacio/tabulador/etc. seguidos del carácter '\n'.

O bien se puede utilizar solo scanf pero queda (en mi opinión) muy feo:
int leidos =
   scanf("%2u%2u%4u", &fecha.tm_mday, &fecha.tm_mon, &fecha.tm_year) == 3
   && (scanf("%*[ \t]"), scanf("%1[\n]", &truco) == 1)
;


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Peregring-lk

Tienes razón en lo del carácter fin de línea. Mi solución es, quizás, más adecuada para cadenas recibidas como parámetro (`sscanf`), que para comprobar directamente la entrada. De todas formas, ¿no es ésta una solución más sencilla?

Código (cpp) [Seleccionar]

/* Con barras invertidas para que tenga más "pinta" de fecha :)
leidos = scanf("%2u/%2u/%4u%c", &dia, &mes, &anno, &truco);

if (leidos < 3)
    exit(EXIT_FAILURE);

if (leidos > 3 && truco != '\n'))
   exit(EXIT_FAILURE);


De ésta forma, solo permitimos una fecha seguida inmediatamente por un salto de línea. No creo que haga falta comprobar todo lo que venga detrás, sencillamente, con obligar al usuario a escribir la fecha y luego justo después, pulsar "Intro", sería suficiente.

rir3760

#5
Cita de: Peregring-lk en  2 Junio 2015, 11:46 AM¿no es ésta una solución más sencilla?
En el caso que mencionas si, es mas corta.

Por cierto se puede abreviar un poco mas. Cuando la fecha para ser valida solo puede ser seguida del avance de linea puedes indicarlo en la cadena de formato con "%1[\n]" y verificar que el resultado de la función sea igual a cuatro. Mas o menos así:
if (scanf("%2u/%2u/%4u%1[\n]", &dia, &mes, &anno, &truco) == 4){
   puts("OK");
}else {
   puts("Entrada no valida");
}


Edito: Ups, el especificador "%[]" almacena los caracteres coincidentes seguidos de un '\0' por lo que el objeto destino no puede ser una variable de tipo char sino un array de estos (mea culpa).

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language