Zadanie z matury: Gdzie błąd?

0

Próbowałem swoich sił w jednym z zadań które kiedys pojawiło sie na maturze i gdześ mam błąd.
Zły wynik wychodzi dla lat z kalendarza gregoriańskiego czyli błąd powinien być gdzieś pod:

// Dla naszych lat:D............................................................
Według kalendarza juliańskiego wprowadzonego przez Juliusza Cezara od roku 45 p.n.e., każdy rok nieprzestępny trwał 365 dni, a rok przestępny przypadający dokładnie co 4 lata trwał 366 dni.
Ustalenia te spowodowały, że na każde 128 lat pojawiała się różnica jednego dnia pomiędzy tym kalendarzem, a kalendarzem astronomicznym. Aby zlikwidować narastający błąd, w roku 1582 zastąpiono kalendarz juliański kalendarzem gregoriańskim. Nowy kalendarz obowiązuje od 4 października 1582 roku, kiedy po czwartku 4 października 1582 nastąpił piątek 15 października 1582 r.
Latami przestępnymi w kalendarzu juliańskim były wszystkie te lata, które dzieliły się bez reszty przez 4.
Według kalendarza gregoriańskiego latami przestępnymi są te, które dzielą się bez reszty przez 4, z wyjątkiem tych, które dzielą się bez reszty przez 100, a nie dzielą się bez reszty przez 400.
a) Napisz program, który uwzględniając powyższy opis wyświetli wszystkie daty wypadające w podanym z klawiatury dniu tygodnia w lutym wskazanego roku.
Rok powinien być liczbą naturalną z przedziału <1500, 2005>.

Przykładowe rozwiązanie(pierwsze daty-dzień miesiąca):

- w roku 1900 – 1 pkt ( 1.02.1900 - czwartek)
- w roku 1857 – 1 pkt ( 5.02.1857 – czwartek)
- w roku 1760 – 1 pkt ( 2.02.1760 - sobota)
- w roku 1624 – 1 pkt ( 2.02.1624 - piątek)
- w roku 1582 – 1 pkt ( 5.02.1582 - poniedziałek)
- w roku 1500 – 1 pkt ( 2.02.1500 - niedziela)
#include <iostream>
using namespace std;
int tyg(string n)
{int k;
 if (n=="pon")k=1;else
 if (n=="wt")k=2;else
 if (n=="sr")k=3;else
 if (n=="czw")k=4;else
 if (n=="piat")k=5;else
 if (n=="sob")k=6;else
 if (n=="nied")k=7;else
 k=8;
 return k;
}


int main()
{ pocz:
 string a;
 cout<<"podaj dz. tygodnia:";   
 cin>>a;
 int t,x,k;                                                                     //dzien twój, dzien pomocniczy, przest.
 t=tyg(a);                                                                      //dzien w liczbie
 if (t==8) {cout<<"\nZle podales dzien tygoodznia\n"; goto pocz;};   
 int rok;
 cout<<"podaj rok:";  
 cin>>rok;
 if (rok<1500 || rok>2005) {cout<<"\nZle podales rok\n"; goto pocz;};
 //2 mozliwosc = 2 różne kalendarze            //246 dni / 109 dni do lutego
 if (rok<1583)
    {
     x=4;                                                                       // 4 - czwartek 
     for(int i=0 ; i!=245 ; ++i)
      {
       --x;
       if (x==0) x=7;                                                           //zmiana tygodznia
      }
     if (rok<1582)
       {
        for(int i=1582 ; i!=rok ; --i)
         {
          if (i-1%4 == 0) k=1; else k=0;                                        //czy rok jest przestepny
//odejmowanie do lutego**************************************
          if (k==0)                                         //
            {                                               //
             for(int j=0 ; j!=365 ; ++j)                    //
              {                                             //
               --x;                                         //
               if (x==0) x=7;                               //                  //zmiana tygodznia
              }                                             //
            }                                               //
          else                                              //
            {                                               //
             for(int j=0 ; j!=366 ; ++j)                    //
              {                                             //
               --x;                                         //
               if (x==0) x=7;                               //                  //zmiana tygodznia
              }                                             //
            }                                               //
//odejmowanie do lutego**************************************       
         }  
       }
      if (rok%4 == 0) k=1; else k=0; 
        if(k==0)
           {
            for (int d=1; d<=28 ; ++d) 
                {
                 if (x==8) x=1;
                 if (x==t) cout<<d<<"\n";
                 x++;
                }
           }           
        else
            {
             for (int d=1; d<=29 ; ++d)
                 {
                  if (x==8) x=1;
                  if (x==t) cout<<d<<"\n";
                  x++;
                 }
            }
        }
// Dla naszych lat:D............................................................
     else
     {
     x=5; 
     for(int i=0 ; i!=109 ; ++i)
      {
       ++x;
       if (x==8) x=1;                                                           //zmiana tygodznia
      }
     if (rok>1584)
       {
        for(int i=1584 ; i!=rok ; ++i)
         {
          if (i%4 == 0 && !((i%100==0) && (i%400!=0))) k=1; else k=0;           //czy rok jest przestepny
//dodawanie do lutego****************************************
          if (k==0)                                         //
            {                                               //
             for(int j=0 ; j!=365 ; ++j)                    //
              {                                             //
               ++x;                                         //
               if (x==8) x=1;                               //                  //zmiana tygodznia
              }                                             //
            }                                               //
          else                                              //
            {                                               //
             for(int j=0 ; j!=366 ; ++j)                    //
              {                                             //
               ++x;                                         //
               if (x==8) x=1;                               //                  //zmiana tygodznia
              }                                             //
            }                                               //
//dodawanie do lutego****************************************       
         }  
       }
      if (rok%4 == 0 && !((rok%100==0) && (rok%400!=0))) k=1; else k=0;
        if(k==0)
           {for (int d=1; d<=28 ; ++d) 
                {
                 if (x==8) x=1;
                 if (x==t) cout<<d<<"\n";
                 x++;
                }
           }
        else
            {for (int d=1; d<=29 ; ++d)
                 {
                  if (x==8) x=1;
                  if (x==t) cout<<d<<"\n";
                  x++;
                 }
            }            
    }
 system("pause");
}

Przeszukałem program wielokrotnie i próbowałem różne zmiany ale nic nie wyszło.
Z góry dzięki za pomoc

0
  1. Naucz się formatowac kod
  2. Zapomij o czymś takim jak goto
  3. Przepisz ten program bez użycia goto
  4. Pomyśl nad tym zadaniem z kartką papieru zanim zaczniesz kodzić...
0
Shalom napisał(a)
  1. Zapomij o czymś takim jak goto
    A jakiś racjonalny powód, dlaczego ma zapomnieć o goto? Ktoś tu chyba się dał omamić tym, którzy wołają że to przez goto jest świńska grypa... O nie, goto samo w sobie nie jest złe, złe jest jego nadużywanie... Jak w kodzie wyżej - spokojnie wystarczy pętla.
0

Fanael:

Co do goto, to ludzie mają rację ,aby tego unikać.
1)Debugowanie programu instrukcjami goto jest trudniejsze ( większe projekty)
2) Zaburza koncepcje programowania strukturalnego
3) instrukcja goto jest kłopotliwa do wykonania przez procesor ( wolna )
4) zasze da się uniknąć goto
5) Strzelenie w kodzie goto wymusza dodania etykiety , co zaśmieca kod

PS> 1)To tylko moje zdanie :)
2) Na Polibudzie zawsze mi powtarzali ,że goto jest "fuj"

PZDR</b>

0

Ja znam tylko jedno miejsce, gdzie użycie goto jest bardziej czytelniejsze niż inne równoważne konstrukcje: wychodzenie z wielokrotnie zagnieżdżonych pętli.

0

a widzisz, w liecum widać uczyli go używać goto :>

0

@rnd,
o jak dobrze mówisz :> raz na te dobrych parę lat jak programuje miałem taki przypadek (6 czy 7 zagnieżdżeń), sterowanie zwijaniami i rozwijaniem bloków za pomocą zmiennych zmiennych to byłby wtedy masochizmem, goto załatwiało wtedy ładnie sprawę
i to było jedyne użycie goto w moim życiu, oby ostatnie :P

ale generalnie goto to zło jest :P i już

0
aro napisał(a)

Co do goto, to ludzie mają rację ,aby tego unikać.
Tak, nawet to potwierdziłem -

Fanael napisał(a)

złe jest jego [goto] nadużywanie

aro napisał(a)

instrukcja goto jest kłopotliwa do wykonania przez procesor ( wolna )
No co ty, to jest jeden bezwarunkowy skok. Jedna szybka (jak na skok) instrukcja. Już wolniejszy jest if (szczególnie jeśli zrobi się z tego mispredicted branch) ;).

aro napisał(a)

zasze da się uniknąć goto
Tak, to prawda, jednak kosztem szybkości i, czasem, paradoksalnie, czytelności kodu.
Nie zrozumcie mnie źle - ja nie lubię goto. Używam tylko w ostateczności, w przypadkach jak np. podany przez crayzego.

0

Są (były ?) języki, które mają if, a nie mają if .. else (np. język plików wsadowych). Nie da się w nich programować bez użycia goto.

0

ja bym pisania *.batów nie nazwał programowaniem :P

0

@programista archeolog jasne, może jeszcze o asmie wspomnisz gdzie tez korzysta sie z takich skoków? :P
Jakby użył tutaj goto przy wychodzeniu z kilku zagnieżdżeń to bym sie nie czepiał, ale robienie tego w ten sposób nie jest eleganckie.

0

Jakby się zagłebić w kod, to w każdej konstrukcji if-else, switch/case/break siedzi gdzieś maszynowy odpowiednik goto w postaci jmp.
Prosty if:

if(a==mem)
  mem=5;
else
  mem=8;

da nam mniej wiecej:

  cmp eax,[mem]
  jne diff
  mov [mem],5;
  jmp exit_if   //harmful goto ;-)
diff:
  mov [mem],8
exit_if:

Goto nie jest samo w sobie złe - de facto każdy kompilator niejawnie 'używa' go nagminnie- wiec nie widzę powodu, dla którego w swoim kodzie ja nie miałbym go używać. Oczywiście co innego kiedy nad kodem pracuje team - wtedy zazwyczaj guidelines-y to regulują.

Poza tym, wiekszość, a może i wszystkie niebezpieczne zachowania goto są wyłapywane prze kompilator - mam tu na myśli np. przeskakiwanie deklaracji zmiennych lokalnych;

0

@_asd: Z tego kodu akurat kompilator mógłby zrobić cmov* (albo jakieś zabawy z set*), bez skoków ;). Na przykład z http://pastebin.4programmers.net/281 kompilator (gcc 4.3.3 , -O3, -march=athlon64) robi coś takiego: http://pastebin.4programmers.net/282

0
Fanael napisał(a)

@_asd: Z tego kodu akurat kompilator mógłby zrobić cmov* (albo jakieś zabawy z set*), bez skoków ;). Na przykład z http://pastebin.4programmers.net/281 kompilator (gcc 4.3.3 , -O3, -march=athlon64) robi coś takiego: http://pastebin.4programmers.net/282

tak może być, jeśli ustawisz architekturę CPU na odpowiednią, ale mimo wszystko conditional move'y są traktowane po macoszemu ze względu na dorzucenie ich(co prawda dosyć dawno temu) jako rozszerzenie listy x86 - gdzie przed ich użyciem powinieneś sprawdzić ich obecność w run-time przez cpuid.

A to co wygenerował gcc- ładnie, ale to tylko przykład z tym ifem z jednym przypisaniem - kilka więcej operacji w if/else i dostaniesz harmful goto ;-) (jmp) - co zapewne wiesz, bo widzę, że jesteś dobrze oblatany w temacie.

0

W sumie masz rację - ale na dobrą sprawę podanie kompilatorowi procesora >= Pentium Pro załatwia sprawę - zdaje się że ten model wprowadził conditional movy. Ale tutaj gcc zrobił set*, co zrobiłby i bez podania -march, bo te instrukcje dostępne są od 386.
Jeśli chodzi o więcej instrukcji w if/else - jasne, wiem, chciałem tylko pokazać, że czasami kompilator zrobi totalnie coś innego, jak w tym przykładzie.

0

Fajnie, ale z tego się zrobił duży offtop.

To jest typowe zadanie, najpierw przemyśleć wszystko dokładnie na kartce, porachować przemyśleć jakie wzory, a potem zaimplementować. Na końcu powinieneś mieć zdecydowanie krótszy kod, pisząc bardzo opisowo i rozwlekle 50 linijek powinno wystarczyć (strasznie to skomplikowałeś). Jak znajdę dłuższą chwilę to pokażę jak powinno to wyglądać.

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