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, botów: 0