Ano Bissexto - Linguagem C

Oi pessoal, o código abaixo é pra calcular o ano bissexto, aparentemente o resultado está sendo o correto, mas na apostila a implementação parece ser muito melhor do que a minha, pensando apenas na eficiência do código, o meu está correto, quer dizer o resultado é o esperado?

[code]#include <stdio.h>
#include <stdlib.h>

int main()
{

int m,d,a;

do{
    printf ("Entre com o dia [1,31]: ");
    scanf ("%d", &d);
    }while(d<1||d>31);
    
do{
    printf ("Entre com o mes [1,12]: ");
    scanf ("%d", &m);
    }while(m<1||m>12);
    
do{
    printf ("Entre com o ano [1900,2100]: ");
    scanf ("%d", &a);
    }while(a<1900||a>2100);
    
    if(a%4==0 || a%100!=0 || a%400==0)
      printf ("\nO ano %d e bissexto.\n", a);          
     
     printf ("\nData: %d/%d/%d \n\n", d,m,a);
                  
system("PAUSE");
return (0);

}
[/code]

Paloma:

Seu código está errado, porque:

  • Aceita datas inválidas, como 30/02, por exemplo.
  • A verificação de ano bissexto está incorreta, deveria ser:
    if(a%4==0 && (a%100!=0 || a%400==0))

Abraço,

Armando

[quote=armando]Paloma:
Seu código está errado, …deveria ser:
if(a%4==0 && (a%100!=0 || a%400==0))
[/quote]

Armando, acho que o seu também está.

Meu algorítmo é diferente do seu (este eu escrevi há uns 16 anos atrás). A parte diferente é que o OU tem que ser EXCLUSIVO para os módulos de 100 e 400, e em C não existe OU EXCLUSIVO, aliás só vi OU exclusivo até hoje em BASIC e ASSEMBLER.

Por isto há a condição p/ verificação do terceiro módulo, pois não podemos ter ano bissexto cujo (a%100!=0 && a%400==0), e o “ou” “||” permite isto, por não ser exclusivo.

Aliás, este maldito “ou exclusivo” é motivo de discussões em qualquer questão de estatística.

#define UTIL_ANO_BISSEXTO(ano) (!((ano)%4) ?(!((ano)%100) ?(!((ano)%400) ?1 :0) :1) :0)
Por favor, não critiquem a macro. Foi escrita em C ANSI, que não tem funções inline, por isto a macro para não replicar código, já que uma função nos traria uma entrada a mais na pilha seguida de mais um “call” - problema sério para o desempenho na época.

Então quer dizer que desta forma está incorreto?

if(a%4==0 && (a%100!=0 || a%400==0)) printf ("\nO ano %d e bissexto.\n", a);

Sendo preciosista, sim. Está errado.

Já que este ou “||” não invalida a condição quando ambas as partes da condição no OU forem verdadeiras, ou seja, quando um && se aplicar.

Este OU tem nome: é o “XOR”, mas não o temos em C e nem em Java como um operador condicional. Não confundir com o XOR para operações binárias “^”.

Em BASIC, existia o tal do XOR, escrito mais ou menos assim:

if (exp1 XOR exp2) then goto 100

Pensando… talvez fosse legal se existisse um correspondente usando o “^^”, mas fica horrível:

if (expr1 ^^ expr2) { ...}

Incrível ! Acabei de testar, e a Microsoft absorveu bem o BASIC no VB. O também VB tem o XOR, e funciona.

Paloma e Armando. Desculpe-me. Muito bonito o assunto do XOR, mas creio estar enganado. Não li a expressão, e me baseie num comentário no código, que parece não ter o menor sentido, pois se algo for divisivel por 400 certamento o será por 100 também.

Esqueça o XOR, não sei de onde surgiu este comentário sem sentido, no código.

[quote=lucianomx]Paloma e Armando. Desculpe-me. Muito bonito o assunto do XOR, mas creio estar enganado. Não li a expressão, e me baseie num comentário no código, que parece não ter o menor sentido, pois se algo for divisivel por 400 certamento o será por 100 também.

Esqueça o XOR, não sei de onde surgiu este comentário sem sentido, no código.[/quote]

if (ANO%4==0 && (ANO%400==0 ||ANO%100!=0)) cout<<”Ano Bissexto”; else cout<<”Ano não é Bissexto”;

Oi pessoal, o programa agora tá rodando certinho, mas meu código tá muito feio, alguém tem uma idéia pra que fique mais legível?

[code]#include <stdio.h>
#include <stdlib.h>

int main()
{
int d,m,a;

printf ("\t\t\tCALENDARIO ANO BISSEXTO\n\n");

do{
 do{
    printf ("Entre com o dia [1,31]: ");
    scanf ("%d", &d);
    }while(d<1||d>31);
    
    do{
    printf ("Entre com o mes [1,12]: ");
    scanf ("%d", &m);          
    }while(m<1||m>12);
    
    if((d==30 || d==31) && (m==2))
      printf ("\nData Invalida, digite novamente.\n\n");
      
    }while((d==30 || d==31) && (m==2));
    
if((d==30 || d==31) && (m==2))
{
  printf ("Data Invalida.\n\n");
  return(0);
  }
       
do{
    printf ("Entre com o ano [1900,2100]: ");
    scanf ("%d", &a);
    }while(a<1900||a>2100);
    
    if(a%4==0 && (a%100!=0 || a%400==0))
      printf ("\nO ano %d e bissexto.\n", a);          
     
     printf ("\nData: %d/%d/%d \n\n", d,m,a);
                  
system("PAUSE");
return (0);

}
[/code]

Não use C :smiley:

Vc tá falando pra não usar a linguagem C? :roll:

Uma forma ‘suja’ seria deixar o C tentar converter a data

[code]#include <time.h>
#include <stdio.h>

int main(void)
{
int d,m,a;
struct tm t;
time_t t_of_day;

for(;;) {
	printf ("Digite a data no formato dd/mm/yyyy \n");

	scanf("%d/%d/%d",&d,&m,&a);

	t.tm_year  = a - 1900;
	t.tm_mon   = m - 1;
	t.tm_mday  = d;
	t.tm_hour  = 0;
	t.tm_min   = 0;
	t.tm_sec   = 0;
	t.tm_isdst = 0;

	t_of_day = mktime(&t);
	if(t_of_day <= 0)	        
        	printf("!!!data invalida!!!\n");
        else
        	break;
}

return 0; 

}[/code]

Em C mais basico

[code]#include <time.h>
#include <stdio.h>

int main(void)
{
int dia,mes,ano;
int ultimo_dia[] = {-1,31,28,31,30,31,30,31,31,30,31,30,31};

for(;;) {
	printf ("Digite a data no formato dd/mm/yyyy \n");

	scanf("%d/%d/%d",&dia,&mes,&ano);

	// testa coisas obvias: dia/ano negativo,mes invalido 			
	if(dia<=0||mes<1||mes>12||ano<=0){	
		printf("Data invalida\n");
		continue;
	}
	
	// atualiza o ultimo dia do mes se bissexto
	if(ano%4==0 && (ano%400==0 || ano%100!=0))
		ultimo_dia[2]=29;					
	else
		ultimo_dia[2]=28;

	// verifica se o dia eh maior que o ultimo dia do ano
	if(dia>ultimo_dia[mes])
		printf("Data invalida\n");
	else 
		break;
}

return 0; 

}[/code]

eu completei o codigo
[size=18][/size]
#include <stdio.h>
#include <stdlib.h>

int main()
{
  
  int dia , mes ,ano;
  int ultimo_dia[]= {-1,31,28,31,30,31,30,31,31,30,31,30,31};
  for (;;){
      printf(&quot;digite o dia---&gt;&quot;);
      scanf (&quot;%d&quot;,&dia);
      system (&quot;cls&quot;);
      printf(&quot;digite o mes---&gt;&quot;);
      scanf(&quot;%d&quot;,&mes);
      system (&quot;cls&quot;);
      printf (&quot;digite o ano---&gt;&quot;);
      scanf(&quot;%d&quot;,&ano);
      system(&quot;cls&quot;);
      if(dia&lt;=0 ||mes&lt;0||mes&gt;12||ano&lt;=0)
      {
         printf(&quot;data invalida\n&quot;);
         continue;
         system(&quot;pause&quot;);
      }
      if (ano%4==0&& (ano%400==0 ||ano%100!=0))
      ultimo_dia[2]= 29;
      else
      ultimo_dia[2]= 28;
      if(dia &gt;ultimo_dia[mes])
      {
      printf(&quot;data invalida\n&quot;);
                   continue;
      }
      if (ano%4==0 && (ano%400==0||ano%100!=0))
      {
      printf(&quot;ano bissexto\n\n&quot;);
      }
    printf(&quot;%d/%d/%d\n&quot;,dia,mes,ano);
  	
 break;     
} 
system(&quot;PAUSE&quot;);
 return 0;
}