Předchozí [Funkce v C]

Dnes si naprogramujeme jednoduchou kalkulačku. Dřív, než se podíváte na řešení, vyzkoušejte si implementaci sami. Opravdu, věřte mi. Jenom čtením kódu se programovat nenaučíte, je potřeba samostatně zkoušet, chybovat a znovu zkoušet.

Upozorňuju, že se moje řešení může (a pravděpodobně bude) od vašeho lišit! Každý má jiné nápady, jiné myšlenkové pochody. V normálním světě, tam venku, by body, kde se názory rozcházejí, byly předmětem diskuze, případně by ideálně byly rovnou součástí specifikace (např. po poradě se zákazníkem). Pokud vaše řešení dělá to, co má, je to v pořádku. Pokud se budete držet zásady, že každá funkce má plnit jenom jednu úlohu, rozdělíte kód, budete ho udržovat hezky čitelný, o to lépe.

Začneme tím, že si vytvoříme základní kostru. Každý program potřebuje main-funkci, dodatečně k této hlavní funkci se zamyslíme i nad tím, jaké další funkcionality by naše kalkulačka měla mít.

Nejdříve se zamyslíme nad tím, co naše kalkulačka musí umět a jak to budeme testovat. Přičemž testování bude zatím nejjednodušší pomocí printf v mainu. A naše kalkulačka by měla umět sčítat, odečítat, násobit a dělit.

První základní kostra by mohla vypadat následovně:
#include <stdio.h>

int scitani(int a, int b)
{
    return a + b;
}

int odecitani(int a, int b)
{
    return 0;
}

int nasobeni(int a, int b)
{
    return 0;
}

// TODO: deleni

int main(void)
{
    printf("Test: %d\n", scitani(5, 3));
    return 0;
} 
Předpokládejme, že naše kalkulačka zatím umí počítat jenom s celými čísly. Implementace sčítání, odečítání a násobení by tedy neměla být těžká. Sčítání můžu otestovat v mainu a výsledek si nechat vytisknout na konzoli. Zkuste si sami doplnit kód pro odečítání a násobení (momentálně tyto dvě funkce vrací pouze hodnotu 0).


Podařilo se vám naimplementovat odečítání a násobení? Vyzkoušeli jste, jestli funkce vrací požadovanou hodnotu? Pokud ano, tak se můžeme vrhnout na dělení.

Dělení:
#include <stdio.h>

int scitani(int a, int b)
{
    return a + b;
}

int odecitani(int a, int b)
{
    return 0;
}

int nasobeni(int a, int b)
{
    return 0;
}

double deleni(int a, int b)
{
    if (b == 0)
    {
        printf("Chyba: deleni nulou!\n");
        return -1;
    }

    return (double) a / b;
}

int main(void)
{
    printf("Test: %f\n", deleni(5, 3));
    return 0;
} 
Nezapomeňte u dělení dát návratnou hodnotu double - pokud byste dali int, pak by se vždy vracelo pouze celé číslo a tudíž (většinou) nesprávný výsledek. A také je třeba dopsat u return double, protože int děleno int je vždy int a tedy výpočet je celé číslo, i přesto, že je následně vráceno na volajícího ve formě desetinného čísla (opět - zkuste si (double) vynechat a mrkněte, co se stane). V případě, že je dělitel 0, funkce má vytisknout na konzoli chybovou hlášku. Vrátit by se mohlo jakékoli číslo, např. -1 (nebo i 1, 2 atd., prostě jiné než 0). Mezi programátory se ustálilo, že jakékoli jiné číslo než 0 značí chybu. Např. zde je hezky popsáno, co znamená návratové hodnota main. Také si ohlídejte format specifier u printf v mainu. Tentokrát je třeba %f, protože jako argument máme desetinné číslo.


Hurá, pokud jste se dostali až sem, tak už váš program počítá! Ale nezůstaneme jenom u toho. Zatím jsme čísla předávali v kódu. Zkuste si o čísla říct uživateli (připomínám kapitolu o scanf).

User input:
int main(void)
{
    int a, b;

    printf("Prosim zadejte 2 cisla (oddelena mezerou): ");
    scanf("%d %d", &a, &b);

    printf("Test: %f\n", deleni(a, b));
    return 0;
} 
Ostatní funkce zůstávají stejné, momentálně pracujeme jenom v main. Nejprve je potřeba si někde určit 2 proměnné, ve kterých následně uložíme čísla, která nám dodá uživatel. A načtení textu dosáhneme pomocí scanf, jak jsme viděli v předposlední kapitole.


Skvělé, uživatel dokáže určit, se kterými čísly bude chtít počítat. Už zbývá jenom nechat ho rozhodnout, kterou operaci by rád provedl a následně pomocí větvení provést vybranou početní operaci. Zkuste si příklad dořešit nejdříve sami.

Výsledný kód by mohl vypadat takto:
#include <stdio.h>

int scitani(int a, int b)
{
    return a + b;
}

int odecitani(int a, int b)
{
    return a - b;
}

int nasobeni(int a, int b)
{
    return a * b;
}

double deleni(int a, int b)
{
    if (b == 0)
    {
        printf("Chyba: deleni nulou!\n");
        return -1;
    }

    return (double) a / b;
}

int main(void)
{
    int a, b;
    char operace;

    printf("Prosim zvolte operaci (+, -, *, /): ");
    scanf("%c", &operace);

    printf("Prosim zadejte 2 cisla (oddelena mezerou): ");
    scanf("%d %d", &a, &b);

    double vysledek;

    switch (operace)
    {
    case '+':
        vysledek = scitani(a, b);
        break;
    case '-':
        vysledek = odecitani(a, b);
        break;
    case '*':
        vysledek = nasobeni(a, b);
        break;
    case '/':
        vysledek = deleni(a, b);
        break;
    default:
        printf("Neplatna operace!\n");
        return -1;
    }

    printf("Vysledek: %d %c %d = %.2f\n", a, operace, b, vysledek);
    return 0;
}
 
Kód je jako vždy dostupný na GitHubu.


Gratuluju všem, kdo se prokousali až sem. Vím, že začátky nejsou jednoduché. Pokud něčemu nerozumíte, klidně se ozvěte na Discordu nebo tady dole v komentářích. Nezpomeňte, že žádná otázka není blbá otázka a pravděpodobně nebudete první ani poslední, co si takovou nebo podobnou otázku klade.

Kam dál?

Další příklady