/*
* File: imprima_calendario.c
* --------------------------
* Este programa imprime um calendario para o ano dado pelo
* usuario. (O ano deve ser pelo menos 1900.)
*
* Este programa foi adaptado do livro "The Art and Science of C", de
* Eric S. Roberts. Veja em:
*
* http://cseng.awl.com/bookdetail.qry?ISBN=0-201-54322-2&ptype=0
*
*/
#include <stdio.h>
/* ************************************************************
* Constantes:
* -----------
* Os dias da semana sao representados pelos inteiros de 0 a 6.
* Os meses do ano sao representados pelos inteiros de 1 a 12.
*/
#define domingo 0
#define segunda 1
#define terca 2
#define quarta 3
#define quinta 4
#define sexta 5
#define sabado 6
#define VERDADEIRO 1
#define FALSO 0
/****************************************************************/
/* Prototipos de funcoes */
/****************************************************************/
void forneca_instrucoes(void);
int obtenha_ano(void);
void imprima_calendario(int ano);
void imprima_calendario_do_mes(int mes, int ano);
void indente_primeira_linha(int dia_da_semana);
int numero_de_dias_do_mes(int mes, int ano);
int primeiro_dia_do_mes(int mes, int ano);
int eh_bissexto(int ano);
void imprima_cabecalho(int mes, int ano);
/****************************************************************/
/* Programa principal */
/****************************************************************/
int main()
{
int ano;
forneca_instrucoes();
ano = obtenha_ano();
imprima_calendario(ano);
return 0;
}
/*****************************************************************
* Funcao: forneca_instrucoes()
* Uso: forneca_instrucoes();
* --------------------------
* Esta funcao imprime uma mensagem com intrucoes
* para o usuario.
*/
void forneca_instrucoes(void)
{
printf("Este programa imprime o calendario para um dado ano.\n");
printf("O ano nao pode ser anterior a 1900.\n");
}
/*****************************************************************
* Funcao: obtenha_ano()
* Uso: ano = obtenha_ano();
* ---------------------------
* Esta funcao le um ano digitado pelo usuario. Se o usuario fornece
* um ano anterior a 1900, a funcao avisa que o ano deve ser pelo menos 1900.
* Quando um tal valor e' fornecido, a funcao devolve esse valor.
*/
int obtenha_ano(void)
{
int ano;
while (VERDADEIRO) {
printf("Calendario de que ano? ");
scanf("%d", &ano);
if (ano >= 1900){
printf("Calendario de %d\n\n", ano);
return ano;
}
printf("O ano precisa ser pelo menos 1900.\n");
}
}
/*****************************************************************
* Funcao: imprima_calendario()
* Uso: imprima_calendario(ano);
* -----------------------------
* Esta funcao imprime o calendario do ano dado.
*/
void imprima_calendario(int ano)
{
int mes;
for (mes = 1; mes <= 12; mes++) {
imprima_calendario_do_mes(mes, ano);
printf("\n");
}
}
/****************************************************************
* Funcao: imprima_calendario_do_mes()
* Uso: imprima_calendario_do_mes(mes, ano);
* ---------------------------------------
* Esta funcao imprime o calendario de um dado mes e ano.
*/
void imprima_calendario_do_mes(int mes, int ano)
{
int dia_da_semana, n_dias, dia;
imprima_cabecalho(mes, ano);
printf(" Do Se Te Qu Qu Se Sa\n");
n_dias = numero_de_dias_do_mes(mes, ano);
dia_da_semana = primeiro_dia_do_mes(mes, ano);
indente_primeira_linha(dia_da_semana);
for (dia = 1; dia <= n_dias; dia++) {
printf(" %2d", dia);
if (dia_da_semana == sabado)
printf("\n");
dia_da_semana = (dia_da_semana + 1) % 7;
}
if (dia_da_semana != domingo)
printf("\n");
}
/****************************************************************
* Funcao: imprima_cabecalho()
* Uso: imprima_cabecalho(mes, ano);
* ---------------------------------
* Esta funcao imprime um cabecalho para
* o calendario do mes do ano dado.
*/
void imprima_cabecalho(int mes, int ano)
{
switch(mes) {
case 1: printf(" Janeiro"); break;
case 2: printf(" Fevereiro"); break;
case 3: printf(" Marco"); break;
case 4: printf(" Abril"); break;
case 5: printf(" Maio"); break;
case 6: printf(" Junho"); break;
case 7: printf(" Julho"); break;
case 8: printf(" Agosto"); break;
case 9: printf(" Setembro"); break;
case 10: printf(" Outubro"); break;
case 11: printf(" Novembro"); break;
case 12: printf(" Dezembro"); break;
default: printf("Nao pode acontecer!\n"); exit(0);
}
printf(" %d\n", ano);
}
/*
* Funcao: indente_primeira_linha()
* Uso: indente_primeira_linha(dia_da_semana);
* -------------------------------------------
* Esta funcao indenta a primeira linha de um calendario
* de um mes, imprimindo o numero suficiente de brancos
* para colocar o cursor na posicao correta para a impressao
* do primeiro dia daquele mes, que cai no dia da semana
* dado como parametro (dia_da_semana).
*/
void indente_primeira_linha(int dia_da_semana)
{
int i;
for (i = 0; i < dia_da_semana; i++) {
printf(" ");
}
}
/*
* Funcao: numero_de_dias_do_mes()
* Uso: n_dias = numero_de_dias_do_mes(mes, ano);
* ----------------------------------------------
* Esta funcao devolve o numero de dias do dado mes do
* dado ano.
*/
int numero_de_dias_do_mes(int mes, int ano)
{
switch (mes) {
case 2:
if (eh_bissexto(ano)) return 29;
return 28;
case 4: case 6: case 9: case 11:
return 30;
default:
return 31;
}
}
/*
* Funcao: primeiro_dia_do_mes();
* Uso: dia_da_semana = primeiro_dia_do_mes(mes, ano);
* ---------------------------------------------------
* Esta funcao devolve o dia da semana em que cai o dia
* primeiro do mes dado do ano dado.
*
* O metodo que usamos para determinar este dia da semana
* 'e simples: usamos o fato que 1/1/1900 foi uma
* segunda-feira e contamos o numero de dias decorridos
* desde entao ate a data em questao.
*/
int primeiro_dia_do_mes(mes, ano)
{
int dia_da_semana, i;
dia_da_semana = segunda;
for (i = 1900; i < ano; i++) {
dia_da_semana = (dia_da_semana + 365) % 7;
if (eh_bissexto(i)) dia_da_semana = (dia_da_semana + 1) % 7;
}
for (i = 1; i < mes; i++) {
dia_da_semana = (dia_da_semana + numero_de_dias_do_mes(i, ano)) % 7;
}
return dia_da_semana;
}
/*
* Funcao: eh_bissexto()
* Uso: if (eh_bissexto(ano)) . . .
* ----------------------------------
* Esta funcao devolve VERDADEIRO se o dado ano
* 'e bissexto.
*/
int eh_bissexto(int ano)
{
return ((ano % 4 == 0) && (ano % 100 != 0))
|| (ano % 400 == 0);
}