C/Visual C - Problema en programa de calendario

 
Vista:
sin imagen de perfil

Problema en programa de calendario

Publicado por Daniel (2 intervenciones) el 14/01/2024 02:54:44
Buenas estoy en 1º año de carrera y me han pedido una práctica de hacer el calendario de un mes. Pero tengo un problema en el cálculo de la variable primerDia que calcula el primer día del mes. Falla cuando la semana empieza en domingo (es decir día 1 en domingo). El fallo está seguro en esa variable pero no consigo arreglarlo de ninguna forma y todas las fórmulas que encuentro tienen en cuenta el domingo como el primer día del calendario y ya no sé qué hacer. (También al final del mes en lugar de espacios deberían imprimirse puntos pero no me he puesto todavía a ello aunque tampoco logré mucho cuando lo intenté). Por cierto si veis algo raro es porque el lenguaje que uso se lo han inventado y lo han llamado C+- como una supuesta mezcla entre C y C++, mejor no preguntéis. Este es el código:

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
#include <stdio.h>
#include <string.h>
 
/* Función para saber si un año es bisiesto o no*/
bool esBisiesto(int anno) {
  return(((anno % 4 == 0) && (anno % 100 != 0)) || (anno % 400 == 0));
}
 
int determinarPrimerDia(int anno, int mes){
	int primerDia;
	int d1, d2, d3;
 
	d1 = (anno - 1)/ 4;
	d2 = (anno - 1)/ 100;
	d3 = (anno - 1)/ 400;
	primerDia = (anno + d1 - d2 + d3) %7;
 
  // Calcular días acumulados de los meses anteriores
  for (int i = 1; i < mes; i++) {
    switch (i) {
      case 4: case 6: case 9: case 11:
        primerDia = (primerDia + 30) % 7;
        break;
      case 2:
        if (esBisiesto(anno)) {
          primerDia = (primerDia + 29) % 7;
        } else {
          primerDia = (primerDia + 28) % 7;
        }
        break;
      default:
        primerDia = (primerDia + 31) % 7;
    }
  }
  if (primerDia < 1) {
    primerDia++;
    return primerDia;
  } else {
	  return primerDia;
  }
}
 
 
/* Función para imprimir el calendario*/
void imprimirCalendario(int anno, int mes) {
  const int NumeroMeses = 13;
  typedef int TipoMes[NumeroMeses];
  const char nombresMeses[NumeroMeses][15] = {"","ENERO", "FEBRERO", "MARZO", "ABRIL", "MAYO", "JUNIO", "JULIO", "AGOSTO", "SEPTIEMBRE", "OCTURBRE", "NOVIEMBRE", "DICIEMBRE"};
  int primerDia;
  TipoMes diasEnMes = {0};
  int contadorBarra = 1;
 
  primerDia = determinarPrimerDia(anno, mes) - 1;
 
  if (esBisiesto(anno)) {
    diasEnMes[2] = 29;
  } else {
    diasEnMes[2] = 28;
  }
 
  diasEnMes[1] = 31;
  diasEnMes[3] = 31;
  diasEnMes[4] = 30;
  diasEnMes[5] = 31;
  diasEnMes[6] = 30;
  diasEnMes[7] = 31;
  diasEnMes[8] = 31;
  diasEnMes[9] = 30;
  diasEnMes[10] = 31;
  diasEnMes[11] = 30;
  diasEnMes[12] = 31;
 
  printf("\n%s                %4d\n", nombresMeses[mes], anno);
  printf("==============================\n");
  printf("  LU  MA  MI  JU  VI |  SA  DO\n");
  printf("==============================\n ");
 
 
  for (int i = 0; i < primerDia; i++) {
    contadorBarra++;
    printf("  . ");
    if (contadorBarra == 6) {
      printf("| ");
    }
  }
 
/*  */
  for (int dia = primerDia + 1; dia <= diasEnMes[mes]+(primerDia); dia++ ) {
    if (dia <= diasEnMes[mes]+primerDia) {
      printf("%3d", dia-primerDia);
      if(contadorBarra == 5) {
        printf(" |");
      }
    } else {
      printf(" . ");
      if(contadorBarra == 5) {
        printf(" |");
      }
    }
      contadorBarra++;
 
/* Imprimir los espacios entre días y el salto de fila al final de la semana */
    if ( dia % 7 > 0 ) {
      printf(" ");
    }	else {
      printf("\n " );
      contadorBarra = 1;
    }
  }
}
 
 
 
int main() {
    int anno, mes;
 
    /* Solicitar al usuario que ingrese un año */
    printf("Mes (1...12)? \n");
    scanf("%d", &mes);
    printf("Año (1601...3000)? \n");
    scanf("%d", &anno);
 
    /* Validar si el año está en el rango permitido */
    if (anno > 1600 && anno < 3001) {
        imprimirCalendario(anno, mes);
    } else {
        printf("Por favor, ingrese un año válido.\n");
    }
 
    return 0;
}
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil

Problema en programa de calendario

Publicado por Daniel (2 intervenciones) el 14/01/2024 03:14:07
Ah cierto que se me olvidó comentarlo, el compilador es GNU GCC Compiler
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 89
Ha mantenido su posición en C/Visual C (en relación al último mes)
Gráfica de C/Visual C

Problema en programa de calendario

Publicado por Bruno (38 intervenciones) el 16/01/2024 20:54:08
Dejo un aporte de un mensual, espero le pueda servir a alguien.

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define TRUE 1
#define FALSE 0
 
#define DAYS_IN_WEEK 7
#define WEEK_IN_MONTH 6
 
#define FEBRUARY 2
 
int isLeapYear (int _year) {
  if (((_year % 4 == 0) && (_year % 100 != 0)) || (_year % 400 == 0))
    return TRUE;
  else
    return FALSE;
}
 
int getDaysOfMonth (int month_, int year_) {
    const int DAYS_OF_MONTH[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int days = DAYS_OF_MONTH[month_];
 
    if (month_ == FEBRUARY && isLeapYear(year_))
      days = days + 1;
 
    return days;
}
 
/* Para determinar el día de la semana de una fecha arbitraria
*  en base al algoritmo matemático de Gauss.
*  Numeró los días de la semana del 0 al 6 comenzando con el domingo.
*  @day_ int día de la fecha
*  @month_ int mes de la fecha
*  @year_ int año de la fecha
*  @return int 0>=x<=6
*/
int getDayOfWeek (int day_, int month_, int year_) {
    // Arreglos de búsquedas
    int COMMON_YEAR[] = { 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 };
    int LEAP_YEAR[] = { 0, 3, 4, 0,	2, 5, 0, 3, 6, 1, 4, 6 };
 
    // Adecuamos month_ por el índice 0 de los arreglos
    int adapterMonth = month_ - 1;
 
    int aux = day_ + COMMON_YEAR[adapterMonth];
    if (isLeapYear(year_))
        aux = day_ + LEAP_YEAR[adapterMonth];
 
    return (
        (aux +
            (5 * ((year_ - 1) % 4)
                + 4 * ((year_ - 1) % 100)
        	    + 6 * ((year_ - 1) % 400)
        	)
        ) % 7
    );
}
 
/* Devuelve una matriz con el mes del año determinado.
*  @mont_ int mes de la fecha
*  @year_ int año de la fecha
*  @return int [][] el mensual
*
*  La matriz monthly contiene el mensual y comienza con el
*  indice 0 como domingo. Las filas indican la semanas y
*  es suficientemente grande para que pueda contener un mes
*  que tiene 31 días con su primer día que caiga sábado. Se
*  inicializa en 0 con calloc y luego se asignan los números
*  de días según corresponda su posición.
*/
int ** getMonthly (int month_, int year_) {
    int firstDayOfMonth = getDayOfWeek(1, month_, year_);
    int daysOfMonth = getDaysOfMonth(month_, year_);
    int **monthly;
    int day, week;
    int count = 1;
 
    monthly = (int **) malloc(WEEK_IN_MONTH * sizeof(int *));
    for (week = 0; week < WEEK_IN_MONTH; week++)
        monthly[week] = (int *) calloc(DAYS_IN_WEEK, sizeof(int));
 
    day = firstDayOfMonth;
    week = 0;
    while (count <= daysOfMonth) {
        monthly[week][day++] = count++;
        if (day == DAYS_IN_WEEK) {
            day = 0;
            week++;
        }
    }
 
    return monthly;
}
 
void printMonthly (int ** monthly_) {
    int week, day;
    char out[4];
 
    printf("\n D  L  M  M  J  V  S\n\n");
 
    for (week = 0; week < WEEK_IN_MONTH; week++) {
        for (day = 0; day < DAYS_IN_WEEK; day++) {
            if (monthly_[week][day] == 0)
                strcpy(out, " ");
            else
                sprintf(out, "%i", monthly_[week][day]);
 
            if (monthly_[week][day] < 10)
                printf(" %s ", out);
            else
                printf("%s ", out);
            }
 
        printf("\n");
    }
}
 
int main()
{
    int MONTH = 2;
    int YEAR = 2024;
 
    printf("\n");
    printMonthly(getMonthly (MONTH, YEAR));
 
    return 0;
}

1
2
3
4
5
6
7
8
Output:
D  L  M  M  J  V  S
 
             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
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar