Monthly archive for August, 2007

Pętle w Pythonie

2007-08-12 12:21

Konstrukcje iteracyjne w C++ mają całkiem spore możliwości. Dotyczy to zwłaszcza instrukcji for, która jest o wiele elastyczniejsza niż w innych językach. Mimo to w dziedzinie pętli C++ ma pewne niedostatki.
Zwykle najbardziej brakuje nam sposobu na przerwanie zagnieżdżonych pętli. W C# czy Javie jest to możliwe za pomocą specjalnych wariantów instrukcji break. Lecz w C++ trzeba to robić albo z wykorzystaniem wyklętej (niezbyt zresztą słusznie) instrukcji goto, albo poprzez zastosowanie zmiennych logicznych. Istnieje też sposób z wykorzystaniem wyjątków, ale można go traktować chyba tylko jako ciekawostkę.

Jest jeszcze jedno usprawnienie mechanizmu pętli, którego C++ nie posiada, ale dla odmiany ten brak nie jest aż tak dolegliwy. Chodzi tu o klauzulę else występującą po pętli. Tę nietypową konstrukcję widziałem jak dotąd tylko w języku Python; wygląda ona następująco:

  1. # sprawdzenie, czy liczba x jest pierwsza
  2. for i in range(2, x):
  3.    if x % i == 0:
  4.       print x, " dzieli się przez ", i
  5.       break
  6. else:
  7.    print x, " jest liczbą pierwszą"

Fraza else odnosi się tutaj do pętli, a nie do instrukcji if. Jest ona wykonywana wtedy, gdy pętla kończy się normalnie, tzn. nie następuje wykonanie instrukcji break. Jak widać oznacza to zwykle, że jakiś rodzaj przeszukiwania dotarł do końca wyznaczonego zakresu bez znalezienia pasującego elementu (w tym przypadku – dzielnika).

Większość języków nie posiada tej dziwnej konstrukcji, bo najczęściej można się bez niej obejść. Przeszukiwanie dokonywane w pętli jest bowiem często zamykane w funkcję, którą można zapisać bez użycia break:
bool IsPrime(unsigned x)
{
for (unsigned i = 2; i < x; ++i) if (x % i == 0) return false; return true; }[/cpp] Pewne “nowoczesne” konstrukcje w nowszych językach programowania nie są więc zawsze lekarstwem na programistyczne bolączki. Czasami są zwykłym zawracaniem głowy.

Tags: ,
Author: Xion, posted under Programming » 3 comments

Rozsupływanie grafów

2007-08-11 13:36

Zawsze lubiłem teorię grafów. Niestety, ta sympatia jest w dużym stopniu nieodwzajemniona, gdyż z obejmującej tę teorię matematyki dyskretnej nie miałem zbyt dobrych ocen :) Mimo to chciałbym dzisiaj polecić pewną grę ściśle związaną z tą dziedziną.

Chodzi o Planarity. Polega ona na tym, by ułożyć wierzchołki danego grafu planarnego tak, by żadne jego krawędzie się nie przecinały. Dla małych grafów jest to oczywiście proste, lecz gdy liczba wierzchołków przekracza kilkanaście, na rysunku zaczyna być już gęsto…

Screen z etapu 3 gry Planarity Screen z etapu 5 gry Planarity

Na forum Warsztatu pojawił się wątek z pytaniem o jakiś systematyczny sposób na odpowiednie ułożenie wierzchołków w tej grze. Z faktu, że o tej pory nie znaleziono tam żadnego pewnego rozwiązania wynika, że to całkiem interesująca gra ;)

Tags: ,
Author: Xion, posted under Games » Comments Off on Rozsupływanie grafów

O pożytkach z komentarzy

2007-08-10 13:35

Kiedy komukolwiek pokazuję fragment napisanego przez siebie kodu, reakcja jest zawsze dość podobna. Można ją streścić jako pytanie: “A dlaczego tu tak zielono?” :)

Faktycznie, dość intensywnie używam komentarzy. Rzeczywiście, nadużywam też stosowania przerw w postaci pustych wierszy. Zgadza się, że dwa wiersze “normalnego” kodu odpowiadają przeciętnie trzem wierszom napisanym przez mnie. Tak, to wszystko prawda. Co mam na swoje usprawiedliwienie?
Otóż… nic :P Wręcz przeciwnie, taki sposób pisania uważam za bardzo pożyteczny, a powodują mną takie oto motywy:


    Logo programu doxygen, jednego z darmowych systemów generujących dokumentację techniczną z kodu
  • Pierwszy jest dość oczywisty: duża ilość komentarzy ułatwia zrozumienie kodu. Ponadto jeżeli nie są to komentarze pisane ot, tak sobie, lecz zgodnie z pewnym powszechnym standardem, mogą zostać wykorzystane do stworzenia dokumentacji technicznej. Na temat takiej dokumentacji można oczywiście powiedzieć mnóstwo złych rzeczy – na czele z jej małą przydatnością dla samego programisty, który dany kod tworzy. Pozwala ona jednak przynajmniej spojrzeć całościowo na daną klasę/moduł/przestrzeń nazw/bibliotekę/program, zwłaszcza jeśli używany program potrafi też rysować ładne schematy :)
  • Poza tym ktoś ładnie powiedział, że komentarze są przydatne, ponieważ są zielone ;] Zdecydowanie lepiej patrzy się na kawałek kodu poprzecinany adnotacjami czy pustymi liniami niż na jednolitą szpaltę wysokości drapacza chmur. Stosowanie separatorów w rodzaju /********/ czy nagłówków opisujących pliki na pewno polepsza czytelność kodu.
    Kiedyś na Warsztacie założyłem sondę na temat zalet komentarzy i wolą większości ten argument został uznany za najważniejszy.
  • Po trzecie kod z komentarzami jest zwyczajnie ładniejszy. Naturalnie nie zdadzą się one na wiele, jeżeli ktoś stosuje nazwy w stylu function1, a klawisza Tab używa tylko w połączeniu z Altem :) Szkoda, że tego rodzaju kod widzi się stanowczo za często ;P
  • I wreszcie jedna sprawa dotycząca nie samych komentarza, lecz ich pisania. Kiedy programuje się z zamiłowania, nierzadko ma się “natchnienie”, które chciałoby się od razu przełożyć na kod. Jakie są tego skutki, nietrudno się domyślić, bo przecież co nagle to po diable ;) Jeżeli jednak wcześniej poświęci się chociaż chwilę na napisanie komentarza do powstającej funkcji/klasy/itp. to skutek jest zwykle lepszy.

Tak więc, Wysoki Sądzie, z powodu swojego rozwlekłego stylu kodowania nie czuję najmniejszych wyrzutów sumienia i nie postanawiam nawet minimalnej poprawy ;P Co więcej, nie będę się krępował przed propagowaniem swoich poglądów na ten temat każdemu, kto będzie miał (nie)przyjemność oglądać napisany przeze mnie kod :)

Tags:
Author: Xion, posted under Programming » 3 comments

Nadmiar interfejsu

2007-08-09 16:40

Projektując klasy i kontrolki systemu GUI, wzoruję się na kilku istniejących rozwiązaniach. Większość wzorców czerpię jednak z Windows Forms, części platformy .NET. Tym, co ostatnio zwróciło w niej moją uwagę, to fakt, że wiele czynności można w niej wykonać na kilka sposób. Mówiąc ściślej, klasy wchodzące w skład WF posiadają często więcej niż jedną składową służącą osiągnięciu tego samego celu.

Przykład? Proszę bardzo. Do zmiany położenia i wymiarów kontrolki wystarczą dokładnie cztery właściwości. Mogą to być: Left (pozycja lewej krawędzi kontrolki), Top (górnej krawędzi), Width i Height. Tyle w zupełności wystarczy. Klasa Windows.Forms.Control ma też jednak inne:

  • Right – pozycja prawej krawędzi
  • Bottom – dolnej krawędzi
  • Location – pozycja lewego górnego rogu
  • Size – wymiary kontrolki
  • Bounds – prostokąt otaczający kontrolkę

Wszystkie je można oczywiście uzyskać z tych czterech, które wymieniłem na początku. Istnieje też rzecz jasna mnóstwo innych kombinacji z innymi właściwościami “pierwotnymi” i “pochodnymi”.

Można mieć jednak wątpliwości, czy istnienie różnych dróg dotarcia do podobnych danych jest konieczne i właściwe. Przy tak bogatym interfejsie (inny przykład: metoda Graphics.DrawImage() ma aż 30 (!) przeciążonych wersji) można bardzo długo zastanawiać się nad tym, którego sposobu mamy użyć w konkretnym przypadku.
To prawda, że interfejs zbyt ubogi jest zwykle o wiele większym problemem. Uważam jednak, że w programowaniu brzytwa Ockhama ma zastosowanie i że dróg prowadzących do tego samego celu nie należy mnożyć ponad potrzebę.

Tags:
Author: Xion, posted under Programming » 1 comment

Minesweeper: The Movie

2007-08-08 22:17

Wszyscy znają tę grę. Jedna z najpopularniejszych, najbardziej rozpowszechnionych i najlepszych produkcji w dziejach komputerowej rozgrywki. Mają prawie każdy i praktycznie każdy w nią grał. O jakiej grze mowa? O windowsowym Saperze, naturalnie :)

  

Dlatego wszystkich fanów z pewnością ucieszy fakt, że oto szykuje się ekranizacja tej niezwykłej produkcji. A już teraz można sobie obejrzeć zapowiadający trailer:

Trailer Minesweeper: The Movie

A teraz nieco poważniej… Większość tzw. śmiesznych filmików jest w rzeczywistości mało zabawna, ale trafiają się też perełki. O tym mogę śmiało powiedzieć, że mnie rozbroił :)

Tags:
Author: Xion, posted under Games » 4 comments

“Nie działa! Jejku, co ja zrobię?!”

2007-08-08 16:10

Na forum Warsztatu zdarzają się różne problemy. Część z nich dotyczy nieznanych przyczyn błędnego funkcjonowania programu lub jakiegoś kawałka kodu. Z pewnością nie jest tak, że takie wątki są z góry uznawane za niepożądane. To, co o tym decyduje, to przede wszystkim treść, opisowość i precyzja.

A z tym bywa kiepsko. Bardziej doświadczeni programiści wiedzą oczywiście, że do wyeliminowania błędu potrzebna jest dokładna wiedza, w jakich okolicznościach on występuje. A już zupełnie niezbędne jest określenie, co tak naprawdę się dzieje: błędny rezultat funkcji, wyjątek czasu wykonania, zawieszenie się programu, bluescreen, spalenie płyty głównej (no, może przesadzam ;)) ?…
Nierzadko jednak za cały opis ma wystarczać mgliste stwierdzenie, że coś nie działa. “Serio?” – chce się odpowiedzieć – “więc idź i to napraw ;P”. Przy tak skąpo opisanych objawach trudno przecież oczekiwać, żeby ktokolwiek mógł wywróżyć, co tak naprawdę jest ich przyczyną.

Czasem ta lakoniczność jest spowodowana tym, że dana osoba traktuje fakt niedziałania napisanego przez siebie kodu wręcz jako życiowe niepowodzenie lub – co gorsza – osobistą zniewagę. A gdy w grę wchodzą takie emocje, z zebraniem potrzebnych informacji może być kłopot…
Próbuję się tu wczuć w taką postawę, ale prawdę mówiąc zupełnie jej nie rozumiem. Może każdy na początku przygody z programowaniem reaguje podobnie, a ja zdążyłem już po prostu zapomnieć, że kiedyś mi się to zdarzało? A może jednak zależy to od charakteru i sprawia, że osoby biorące wszelkie niepowodzenia (w tym przypadku błędy) za bardzo do siebie mają trudności w zostaniu dobrymi programistami?

I czy faktycznie podejście emocjonalne tak bardzo przeszkadza?… Nie wiem, jak w jest w istocie, lecz wiem jedno: ostatnio zdecydowanie za często zajmuję się dziwnymi problemami :)

Tags: ,
Author: Xion, posted under Programming, Thoughts » 6 comments

Liczenie stałych

2007-08-07 11:59

Dzisiaj pokażę pewną sztuczkę, mogącą nieco ułatwić życie programiście, który – jak wiadomo – zawsze ma za dużo pracy. Nie jest ona zbyt odkrywcza ani pomysłowa, ale ponieważ wielokrotnie zdarzyło mi się z niej korzystać (ostatni raz całkiem niedawno), sądzę że zasługuje na wzmiankę.

Sprawa dotyczy typów wyliczeniowych w C++ – czyli tworów, które pojawiają się często w większości programów. W moim ostatnim przypadku był to prosty typ definiujący wachlarz kolorów używanych w różnych miejscach systemu GUI:

  1. enum GUI_COLOR
  2. {
  3.     // kolory pasków tytułu okien
  4.     GC_ACTIVE_CAPTION, GC_INACTIVE_CAPTION,
  5.     // kolory kontrolek
  6.     GC_CONTROL_NORMAL, GC_CONTROL_HOVER,
  7.     // kolor tła okna
  8.     GC_WINDOW
  9. };

Jest to podobny zestaw do tego, jaki można zobaczyć w Windows w oknie Właściwości: Ekran, na zakładce Wygląd. Naturalnie jest on dość okrojony, jako że nie potrzebujemy tutaj niczego aż tak skomplikowanego. Nie jest jednak wykluczone, że kiedyś się rozrośnie…
Każdemu z tych “systemowych” kolorów trzeba teraz przyporządkować kolor rzeczywisty – żeby wiedzieć, jak narysować konkretne kontrolki. Można zdefiniować do tego sporo zmiennych w stylu clActiveCaptionColor czy clControlNormalColor, ale lepszym rozwiązaniem jest tablica:

  1. COLOR aColors[???];

Problem w tym, że trzeba podać jej rozmiar. Można oczywiście wpisać tam na sztywno 5, ale doskonale wiadomo, jakie są skutki stosowania w kodzie “magicznych liczb”. Można zdefiniować sobie stałą, lecz wtedy też będziemy musieli ręcznie modyfikować jej wartość, jeżeli liczba kolorów się zmieni.

Potrzebujemy więc sposobu na automatyczne określenie liczby stałych zdefiniowanych w typie wyliczeniowym. W językach dysponujących dynamicznymi informacjami o typie – jak C# czy Java – byłoby to zapewne proste, lecz tutaj nie mamy tego komfortu. Zamiast tego możemy sobie jednak poradzić inaczej – dodając do typu wyliczeniowego kolejną stałą:

  1. enum GUI_COLOR
  2. {
  3.    /* ... */
  4.  
  5.    // na końcu
  6.    GC_COUNT
  7. };

Kompilator nada jej wartość o jeden większą od poprzedniej. Ponieważ pierwszej stałej przypisał zero, GC_COUNT będzie odpowiadało liczbie 5 i to będzie właśnie liczba użytecznych stałych w typie wyliczeniowym. Teraz można już zadeklarować potrzebną tablicę:

  1. COLOR aColors[GC_COUNT];

Podobnie można zrobić dla każdego typu wyliczeniowego. Najlepiej działa to wtedy, gdy kompilator sam numeruje jego stałe. Jeżeli sami to robimy, to oczywiście trik nadal będzie działał (zmienna *_COUNT będzie zawsze miała największa wartość). W tablicy pojawią się jednak niewykorzystane elementy i te dziury ewentualnie trzeba będzie omijać.

Tags: , ,
Author: Xion, posted under Programming » Comments Off on Liczenie stałych
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.