5. díl - Céčko a Linux - Code::Blocks podruhé

C++ Linux Céčko a Linux - Code::Blocks podruhé

Minule jsme se podívali na nastavení a možnosti Code::Blocks a zkusili jsme programátorskou klasiku - Hello world. Dnes si zkusíme vytvořit jednoduchý program a naučíme se debuggovat. Na závěr ještě připojím pár tipů, které by vám mohly zpříjemnit práci. :)

Praktický příklad

Nebudeme nic komplikovat a napíšeme velmi jednoduchý program, co bude sčítat dvě hodnoty a vypíše nám výsledek. Zdrojový kód bude následující:

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

int main(void)
{
   int a = 5;
   int b = 10
   int c;

   printf("Jednoduchá sčítačka\n");
   c = a + b;
   printf("Výsledek je %i", c);

   return 0;
}

Zkusme program přeložit a spustit... Co se stane? V programu máme jednu z nejtypičtějších chyb – chybějící středník za příkazem. Kompilace skončila neúspěšně a v logu najdeme vypsané dvě chyby. První je chybějící středník, druhá nám říká, že proměnná c nebyla deklarovaná. Ve skutečnosti je to ale pouze jedna chyba – chybějící středník za deklarací b způsobil, že neproběhla deklarace c. Řádek s chybou nám Code::Blocks zvýraznil červeným čtverečkem. Pokud klikneme na další chybu (v logu), zvýrazní se ta.

Chyba v Code::Blocks

Chybu si opravíme a znovu spustíme kompilaci. Tentokrát již proběhne v pořádku. Když poté spustíme program pomocí Run, výstup bude následující:

Spuštění programu v Code::Blocks

Ukázali jsme si syntaktickou chybu. Co ale když jde o chybu sémantickou, tedy chybu v algoritmu? Naši sčítačku si trochu upravíme:

int main()
{
   int a, b, c;

   printf("Jednoduchá sčítačka\n");

   printf("Zadej číslo: ");
   scanf(" %i ", &a);

   printf("Zadej další číslo: ");
   scanf(" %i ", &a);

   c = a + b;
   printf("Výsledek je %i", c);

   return 0;
}

Program dělá to stejné s tím rozdílem, že sčítaná čísla získáme od uživatele. Napsali jsme si načítání prvního čísla a protože jsme líní, tak jsme jej pro druhé číslo jen zkopírovali a upravili. Teď to zkusíme přeložit. Vidíme sice, že v logu je warning, ale jako „správné“ programátory nás zajímají pouze chyby. Varování můžeme bez problému ignorovat. Hlavní přeci je, aby to nějak fungovalo. Překlad tedy proběhl v pořádku a my můžeme náš upravený program vyzkoušet.

Chyba

Naše první reakce bude asi ve stylu „Co to je?!?“. Dostali jsme úplně nesmyslný výsledek a přitom ten kód vypadá na pohled dobře... Uznávám, že v našem případě se dá chyba snadno najít, ale představme si program násobně složitější. To již tak jednoduché není. Když tedy narazíme na takovou chybu, jako první se podíváme do logu, jestli se nám překladač náhodou nesnaží něco sdělit.

16 - warning: ‘b’ is used uninitialized in this function [-Wuninitialized]

Na řádku 16 používáme neinicializovanou proměnnou b. Ale jak to? Podíváme se na zmíněný řádek. Najdeme v něm příkaz c = a + b. Z warningu zjistíme, že proměnnou b jsme ještě v programu nepoužili. Ale vždyť do ní přece načítáme druhé číslo, ne? Aha...

Debugging

Pokud si ulehčujete programování kopírováním již napsaného kódu a jeho úpravou, jistě se vám podobná chyba již stala. V malém programu to snadno najdeme. Tu nám navíc pomohou zapnuté direktivy -Wall a -Wextra. Díky nim jsme byli upozorněni na použití neinicializované proměnné. Ale co když bude program složitější? Nebo co když budeme proměnnou b někde v předchozí části programu používat? To už bychom varování nedostali... Co v takovém případě dělat? Jednou možností je strávit hodiny studováním kódu a hledáním chyby. Přesně to dělá mnoho začínajících programátorů, ale je to dobré pouze k získání pocitu frustrace. Existuje další, mnohem lepší možnost – debugger (ladící program, "odvšivovač").

Náš výpočet nám vrací něco neočekávaného. Nastavíme tedy na řádek s výpočtem tzv. breakpoint. Jednoduše řečeno, breakpoint je místo, ve kterém se při debuggování zastaví provádění programu. Breakpoint můžeme jednoduše přidat kliknutím na řádek (hned vedle čísla řádku) nebo pravým kliknutím a vybráním "Toggle breakpoint". Teď spustíme program v debug módu (červená šipka Debug/Continue nebo F8). Zobrazí se nám něco takového:

Breakpoint v Code::Blocks

V okně watches vidíme naše proměnné a co obsahují (hodnoty jsou při spuštění programu náhodné – typicky v nich je hodnota, kterou tam nechala aplikace, které byla paměť předtím přiřazena). Zadáme tedy hodnoty jako normálně. Program normálně běží (nechá si zadat dvě čísla) a zastaví se na řádku s breakpointem (před jeho vykonáním).

Debug

Vidíme, že v a máme 10 (i když by tam měla být hodnota 5), v b něco náhodného (mělo by tam být 10) a v c taky nějaký nesmysl (to je v pořádku – do c jsme ještě nic nezapisovali). Aby se provedl následující příkaz (c = a + b), klikneme na Next line nebo stiskneme F7. Provedl se výpočet a vidíme jasně, že správně – zde tedy chyba není. Z hodnot vstupních proměnných ale vidíme, že při jejich načítání není něco v pořádku. Debugger ukončíme (červený křížek nebo Shift+F8) a přidáme breakpointy na řádky, kde načítáme obě proměnné.

Další breakpointy

Po spuštění programu si všimneme, že se zastavil již před zadáním první proměnné. Pomocí F7 budeme tedy krokovat a sledovat, jak se nám mění hodnoty proměnných. Jen poznámka – F7 musíme stisknout, když máme označené okno Code::Blocks, ne když jsme v XTerm.

Debug podruhé

Zadali jsme 5 a do proměnné a se uložila 5. Tento příkaz je tedy v pořádku. Všimněme si malé žluté šipečky vedle následujícího řádku – tato nám ukazuje, který řádek se po stisknutí F7 vykoná jako další.

Debuggování – První krok

Proběhlo zadání druhé proměnné. Zadali jsme 10, v b by tedy mělo být 10. Místo toho se ale hodnota 10 objevila v proměnné a. Již tedy víme, kde je problém a chybu můžeme opravit.

Krok 2

Zde je výsledný, funkční kód:

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

int main()
{
   int a, b, c;

   printf("Jednoduchá sčítačka\n");

   printf("Zadej číslo: ");
   scanf(" %i ", &a);

   printf("Zadej další číslo: ");
   scanf(" %i ", &b);

   c = a + b;
   printf("Výsledek je %i", c);

   return 0;
}

Možná vám to teď připadá zbytečné a složité. Ale ve větších a komplikovanějších aplikací se obyčejně programátor bez debuggování neobejde. Toto byl pouze takový úvod a základ a někdy příště se na tuto problematiku podíváme hlouběji.

Pár tipů na závěr

Ještě zmíním pár užitečných maličkostí, co by vám mohly usnadnit život :)

Tip 1 - include soubory

Přemýšleli jste někdy, jak je napsaná nějaká knihovní funkce, ale nevěděli, kde se podívat? Nebo máte nějaký větší projekt, který má spoustu hlavičkových souborů, ale není realizovaný v Code::Blocks (a nechce se vám ho vytvářet)? Jednoduché řešení je kliknout pravým tlačítkem na řádek s #include a "Open #include file" :)

Open include

Tip 2 - záložky

Pokud editujete delší kód, mohou se vám hodit záložky - jednoduše označíte řádek (Ctrl+B nebo pravý klik Bookmarks->Toggle bookmark). Mezi více záložkami se pak můžete pohybovat pomocí Alt+PgUp nebo PgDn.

Tip 3 - Poznámky a TODO

Komentovat, komentovat a komentovat. To je základ. Pokud nevěříte, uvěříte, až budete pracovat na větším projektů a komentáře nebudou nebo jich bude málo... ;)

U dlouhých souborů s množstvím komentářů se ale můžeme setkat s tím, že to není příliš přehledné. Určitého zpřehlednění můžeme dosáhnout například pomocí Todo listu (seznam úkolů). Novou položku můžeme přidat například pravým kliknutím na řádek a "Add todo item". Zobrazí se nám následující okno:

Todo item

Zde můžeme napsat samotný text úkolu, přidat uživatele, který poznámku přidal (nebo pro kterého je určena - záleží na domluvě), nastavit prioritu a případně i změnit typ položky a její zápis. Na výběr jsou TODO, FIXME a NOTE. Názvy myslím mluví za sebe.. :)

Dále máme na výběr několik druhů komentáře (různé nástroje pracují s různým zápisem). Můžeme si také nechat připsat dnešní datum. Také nám nic nebrání napsat položku přímo a vyhnout se tak celému klikání.

// TODO (david#1#3.3.2015): Úplně všechno

Seznam všech takovýchto položek si můžeme zobrazit kliknutím na View->Todo list. Objeví se nám okno, které si můžeme někam připnout a kde můžeme různě filtrovat naše poznámky - jestli se mají zobrazit jen ty v aktuálně vybraném souboru, projektu nebo ve všech otevřených souborech. Dále můžeme vyfiltrovat uživatele a typy. Jak můžeme vidět, položky se nám řadí podle priority (9 je nejvyšší). Dvojklikem na položku se přesuneme přímo na místo, kde se nachází.

Todo list

Užitečné, ne? Ještě bych zmínil, že můžeme také přidat poznámku přímo k projektu - Project->Notes.

Tip 4 - "zakomentování" kódu

C nepovoluje vnořené komentáře, takže k zakomentování "otravného" kousku kódu, například když debuggujeme, nemůžeme použít blokový komentář. Jedno řešení je použít podmíněný překlad #if, ale to může jít na úkor přehlednosti.

Code::Blocks nám tohle velmi usnadňuje - stačí označit blok a stisknout Ctrl+Alt+C (respektive X pro odkomentování).

Drobnosti na závěr

Kliknutím na proměnnou a stisknutím Alt+N vyvoláte okno, kde můžete snadno přejmenovat všechny její výskyty.

Když jste vedle závorky a stisknete Ctrl+Shift+B, skočíte na druhou závorku, která k ní patří. Pomocí Ctrl+, můžete přepínat otevřené soubory. Ctrl+Enter posune kurzor na konec řádku.

Tak, to bude pro dnešek asi vše... :) Někdy příště se podíváme na Code::Blocks trochu blíže. Příští díl bude o filtrech - aplikacích, jejichž jediný vstup od uživatele je při jejich spuštění a dále již běží autonomně.


 

  Aktivity (1)

Článek pro vás napsal David Novák
Avatar
Autor v současné době studuje FIT VUT Brno a zajímá se především o nízkoúrovňové programování (C/C++, ASM) a návrh hardwaru (VHDL). Je zde také členem výzkumného týmu ANT@FIT (Accelerated Network Technologies).

Jak se ti líbí článek?
Celkem (1 hlasů) :
55555


 


Miniatura
Předchozí článek
Céčko a Linux - Code::Blocks
Miniatura
Všechny články v sekci
Programování v jazyce C v Linuxu
Miniatura
Následující článek
Céčko a Linux - Filtry

 

 

Komentáře

Avatar
Libor Šimo (libcosenior):

Veľmi pekne napísané. Len doplním, že všetky tieto vychytávky sa dajú rovnako použiť aj v Code:Blocks na platforme windows.

Odpovědět  +1 4.3.2015 15:24
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
David Novák
Tým ITnetwork
Avatar
Odpovídá na Libor Šimo (libcosenior)
David Novák:

A taky na MacOS X.. ;) Code::Blocks je dobře multiplatformní.

Odpovědět 4.3.2015 15:27
Chyba je mezi klávesnicí a židlí.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.