004 ‐ výpis řady - zizanek/github-tz-is-2026-sk1 GitHub Wiki
Úvod: Základní skladba programu
Než začneme psát konkrétní řádky kódu, je důležité pochopit, jak je většina programů (od nejjednodušších konzolových úloh až po rozsáhlé systémy) vnitřně strukturována.
Téměř každý algoritmus se v zásadě skládá ze tří až čtyř navazujících fází:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐
│ VSTUP │ ──> │ LOGIKA │ ──> │ VÝSTUP │
│ (Input / Data) │ │ (Algoritmus) │ │ (Output / Zobrazení)│
└─────────────────┘ └─────────────────┘ └─────────────────────┘
▲ │
└──────────── [ŘÍDICÍ SMYČKA / OPAKOVÁNÍ] ──────┘
-
Příprava a Vstup (Input):
- Získání dat potřebných pro běh programu (od uživatele z klávesnice, ze souboru nebo ze sítě).
- V této fázi je klíčová validace – program musí data zkontrolovat dříve, než s nimi začne cokoliv dělat.
- U začátečnických programů tato část často zabírá nejvíce řádků kódu, protože ošetřujeme překlepy a neplatné zadání uživatele.
-
Logika / Výpočet (Processing):
- Samotné „jádro“ algoritmu (výpočty, cykly, podmínky, transformace dat).
- U jednoduchých úloh bývá tato část překvapivě krátká – často jen 3 až 5 řádků čisté matematiky nebo logiky.
- Zde se řeší podstata problému odděleně od toho, jak se data načetla nebo jak se budou zobrazovat.
-
Výstup (Output):
- Prezentace výsledků uživateli (výpis do konzole, uložení do souboru, zobrazení v grafickém rozhraní).
- Správný výstup by měl být přehledný, srozumitelný a měl by obsahovat i kontext (např. rekapitulaci vstupních hodnot, aby uživatel věděl, k čemu výsledek patří).
-
Řídicí smyčka (Application Lifecycle):
- Zajišťuje, aby program po jednom výpočtu hned neskončil, ale umožnil uživateli celou akci zopakovat nebo program korektně ukončit.
Při čtení i psaní kódu je dobré si všímat, kde jedna fáze končí a druhá začíná. Tento návyk vám později výrazně usnadní rozdělování programů do samostatných funkcí a metod.
Program: Výpis aritmetické řady čísel
Tento program slouží k procvičení základních stavebních kamenů jazyka C#:
- cyklus s podmínkou na začátku (
while), - bezpečné načítání číselného vstupu od uživatele (
int.TryParse), - samostatná deklarace proměnných v paměti (
int), - formátovaný výstup do konzole pomocí interpolace řetězců (
$"").
1. Kompletní zdrojový kód programu
string again = "a";
// Řídicí cyklus aplikace:
// .ToLower() převede vstup na malá písmena, takže program pokračuje při zadání 'a' i 'A'.
// Jakýkoliv jiný vstup program ukončí.
while (again.ToLower() == "a")
{
Console.Clear();
Console.WriteLine("****************************");
Console.WriteLine("***** Výpis řady čísel *****");
Console.WriteLine("****************************");
Console.WriteLine("******* Tomáš Žižka ********");
Console.WriteLine("****************************");
Console.WriteLine();
// 1. Vstup počáteční hodnoty
Console.Write("Zadejte první číslo řady (celé číslo): ");
int first;
while (!int.TryParse(Console.ReadLine(), out first))
{
Console.Write("Nezadali jste celé číslo. Zadejte první číslo znovu: ");
}
// 2. Vstup koncové hodnoty
Console.Write("Zadejte poslední číslo řady (celé číslo): ");
int last;
while (!int.TryParse(Console.ReadLine(), out last))
{
Console.Write("Nezadali jste celé číslo. Zadejte poslední číslo znovu: ");
}
// 3. Vstup diference s kontrolou na kladnou hodnotu
Console.Write("Zadejte diferenci (kladné celé číslo): ");
int step;
while (!int.TryParse(Console.ReadLine(), out step) || step <= 0)
{
Console.Write("Diference musí být kladné celé číslo větší než 0. Zadejte znovu: ");
}
// 4. Rekapitulace zadaných hodnot
Console.WriteLine();
Console.WriteLine("====================================");
Console.WriteLine($"První číslo: {first}; Poslední číslo: {last}; Diference: {step}");
Console.WriteLine("====================================");
Console.WriteLine();
// 5. Výpis řady
Console.WriteLine("Výpis číselné řady:");
if (first <= last)
{
int current = first;
while (current <= last)
{
Console.WriteLine(current);
current += step;
}
}
else
{
Console.WriteLine("První číslo je větší než poslední. Tento program umí vypsat pouze vzestupnou řadu (od menšího k většímu).");
}
// 6. Dotaz na opakování
Console.WriteLine();
Console.Write("Pro opakování programu stiskněte 'a' a potvrďte klávesou Enter: ");
again = Console.ReadLine() ?? "";
}
2. Řídicí cyklus programu (Event / Repeat Loop)
string again = "a";
while (again.ToLower() == "a")
{
// ... tělo programu ...
Console.Write("Pro opakování programu stiskněte 'a' a potvrďte Enterem: ");
again = Console.ReadLine() ?? "";
}
Princip:
- Proměnná
againuchovává text zadaný uživatelem. - Cyklus
whiletestuje podmínku před každým průchodem. Protože je na začátku hodnota nastavena na"a", tělo proběhne minimálně jednou. - Metoda
.ToLower()převádí text na malá písmena, takže program pokračuje i při zadání velkého písmeneA.
3. Bezpečné načítání celočíselného vstupu
Proč nepoužívat int.Parse u uživatelských vstupů?
// NEVHODNÉ ŘEŠENÍ:
int first = int.Parse(Console.ReadLine());
Pokud uživatel zadá text (např. "ahoj") nebo stiskne pouze Enter, metoda int.Parse vyvolá neošetřenou výjimku (FormatException) a celá aplikace okamžitě spadne.
Správné řešení s oddělenou deklarací proměnné:
Console.Write("Zadejte první číslo řady (celé číslo): ");
int first;
while (!int.TryParse(Console.ReadLine(), out first))
{
Console.Write("Nezadali jste celé číslo. Zadejte první číslo znovu: ");
}
Jak to funguje:
int first;nejprve vyhradí místo v paměti pro celé číslo.Console.ReadLine()přečte řádek textu od uživatele.int.TryParse(...)se pokusí text převést:- Pokud se převod podaří: uloží hodnotu přes parametr
out firsta vrátítrue. - Pokud se převod nezdaří: vrátí
falsea program nespadne.
- Pokud se převod podaří: uloží hodnotu přes parametr
- Operátor negace
!otočí logickou hodnotu: pokud převod selhal (!falsejetrue), cykluswhilese zopakuje a požádá o vstup znovu.
4. Ošetření logických mezí (Diference nesmí být nulová)
Console.Write("Zadejte diferenci (kladné celé číslo): ");
int step;
while (!int.TryParse(Console.ReadLine(), out step) || step <= 0)
{
Console.Write("Diference musí být kladné celé číslo větší než 0. Zadejte znovu: ");
}
Algoritmické riziko:
Pokud by diference (step) byla rovna 0, hodnota proměnné current by se nikdy nezvýšila a cyklus výpisu by skončil nekonečnou smyčkou. Podmínka step <= 0 brání zacyklení a vynucuje smysluplnou hodnotu.
5. Generování a výpis číselné řady
int current = first;
while (current <= last)
{
Console.WriteLine(current);
current += step; // ekvivalent zápisu: current = current + step;
}
Kroky algoritmu:
- Řídicí proměnná
currentse nastaví na počáteční hodnotufirst. - Podmínka
current <= lasthlídá, zda jsme nepřekročili horní mez. - Po vypsání se hodnota
currentzvětší o diferencistep. - Jakmile hodnota přesáhne
last, cyklus se přirozeně zastaví.
6. Otázky k zamyšlení a obhajobě kódu
- Co se stane, pokud uživatel zadá
first = 20alast = 5? Proč je před výpisem zařazena podmínkaif (first <= last)? - Jaké klíčové slovo v metodě
int.TryParseumožňuje předat proměnnou tak, aby do ní metoda mohla zapsat výsledek? - Jak by bylo potřeba upravit podmínku a přičítání v cyklu, kdybychom chtěli vytvořit sestupnou řadu (např. od 100 do 0)?
7. Dobré programátorské návyky (Best Practices)
Na tomto prvním programu si můžeme ukázat několik základních pravidel profesionálního vývoje, která odlišují kvalitní software od narychlo sepsaného skriptu.
7.1. Uživatel nesmí tápat (Informativní UI)
Program běží v textové konzoli, kde uživatel nevidí žádná tlačítka ani nápovědu. O to důležitější je jasná komunikace:
- Přesné výzvy: Místo vágního textu
Zadejte číslo:uveďteZadejte první číslo řady (celé číslo):. Uživatel musí předem vědět, jaký formát program očekává. - Konstruktivní chybové hlášky: Nestačí napsat
Chyba!. Řekněte, v čem problém spočívá a co má uživatel udělat pro nápravu (Nezadali jste celé číslo. Zadejte hodnotu znovu:). - Zpětná vazba (rekapitulace): Před spuštěním samotného výpočtu program zopakuje zadané hodnoty. Uživatel si tak okamžitě ověří, s jakými daty aplikace reálně pracuje.
7.2. Předpokládejte neplatný vstup (Defenzivní programování)
Uživatelé dělají chyby, překlepy nebo program testují nečekanými vstupy:
- Nikdy se nespoléhejte na metody, které při chybě spadnou (
int.Parse). - Používejte bezpečné parsování (
int.TryParse) v kombinaci s cyklem, který aplikaci udrží v chodu, dokud nezíská korektní data. - Aplikace nesmí za žádných okolností skončit neošetřenou výjimkou (červeným chybovým výpisem v konzoli).
7.3. Kontrola logických mezí, nejen datových typů
To, že uživatel zadá platné číslo typu int, ještě neznamená, že dává v kontextu úlohy smysl:
- Diference
step = 0je formálně platné celé číslo, ale pro cykluswhile (current <= last)znamená okamžité zamrznutí v nekonečné smyčce. - Vždy hlídejte logické podmínky domény problému (např.
step > 0).
7.4. Anglické názvy identifikátorů (Clean Code)
Ačkoliv texty vypisované uživateli jsou v češtině, zdrojový kód píšeme podle mezinárodních standardů:
- Proměnné (
first,last,step,current,again) i názvy metod volíme v angličtině. - V praxi se software vyvíjí v mezinárodních týmech, s mezinárodními knihovnami a verzovacími nástroji. Míchání češtiny do kódu zhoršuje čitelnost a profesionalitu projektu.
7.5. Ochrana před hodnotami null
Moderní C# klade velký důraz na bezpečnost práce s pamětí:
- Metoda
Console.ReadLine()může za určitých okolností vrátit prázdný odkaz (null). - Použitím operátoru sloučení s hodnotou null (
?? "") předcházíme pádům naNullReferenceExceptiona zbavujeme kód varování kompilátoru.
8. Jak přemýšlet jako programátor: Jak sestavit algoritmus cyklu
Pro začátečníka bývá nejtěžší přejít od zadání úlohy k funkčnímu kódu. Když se podíváte na samotné jádro výpisu, má pouhých 6 řádků (včetně složených závorek):
int current = first;
while (current <= last)
{
Console.WriteLine(current);
current += step; // ekvivalent zápisu: current = current + step;
}
Jak na tuto konstrukci přijít z hlavy? Stačí si položit 4 základní otázky, které fungují pro jakýkoliv cyklus v programování:
Krok 1: Kde začínám? (Inicializace)
Než se cyklus rozběhne, musíme si připravit výchozí stav.
- Otázka: „Jaká je hodnota úplně prvního čísla, které chci zpracovat?“
- Odpověď: Hodnota, kterou uživatel uložil do proměnné
first. - Kód: Vytvoříme si pracovní proměnnou (kurzor / počítadlo):
(Poznámka: Neupravujeme přímo proměnnouint current = first;first, abychom si nezničili původní zadanou hodnotu pro případný další výpis).
Krok 2: Dokdy má cyklus pokračovat? (Podmínka běhu)
V C# klíčové slovo while znamená „DOKUD PLATÍ, ŽE...“, nikoliv „AŽ NASTANE...“.
- Otázka: „Za jaké podmínky má program ještě vypsat další číslo?“
- Častá chyba začátečníků: Přemýšlí nad tím, kdy má cyklus skončit („skonči, až bude current větší než last“ $\rightarrow$
current > last). - Správný postup: Podmínku musíme formulovat pro stav, kdy má cyklus ještě běžet: „Běž, dokud je aktuální číslo menší nebo rovno cíli.“
- Kód:
while (current <= last)
Krok 3: Co se má stát v jednom kroku? (Tělo cyklu)
Soustřeďte se vždy pouze na jeden jediný okamžik, jako by program dělal jen jeden krok:
- Otázka: „Co mám s aktuálním číslem udělat teď a tady?“
- Odpověď: Zobrazit ho uživateli na obrazovce.
- Kód:
Console.WriteLine(current);
Krok 4: Jak se posunu dál? (Krokování / Posun)
Každý cyklus se musí posouvat směrem k ukončovací podmínce, jinak vznikne nekonečná smyčka (program zamrzne).
- Otázka: „Jak se dostanu k následujícímu číslu v řadě?“
- Odpověď: K aktuální hodnotě přičtu zadanou diferenci
step. - Kód:
current += step;
Shrnutí postupu na mentálním modelu:
Kdykoliv stojíte před prázdným monitorem a potřebujete navrhnout cyklus, vezměte si tužku a papír a projděte si tuto tabulku:
| Fáze návrhu | Otázka pro vás | Konkrétní kód v C# |
|---|---|---|
| 1. Start | Z jakého čísla vycházím? | int current = first; |
| 2. Podmínka | Dokud platí co, má program pokračovat? | while (current <= last) |
| 3. Akce | Co přesně chci v tomto jednom kroku provést? | Console.WriteLine(current); |
| 4. Krok vpřed | Co musím změnit, abych se přiblížil ke konci? | current += step; |
Pokud si tyto 4 otázky zautomatizujete, dokážete bezpečně sestavit jakýkoliv cyklus – ať už půjde o počítání splátek, rozklad čísla na cifry nebo vykreslování herní grafiky.