1 / 6
Feb 2017

Czasami otwiera się mi w kieszeni, ale możesz to potraktować, jako szwajcarski scyzoryk, uniwersalny wytrych na różne bolączki:

1. Testowanie poprawności danych wejściowych.

Odp na pytanie w wątku: http://discuss.spoj.com/t/1211-niekolejne-niekolej/11447/17
Dlaczego to jest złe:?

if(n<0 || n>1000000)
    exit(0);

To jest dodatkowe miejsce ewentualnego błędu i pomagający, muszą dodatkowo sprawdzić to miejsce, czy tu faktycznie nie ma błędu. Chcesz pomóc pomagającemu? Więc pomóż i gdy wysyłasz na forum, z prośbą o pomoc, usuń to. Po co to jest? Ano starasz się napisać idiotoodporny program, ale ani autor zadania ani sędzia do nich raczej nie należą, a to twój program w tym momencie może się tak zachować. Dlaczego? Bo gdyby jednak autor się pomylił ździebko, to twój program "obrazi sie", noi ok, ale nic "nie mówiąc" zakończy na tym swoją całą działalność. A przecież, gdy ma to być program idiotoodporny, to może warto coś zakomunikować, jeszcze raz poprosić [człowieka] o wprowadzenie danych, człowieka bo na pewno nie sędzigo na SPOJ'u. I na pewno [za]naprawdę nie można zakończyć cicho i jak by się nic nie stało - exit(0). Lepiej exit(-1), exit(1001) czy jakakolwiek inna wartość różna od zera i nie wykorzystywana w twojej obsłudze błędóœ.
Spróbuj nawet teraz tak poprawić swój kod i dodatkowo popsuć warunek, tzn, np:

 if(n<0 || n>100)
        exit(100);

i zobacz co się stanie.

  • created

    Feb '17
  • last reply

    Mar '17
  • 5

    replies

  • 1.7k

    views

  • 2

    users

  • 2

    likes

  • 3

    links

pinned Feb 21, '17

Dobrze prawisz. W językach C/C++ można też skorzystać z makra assert (z plik nagłówkowego: assert.h/cassert odpowiednio dla C/C++) np: assert(0 <= n && n <= 100); Jeżeli warunek przekazany do makra nie jest spełniony to program zostanie zakończony błędem wykonania, konkretnie sygnałem SIGABRT. W ten sposób jest między innymi testowana poprawność plików testowych przygotowywanych na rundy AlgoLigi.

unpinned Feb 24, '17

pinned Feb 24, '17

8 days later

Masz [dużo]/trochę racji. Ale gdy mówimy o zwykłych śmiertelnikach, to takie nadmiarow sprawdzanie, w ich wykonaniu może przynieść i najczęściej przynosi tylko nieszczęście. Co do AlgoLigi [a co tam słychać?] assert nie jest wcale takim dobrym lekarstwem na całe zło. Ma kilka wad.

  1. Nie sprawdza specyfikacji opisanej w zadaniu z tym co do asertu wstawi autor.
  2. Przerywa brutalnie program, a przecież ogólnie wiadomo, że to bardzo niezdrowe.
  3. Specyfikacja musi się zgadzać w trzech miejscach - w tekście zadania, generatorze testów i w rozwiązaniu wzorcowym. Niestety, to nie assert, ale autor musi to zgrać i zsynchronizować, więc może mu to tylko przeszkadzać, a nie ułatwiać zadania.
  4. Gdy generuję testy, to ustawiam "ręcznie" generator i assert może mi tylko przeszkadzać w generowaniu - przerwie generowanie, a ja wolę pominąć błędny test i "jechać" dalej.
  5. Do niektórych zadań asser trudno wymyślić, bo nie są aż tak ważne dane wejściowe, ale wynik, lub środek.
    Przykłady:
    zadanie: dwumiany. wejście 1000 500 spełnia warunki wejścia. 1000 3 i 1000 997 też, ale jeżeli autor nie wie o co biega... to sam assert nie pomoże.
    zadanie: alfabet morsa. Jeżeli autor sięgnie po błędne źródło, a rozwiązywacz nie skopiuje kodów z treści zadania to i sam assert tu nie pomoże. Oczywiście autor mógł intencjonalnie zamienić kody dwu liter.
    zadanie: Warunek w tablicy - komentarz pod zadaniem.
    zadanie: szyfrogram - zbyt dokładne sprawdzanie specyfikacji, powoduje WA;-), a tu autor także mógł w specyfikacji pominąć [intencjonalnie] jakiś kodzik - w końcu to przecież sztuka dekryptarzu.

Konkluzja: nie sprawdzajcie autorów zadań, oni najczęściej się nie mylą, ale nawet jak "lekko" się pomylą, to lepiej napisać program odporny na takie drobne "odchyłki" a nie program, który w takim wypadku nic nie robi lub się "wyłamuje" z sigabortem, a rozwiązywacz, zobaczy tylko to i nic więcej.

PS
W zadaniu warunek w tablicy, rozwiązywacz mógł zapewne napisać:
if (n < 1000) {
int* tab = new int [n];
lub
vector tab(n); //więc niezależnie czy n == 10 czy 100001 to działa poprawnie
.....
}
else { //<-- tego pewnie już nie zrobił
// nic nie robię <-- to tak
......
}

Suggested Topics

Want to read more? Browse other topics in Tutoriale, poradniki or view latest topics.