Podmínky absolvování předmětu Základy programování

Dodržení těchto zásad je nezbytné pro to, aby byl program obhajitelný.

Základní požadavky

Program musí být bez syntaktických a sémantických chyb (varování překladače) a naformátován ve stylu K&R.
Program musí být členěn na podprogramy. Pokud program čte číslo z klávesnice, bude v něm vždy podprogram pro načtení tohoto čísla s ověřením jeho datového typu nebo i požadovaných mezí.
Podprogramy nesmí být vnořené funkce, viz Učebnice jazyka C Pavla Herouta 2. díl, kapitola 23.6.2.
Program musí skutečně dělat to, co slibuje. Například, když slibuje, že třídí podle velikosti, tak se nestane, že hodnoty 100, 200, 20 budou mít po setřídění pořadí 100, 20, 200.
Program se nesmí ukončit, když je do něj zadán nesprávný vstup z klávesnice. Pokud čte vstup ze souboru, může oznámit, že obsah souboru není správný, a skončit, ale při čtení z klávesnice by uživateli vadilo, kdyby po zadání něklika hodnot správě zadal další hodnotu chybně a program by kvůli tomu nic nespočítal a vše by se muselo zadávat znova. Ověření správného datového typu na vstupu a informování uživatele o případné chybě musí být součástí funkce pro čtení vstupní hodnoty.
Program se nesmí nikdy z jakýchkoli důvodů zacyklit nebo havarovat, tedy nesmí se i při špatných vstupech nebo třeba díky pointerům v programu objevit toto okno.

Dodržení těchto zásad může vylepšit známku ze zkoušky.

Programy s menu, pomocí kterého se vybírá jednoduchá úloha

Po výpočtu úlohy nesmí program skončit, ale musí se znovu objevit menu umožňující spočítat další úlohu.
Nejvyšší úroveň menu musí nabízet volbu pro ukončení programu.
Nižší volby ve víceúrovňových menu mohou také mít volbu pro okamžité ukončení programu namísto postupných přesunů do vyšších menu.
U víceúrovňových menu jsou po výpočtu úlohy dvě možnosti:

Globální proměnné

V programu by neměly být globální proměnné, protože ty jsou nezbytné jen u velmi pokročilého například systémového programování. Globální proměnné, které jsou v programu, protože s nimi pracují podprogramy, jdou nahradit lokálními proměnnými tak, že se podprogramům dají parametry.

Konstanty

Všechny literály (obzvlášť číselné konstanty a názvy souborů) roztroušené v kódu nahraďte pojmenovanými konstantami. V kódu mohou zůstat pouze konstanty s hodnotou 1 a 0.
Pojmenované konstanty používejte i v rámci textových řetězců, například místo printf("Hadate cisla od 1 do 100.\n"); má být printf("Hadate cisla od 1 do %d.\n", MAX_HADANE_CISLO);, protože maximální číslo je vhodné mít definované jako pojmenovanou konstantu.
Hodnoty znaků zapisujte stylem 'a' namísto 97.
Například místo nahodne_pismeno = rand() % 26 + 97; pište nahodne_pismeno = rand() % (1 + 'z' - 'a') + 'a';, protože se tím odhalí logika kódu. Kód musí být především pochopitelný pro člověka.
Pokud je v programu velké množství konstant, které se mohou časem měnit, například po přijetí nové legislativy, může být vhodnější mít je v konfiguračním textovém souboru, ze kterého je program po svém spuštění načte do proměnných. V konfiguračním souboru je nutné načítané hodnoty popsat pro člověka. Program může jejich popis buďto vypsat při jejich načítání nebo přeskočit a ignorovat.
Příklad obsahu konfiguračního souboru:
0.21 Základní sazba DPH
0.15 Snížená sazba DPH

Identifikátory

Názvy (to jest identifikátory) proměnných a funkcí volte tak, aby z nich byl jasný jejich význam.
Dodržujte konvence:

Opakující se kód

Pokud jsou v programu úseky kódu, které se liší jen některými proměnnými, je často vhodné je nahradit jedním podprogramem.
Typické situace: Pokud jsou v programu proměnné, které spolu souvisí, například stupeň obtížnosti hry a jeho vlastnosti, měly by být zabaleny v poli struktur, například ve hře pro procvičování počtů je vhodná struktura
#define MAX_POCET_OPERATORU 4
typedef struct { /* Definice vlastního datového typu, která se umisťuje globálně. */
  char* operatory;
  int max_hodnota[MAX_POCET_OPERATORU]; /* Pro každý operátor se může stanovit jiný rozsah operandů. */
} OBTIZNOST;
Potom se deklaruje lokální proměnná obtiznost jako pole s položkou typu struktura a přiřadí se jí konkrétní hodnoty nebo se později načtou z konfiguračního souboru.
OBTIZNOST obtiznost[] = {
  {"+-", {20, 20}},
  {"+-*", {500, 500, 20}},
  {"+-*/", {1000, 1000, 20, 200}}
};
Možnosti použití takového pole s položkou typu struktura:

Komunikace s uživatelem

Když chceme po uživateli, aby něco zadal, tak se musí vypsat výzva k zadání, například:
Vase volba:
Za výzvou je dvojtečka a za dvojtečkou je mezera. Za mezerou na stejném řádku se objevuje to, co uživatel zadává.
Typicky se na toto zapomíná po výpisu hlavního menu a po spočítání nějaké úlohy, po které program nemá ještě končit.
Pokud vybíráme pomocí písmenek, tak nemá záležet na jejich velikosti, tedy například program zareaguje stejně, když zadáme 'a' i 'A'.
Pokud má uživatel zadat několik hodnot, tak pro každou hodnotu se musí volat funkce pro čtení této jediné hodnoty s jejím ověřením zvlášť. Například místo "Zadejte výšku, šířku, hloubku: " musí být výzva "Zadejte výšku: ", potom se případné chyby uživatele řeší ve funkci pro zadání čísla, po úspěšném zadání výšky se objeví výzva "Zadejte šířku: " a tak dále.

Soubory

Otevírání a uzavírání souborů ověřujte na úspěch standardním způsobem dle Učebnice jazyka C Pavla Herouta.
Soubor, který jste otevřeli, také zavřete.
Pokud pro to není zvláštní důvod, neotevírejte a nezavírejte soubory více než jednou nebo vícekrát než na jediném místě programu.
Například u kalkulaček všech druhů je vhodné mít výstupní soubor, který zaznamenává úlohy se všemi vstupními hodnotami a jejich výsledky.
Program typu kalkulačka zpravidla zapisuje výsledky do souboru v podprogramech. V takových případech je nejlepší otevřít soubor pro zápis ve funkci volající jednotlivé podprogramy pro funkce kalkulačky, předávat do podprogramů pointer na otevřený soubor a na konci funkce volající jednotlivé podprogramy pro funkce kalkulačky soubor pro zápis zase zavřít.
Nechtějte po uživateli, aby musel vždy zadat do programu velké množství dat, například matici nebo dlouhý text. Místo toho bude takový vstup připraven ve vstupním souboru. Čtení ze souboru zařiďte během vývoje programu co nejdříve, abyste si ušetřili práci při ladění programu. Zadávání toho, co je v souboru, pomocí klávesnice může být nepovinně jako jedna z možností, kterou si uživatel může zvolit.
Pokud program zpracovává nebo dokáže jako jednu ze svých možností zpracovat vstupní soubor, k projektu přiložte soubor s vhodným vstupem.
Programy, které čtou vstup ze souboru, je možné udělat tak, že čtou celou množinu souborů a výstupy zapisují do jednoho nebo více výstupních souborů, pomocí argumentů funkce main() nebo redirekce spolu se spustitelným souborem s příkazy pro vícenásobné spuštění programu s parametry se jmény vstupních a výstupních souborů. Spustitelný soubor a vstupní soubory musí být dodány spolu s projektem. Program tohoto typu nemá opakovací menu.

Pointery

Alokaci paměti ověřujte na úspěch standardním způsobem dle Učebnice jazyka C Pavla Herouta.
Je-li v programu použita funkce malloc() nebo calloc(), musí být použita i funkce free(), aby nedošlo k úniku paměti, kdyby se paměť alokovala v cyklu.

Řídící struktury

Pro standardní, tedy často se opakující, typické úlohy používejte standardní učebnicová řešení.
Například opakovací menu řešte vždy pomocí struktury
do {
  kód pro zadávání volby
  switch (volba) {
    case VOLBA1:
    ...
    default:
      kód pro špatnou volbu
  }
} while (podmínka, za které se znovu vrátíme do menu);
Strukturu switch při programování funkcí menu preferujte před strukturou if...else, protože je přehlednější.
Kód v rámci struktury switch nebo if...else by měl být krátký, aby byl přehledný, což se řeší tím, že je členěn na podprogramy.

Skoky

Skoky všeho druhu používejte jen, pokud jsou součástí standardních způsobů řešení typických úloh probíraných v Učebnici jazyka C Pavla Herouta, například ověření správnosti otevření souboru:
if ((fr = fopen(VSTUPNI_SOUBOR, "r")) == NULL) {
  printf("Soubor %s se nepodarilo otevrit.\n", VSTUPNI_SOUBOR);
  return 1; /* Skok, který je vhodný. */
}
kód (zpravidla mnoho řádků), který se provede, když se soubor podařilo otevřít.
Kód
if ((fr = fopen(VSTUPNI_SOUBOR, "r")) == NULL) {
  printf("Soubor %s se nepodarilo otevrit.\n", VSTUPNI_SOUBOR);
} else {
  kód (zpravidla mnoho řádků), který se provede, když se soubor podařilo otevřít.
}
neobsahuje skok a proto je lepší z hlediska zásad strukturovaného programování, ale má nevýhodu v tom, že celý kód, který se provede, když se soubor podařilo otevřít, což je zpravidla spousta kódu, je v rámci struktury, což snižuje kvalitu kódu, protože v kódu by neměla být zbytečná vnoření.
Typický druh skoku, který by se měl ve většině případů nahradit cykly a podmínkami, je goto.

Dodržení těchto zásad může mírně zlepšit hodnocení programu.

Deklarace proměnných a konstant

V rámci funkce nejdříve deklarujte vlastní konstanty (modifikátor const), potom proměnné a teprve po nich pište příkazy.
Vlastní datové typy (klíčové slovo typedef) je většinou nejvhodnější definovat globálně za konstantami definovanými pomocí direktivy #define. Datové typy proměnných by měly odpovídat oboru hodnot dané úlohy. Například počítání obvodu a obsahu by nemělo být pouze celočíselné, hádání čísla od MIN do MAX naopak musí být celočíselné. Používáme-li knihovnu math.h, je vhodné mít proměnné, které se stanou argumenty funkcí z této knihovny, typu double namísto float.

Komentáře

Komentujte kód, aby se vám lépe obhajoval. Neřešte komentování kódu nějakým odděleným souborem s dokumentací, ale mějte komentáře v kódu, protože současné SW inženýrství má workflow ve stylu, že se nejdříve vytvoří kód s komentáři a potom se nějakým programem může z komentovaného kódu vytvořit zvláštní soubor s dokumentací.

Délka řádků kódu

Špatně:
printf("Zadejte\n'p' pokud chcete hadat pismeno, nebo\n'c' pokud chcete hadat cislo.\n(pokud chcete ukoncit program, zadejte jakykoliv jiny znak)\n\nPOZOR - pismena se hadaji od 'a' do 'z', a cisla od 1 do 100.\n");
Dobře:
printf("Zadejte\n");
printf("'p' pokud chcete hadat pismeno, nebo\n");
printf("'c' pokud chcete hadat cislo.\n");
printf("(pokud chcete ukoncit program, zadejte jakykoliv jiny znak)\n\n");
printf("POZOR - pismena se hadaji od 'a' do 'z', a cisla od 1 do 100.\n");

Přehledné menu na obrazovce

Špatně:
Zadejte 'p' pokud chcete hadat pismeno, nebo 'c' pokud chcete hadat cislo. (pokud chcete ukoncit program, zadejte jakykoliv jiny znak) POZOR - pismena se hadaji od 'a' do 'z', a cisla od 1 do 100.

Lépe:
Zadejte
'p' pokud chcete hadat pismeno
'c' pokud chcete hadat cislo
jakykoliv jiny znak pokud chcete ukoncit program

POZOR
Pismena se hadaji od 'a' do 'z'.
Cisla se hadaji od 1 do 100.

Výpisy programu pište bez diakritiky a odstraňte překlepy a různé chyby z nedbalosti.

Běh programu

Pokud to nemá nějakou užitečnou funkci, tak nechtějte po uživateli, aby stisknul libovolnou klávesu nebo zadal nějaký libovolný znak, kvůli tomu, aby program mohl pokračovat. Po vypočítání úlohy se má program sám bezprostředně vrátit zpět do menu nebo skončit.
Při komunikaci s uživatelem rozlišujte mezi slovy "zadej" a "stiskni":