Wątek przeniesiony 2014-01-13 12:23 z C/C++ przez ŁF.

Błąd w prostym programie.

0

Cześć, jestem początkujący i potrzebuję pomocy bardziej doświadczonych w tej dziedzinie. Nie potrafię znaleźć błędu w programie, który wylicza dzień tygodnia dla podanej daty. Otóż wyświetla jeden dzień do tyłu dla dat z 2014, a dla innych o 2 albo 3 dni wstecz. Czy ktoś wie, gdzie leży problem?

#include <stdio.h>
#include <stdlib.h>

  
  char *dni_tygodnia[7] = {"sobota", "niedziela", "poniedzialek", "wtorek", "sroda", "czwartek", "piatek"};
  int dni_mies[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  int mies_roku[12];

int sprawdzenie_daty(int d, int m, int r)
{
    return (d > 0 && d <= dni_mies[m-1]) && (m >= 1 && m <= 12) && (r >= 1582 && r <= 2999);
}

int rok_przestepny(int r)
{
    return (r%400 == 0 || (r%4 == 0 && r%100 != 0));
}

int zlicz_dni()
{
    int i;
    for(i = 1; i < 12; i++)
    {
          mies_roku[i] = mies_roku[i-1] + dni_mies[i-1];
    }
    return i;
}

int liczba_przestepnych(int r)
{
    int i;
    int przestep = 0;
    for(i = 1; i < r; i++)
    {
          if(rok_przestepny(i))
          przestep++;
    }
    return przestep;
}


int main(int argc, char *argv[])
{
  
  int d, m, r;
  
  printf("Date nalezy wpisac wedlug podanego wzoru: dd.mm.rrrr\n\n");
  printf("Podaj date:\n");
  scanf("%d %d %d", &d, &m, &r);
  
  if(rok_przestepny(r)) 
                        dni_mies[1] = 29;
  else
                        dni_mies[1] = 28;
  
  if(sprawdzenie_daty(d, m, r))
                         return 0;
  zlicz_dni();
  
  printf("%s\n", dni_tygodnia[(d + mies_roku[m-1] + r + liczba_przestepnych(r))%7]);
  
  
  system("PAUSE");    
  return 0;
}

0

Przy wpisywaniu daty, jeżeli określiłeś taki format: dd.mm.rrrr to warto wczytywać tak:

scanf("%d.%d.%d", &d, &m, &r);

Sprawdzanie poprawności daty

if(!sprawdzenie_daty(d, m, r))
   return 0;
0

Tak, wiem, ale wtedy niezależnie jaką datę podam konsola się zamyka :/

0

Jesteś pewien?
Pamiętaj, że przy wpisywaniu należy datę podać tak jak napisałeś w poleceniu, czyli np. 12.01.2014 (z kropkami).

4
int liczba_przestepnych(int r)
...
    for(i = 1; i < r; i++)

Co ta funkcja właściwie ma zwracać?
Skoro w sprawdzenie_daty zakładasz że rok ma być >= 1582 (rozsądnie) to dlaczego tutaj w pętli liczysz od 1?

Datą początkową kalendarza gregoriańskiego jest piątek 15 października 1582. Traktuj to jako punkt odniesienia, z poprawką na dni przestępne od tego momentu, a nie od AD 1.

2

Ja tu widzę błąd:

int sprawdzenie_daty(int d, int m, int r)
{
    if (m==2 && d==29 && rok_przestepny(r))
         return 1;
    return (d > 0 && d <= dni_mies[m-1]) && (m >= 1 && m <= 12) && (r >= 1582 && r <= 2999);
}

zresztą tak jak wytknął @Azarien powinieneś też uwzględnić początek kalendarza (specjalnie potraktować 1582rok).
2

Przerobiłem kod implementując bardzo naiwny a miejscami genialny algorytm mojego autorstwa, ale tak naprawdę istnieją na to lepsze i krótsze wzory.

#include <stdio.h>
#include <stdlib.h>

const char *dni_tygodnia[7] = {"czwartek", "piatek", "sobota", "niedziela", "poniedzialek", "wtorek", "sroda"};
const int dni_mies[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
int rok_przestepny(int r)
{
    return (r%400 == 0 || (r%4 == 0 && r%100 != 0));
}

int sprawdzenie_daty(int d, int m, int r)
{
    return r > 1582 && r <= 2999 && 
		   (m >= 1 && m <= 12 && d > 0 && d <= dni_mies[m-1] ||  m == 2 && d == 29 && rok_przestepny(r)) ||
		   r == 1582 && ((m == 11 || m == 12) && d > 0 || m == 10 && d >= 15) && d <= dni_mies[m-1];
}

int liczba_przestepnych(int m, int r)
{
    int i;
    int przestep = 0;
    for(i = 1584; i < r; i += 4)
    {
          if(rok_przestepny(i))
          przestep++;
    }
	
	if (m>=3 && rok_przestepny(r))
		przestep++;

    return przestep;
}

int dzien_tygodnia(int d, int m, int r)
{
	int dzien = (r-1582) * 365;
	dzien += liczba_przestepnych(m, r);
	for (int n=0; n<m-1; n++)
		dzien += dni_mies[n];
	dzien += d;
	return dzien % 7;
}

int main(int argc, char *argv[])
{ 
  int d, m, r;
 
  printf("Date nalezy wpisac wedlug podanego wzoru: dd.mm.rrrr\n\n");
  printf("Podaj date:\n");
  scanf("%d %d %d", &d, &m, &r);
 
  if(!sprawdzenie_daty(d, m, r))
      return 0;

  printf("%s\n", dni_tygodnia[dzien_tygodnia(d, m, r)]);
 
  system("PAUSE");    
  return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1