Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij slevové akce 30% výuky zdarma!
Pouze tento týden sleva až 80 % na e-learning týkající se PHP
Discount week - April - 30

Lekce 14 - Vícerozměrná pole v C# .NET

V minulé lekci, Cykly v C# .NET podruhé - do-while, break a continue, jsme ucelili naše znalosti cyklů dalšími konstrukcemi a klíčovými slovy, na která můžeme narazit v cizích zdrojových kódech.

Dnešní díl základních konstrukcí C# .NET pojednává o tzv. vícerozměrných polích.

Jednorozměrné pole

Již umíme pracovat s jednorozměrným polem, které si můžeme představit jako řádku přihrádek v paměti počítače.

Struktura pole

(Na obrázku je vidět pole osmi čísel)

Dvourozměrné pole

Ačkoli to není tak časté, v programování se občas setkáváme i s vícerozměrnými poli a to zejména pokud programujeme nějakou simulaci (např. hru).

Dvourozměrné pole si můžeme v paměti představit jako tabulku a mohli bychom takto reprezentovat např. rozehranou partii piškvorek. Pokud bychom se chtěli držet reálných aplikací, které budete později v zaměstnání tvořit, můžeme si představit, že do 2D pole budeme ukládat informace o obsazenostech sedadel v kinosálu. Situaci bychom si mohli graficky znázornit např. takto:

Struktura dvourozměrného pole

(Na obrázku je vidět 2d pole reprezentující obsazenost kinosálu)

Kinosál by byl v praxi samozřejmě větší, ale jako ukázka nám toto pole postačí. 0 znamená volno, 1 obsazeno. Později bychom mohli doplnit i 2 - rezervováno a podobně. Pro tyto stavy by bylo správnější vytvořit si vlastní datový typ, tzv. výčet, ale s ním se setkáme až později, takže si teď musíme vystačit pouze s čísly.

2D pole deklarujeme v C# .NET následujícím způsobem:

int[,] kinosal = new int [5, 5];

První číslice udává počet sloupců, druhá počet řádků (samozřejmě si to můžeme určit i obráceně, např. matice v matematice se zapisují opačně).

Všechna číselná pole v C# .NET jsou po deklaraci automaticky inicializována samými nulami, můžeme se na to spolehnout. Vytvořili jsme si tedy v paměti tabulku plnou nul.

Naplnění daty

Nyní kinosál naplníme jedničkami tak, jak je vidět na obrázku výše. Protože budeme jako správní programátoři líní, využijeme k vytvoření řádku jedniček for cykly :) Pro přístup k prvku 2D pole musíme samozřejmě zadat 2 souřadnice.

kinosal[2, 2] = 1; // Prostředek
for (int i = 1; i < 4; i++) // 4. řádek
{
    kinosal[i, 3] = 1;
}
for (int i = 0; i < 5; i++) // Poslední řádek
{
    kinosal[i, 4] = 1;
}

Výpis

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Výpis pole opět provedeme pomocí cyklu, na 2d pole budeme potřebovat cykly 2 (jeden nám proiteruje sloupce a druhý řádky). Jako správní programátoři nevložíme počet řádků a sloupců do cyklů napevno, jelikož se může změnit. C# .NET poskytuje na 2D poli vlastnost Length jako tomu bylo u 1D pole, ale ta vrací celkový počet prvků v poli, v našem případě tedy 25. Nás bude zajímat metoda GetLength(), která přijímá jako parametr dimenzi (0 pro sloupce, 1 pro řádky) a vrátí nám počet prvků v této dimenzi. První dimenzí je počet sloupců, druhou počet řádků.

Cykly zanoříme do sebe tak, aby nám vnější cyklus projížděl řádky a vnitřní sloupce v aktuálním řádku. Po výpisu řádku je nutné odřádkovat. Oba cykly musí mít samozřejmě jinou řídící proměnnou:

for (int j = 0; j < kinosal.GetLength(1); j++)
{
    for (int i = 0; i < kinosal.GetLength(0); i++)
    {
        Console.Write(kinosal[i, j]);
    }
    Console.WriteLine();
}

Výsledek:

Konzolová aplikace
00000
00000
00100
01110
11111

N-rozměrná pole

Někdy může být příhodné vytvořit si pole o ještě více dimenzích. My všichni si jistě dokážeme představit minimálně 3D pole. S příkladem s kinosálem se nabízí případ užití, kdy má budova více pater (nebo obecně více kinosálů). Vizualizace by vypadala asi nějak takto:

3D pole v C# .NET

3D pole můžeme vytvořit tím samým způsobem, jako 2D pole:

int[, ,] kinosaly = new int [4, 4, 3];

Kód výše vytvoří 3D pole jako na obrázku. Přistupovat k němu budeme opět přes indexer (hranaté závorky) jako předtím, jen již musíme zadat 3 souřadnice.

kinosaly[3, 2, 1] = 1; // Druhý kinosál, třetí řada, čtvrtý sloupec

Pokud metodě GetLength() zadáme parametr s hodnotou 2, získáváme počet "pater" (kinosálů).

Pole polí

Mnoho programovacích jazyků vlastně vícerozměrná pole nepodporuje, C# je spíše výjimkou. Můžeme si v nich ale stejně vytvořit kolika-rozměrné pole chceme, jelikož 2D pole není vnitřně nic jiného, než pole polí. Situaci si můžeme představit tak, že si vytvoříme pole o pěti prvcích (1. řádek) a každá buňka v tomto řádku v sobě bude obsahovat další pole, reprezentující sloupeček.

Takové 2D pole deklarujeme následujícím způsobem:

int[][] kinosal = new int[5][];

Výhodou takto deklarovaného 2D pole je fakt, že si do každého řádku/sloupce můžeme uložit jak velké pole chceme. V některých případech tedy nemusíme "plýtvat" pamětí na celou tabulku a můžeme pole vytvořit "zubaté" (anglicky jagged):

Pole polí v C# .NET

Nevýhodou tohoto přístupu je, že musíme pole nepříjemně inicializovat sami. Původní řádek s pěti buňkami sice existuje, ale jednotlivé sloupečky si do něj musíme navkládat sami (zatím si vložme všechny sloupečky o 5ti prvcích):

for (int i = 0; i < kinosal.Length; i++)
{
    kinosal[i] = new int[5];
}

C# rovněž dále neposkytuje žádný komfort ve formě získání počtu sloupců a řádků polí polí. Velikost pole musíme získat takto:

int sloupcu = kinosal.Length;
int radku = 0;
if (sloupcu != 0)
    radku = kinosal[0].Length;

Všimněte si, že je nutné ptát se na počet sloupců, pokud je totiž 0, nemůžeme se dostat k 1. sloupci, abychom zjistili jeho délku (počet řádků ve sloupci).

K hodnotám v poli poté přistupujeme pomocí 2 indexerů:

kinosal[4][2] = 1; // Obsazujeme sedadlo v 5. sloupci a 3. řadě

(Použití jediného indexeru nám vrátí celý sloupeček na daném indexu)

Zkrácená inicializace vícerozměrných polí

Ještě si ukážeme, že i vícerozměrná pole je možné rovnou inicializovat hodnotami (kód vytvoří rovnou zaplněný kinosál jako na obrázku):

int[,] kinosal = new int[,] {
    { 0, 0, 0, 0, 1 },
    { 0, 0, 0, 1, 1 },
    { 0, 0, 1, 1, 1 },
    { 0, 0, 0, 1, 1 },
    { 0, 0, 0, 0, 1 }
};

(Pole je v tomto zápisu otočené, jelikož definujeme sloupce, které zde zapisujeme jako řádky).

Podobnou inicializaci můžeme použít dokonce i u polí zubatých (kód níže vytvoří zubaté pole jako na obrázku):

int[][] zubatePole = new int[][] {
    new int[] {15, 2, 8, 5, 3},
    new int[] {3, 3, 7},
    new int[] {9, 1, 16, 13},
    new int[] {},
    new int[] {5}
};

Na závěr bych rád dodal, že někteří lidé, kteří neumí správně používat objekty, využívají 2D polí k ukládání více údajů o jediné entitě. Např. budeme chtít uložit výšku, šířku a délku pěti mobilních telefonů. Ačkoli se vám nyní může zdát, že se jedná o úlohu na 3D pole, ve skutečnosti se jedná o úlohu na obyčejné 1D pole (přesněji seznam) objektů typu Telefon. Ale o tom až u objektově orientovaného programování. Pole si určitě ještě vyzkoušejte ještě v cvičení v tomto kurzu.

V příští lekci, Matematické funkce v C# a knihovna Math, se podíváme na matematické funkce.


 

Měla jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 310x (32.73 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
Cykly v C# .NET podruhé - do-while, break a continue
Všechny články v sekci
Základní konstrukce jazyka C# .NET
Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
30 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 13 let. Má rád Nirvanu, sushi a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (20)

 

 

Komentáře

Avatar
Patrik Valkovič:13.7.2015 16:26

Jen bych rád doplnil, že někdy se také využívá klasického jednorozměrného pole pro simulaci pole vícerozměrného. Často jsem se s tím setkal napříkald v C.
Idea je taková, že index dopočítáme. Vezneme příklad : mám krychli o hraně 5 prvků. Jednorozměrné pole bude mít 555=125 prvků.
Pokud budeme chtít získat prvek v hloubce 3 (z), 2 prvek zhora (y) a 4 prvek od levého kraje (x), můžeme se dopočítat následovně.

int IndexPrvku = (z-1) * Vyska(5) * Sirka(5) + (y-1) * Sirka(5) + x;

To platí za předpokladu, že indexujeme z levého horního rohu směrem do pravého dolního a teprve potom dozadu. Jedná se tedy o 59 prvek. To, že je prvek ve třetí vrstvě znamená, že před ním jsou ještě dvě vrstvy, které musíme dopočítat, proto se odečítá jednička.
Jedná se jen o zajímavost, se kterou se ale často v C setkávám :)

Odpovědět
13.7.2015 16:26
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Patrik Valkovič:13.7.2015 17:59

Omlouvám se, použil jsem hvězdičky místo krát a tak z toho mám místo násobení kurzívu. Má tam být samozřejmě "Jednorozměrné pole bude mít 5 krát 5 krát 5=125 prvků."
Už příspěvek nemůžu upravit

Odpovědět
13.7.2015 17:59
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Martin Turner:30.7.2015 10:20

Zdravím,
mohl bych požádat o radu, jak zjistit indexy daného prvku ve vícerozměrném poli?
Děkuji.

 
Odpovědět
30.7.2015 10:20
Avatar
Odpovídá na Martin Turner
Štefan Pružinský:31.7.2015 14:03

Ahoj,
riešenie tvojho problému je jednoduché. Predstav si takéto pole:

1   2   3   4   5
6   7   8   9   10
11  12  13  14  15
16  17  18  19  20
21  22  23  24  25
26  27  28  29  30
31  32  33  34  35

A chceme nájsť napr. index čísla 29:

int hladanyPrvok = 29;
for (int y = 0; y < pole.GetLength(1); y++)
{
    for (int x = 0; x < pole.GetLength(0); x++)
    {
        if (pole[x, y] == hladanyPrvok)
            Console.Write(x + "x" + y);
    }
}

Výpis je 3x5, čiže x = 3 a y = 5 (Pole začína od čísla nula. Ak chceme index ôs, ktoré začínajú od 1, k výsledku prirátame 1 tzn. 4x7). Algoritmus je nasledovný: Prejdeme všetky prvky poľa a pri každom prvku overujeme jeho zhodu z hľadaným prvkom. :)

Odpovědět
31.7.2015 14:03
Najefektívnejším spôsobom debuggingu je modlitba. :)
Avatar
Martin Turner:31.7.2015 14:13

Děkuji,

dospěl jsem postupně ke stejnému výsledku. :-)

 
Odpovědět
31.7.2015 14:13
Avatar
Ondřej Krsička
Redaktor
Avatar
Ondřej Krsička:13.5.2016 15:17

To zapisování sloupečků na řádek je strašně stupidní.

int[,] kinosal = new int[,] {
        { 0, 0, 0, 0, 1 },
        { 0, 0, 0, 1, 1 },
        { 0, 0, 1, 1, 1 },
        { 0, 0, 0, 1, 1 },
        { 0, 0, 0, 0, 1 }
};
 
Odpovědět
13.5.2016 15:17
Avatar
Václav Tobiška:7.7.2017 13:20

Ta orientace sloupce/řádky je pěkně šílená, ale několik vytvořených polí snad pomůže v zafixování...

 
Odpovědět
7.7.2017 13:20
Avatar
62624
Člen
Avatar
62624:26.7.2017 22:54

užitečné.

 
Odpovědět
26.7.2017 22:54
Avatar
Riči Jak
Člen
Avatar
Riči Jak:11.9.2017 8:41

Velmi zdařilý celý úvod do C#, tak teď jen procvičovat a zároveň pokročit k dalším částem programování

 
Odpovědět
11.9.2017 8:41
Avatar
ZdenekS
Člen
Avatar
ZdenekS:13.10.2017 16:51

kolegové poradí mi někdo

a/
a1/ List<int> MujList = new List<int>();
a2/ MujList.Add(1);

b/
b1/ jak udělám deklaraci ?
b2/ pokud chci udělat pole o třech prvcích MujList.Add(1,1,1) ???

děkuji

 
Odpovědět
13.10.2017 16:51
Avatar
gcx11
Redaktor
Avatar
Odpovídá na ZdenekS
gcx11:13.10.2017 17:22

Ahoj, myslím že:

List<int> MujList = new List<int>() { 1, 1, 1 };
 
Odpovědět
13.10.2017 17:22
Avatar
ZdenekS
Člen
Avatar
ZdenekS:13.10.2017 20:37

Toto jsem neměl na mysli, v tvém případě kompilátor převede hodnoty na metodu Add. viz přiložený obrázek . Co bych rád věděl jak deklarovat pomocí "List" a následně přidat hodnoty, vytvořit toto pole o třech elementech a např. přidat čtyři řady , - (1,2,3),(4,5,­6),(7,8,9),(7,5,3). Ale nepoužít for ani foreach , použít Add, anebo něco v tomto smyslu

e1 e2 e3
1 2 3
4 5 6
7 8 9
7 5 3

děkuju

 
Odpovědět
13.10.2017 20:37
Avatar
ZdenekS
Člen
Avatar
ZdenekS:13.10.2017 20:45

asi nějak takto, ale nemohu to ani vyguglit

List<int>[] MujList = new List<int>()[];

 
Odpovědět
13.10.2017 20:45
Avatar
gcx11
Redaktor
Avatar
Odpovídá na ZdenekS
gcx11:13.10.2017 22:57

V tom případě myslíš toto:

List<int[]> list = new List<int[]>();

A poté:

list.Add(new int[3]{1, 1, 1});

Ale pokud víš, že tam budeš dávat pouze trojice, tak bych doporučil použít Tuple:

List<Tuple<int, int, int>> triples = new List<Tuple<int, int, int>>();

přidávání:

triples.Add(new Tuple<int,int,int>(1, 1, 1));
 
Odpovědět
13.10.2017 22:57
Avatar
ZdenekS
Člen
Avatar
Odpovídá na gcx11
ZdenekS:14.10.2017 18:02

Skvělý , děkuji moc, to jsem hledal

 
Odpovědět
14.10.2017 18:02
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Petr Zajac
Člen
Avatar
Petr Zajac:28.2.2018 17:48

Tak zatím jsem se s 1D polem dokázak poprat, u 2D pole se mi teď po přečtení pletou řádky a sloupečky, od 3D pole dál už jsem ztracený.
Vysvětlí mi někdo zkušený opravdu "PRAKTICKÉ" využití pole? Pokud zvládnu OOP a WPF není jednodušší se na pole "vykašlat" a dávat si to co zadal uživatel buď rovnou do souboru, nebo pokročit ještě dál a zkrotit "zaklady databází" a ukládat to rozumně tam??? :-O

 
Odpovědět
28.2.2018 17:48
Avatar
huty
Člen
Avatar
Odpovídá na Petr Zajac
huty:28.2.2018 22:50

Pokud chceš reálná data aplikací nějak uchovávat, na pole se vykašli. S polem uchováš data pouze v ram, čili po vypnutí programu o data přijdeš. Pole můžeš použít například pokud programuješ hru, tak si aktuální část mapy načteš do paměti, do pole. Je to jasnější? :-)

Odpovědět
28.2.2018 22:50
obecně je lepší používat více proměnných a dodržovat přehlednost, než psát co nejkratší kód a po měsíci zapomenout, j...
Avatar
pocitac770
Redaktor
Avatar
Odpovídá na Petr Zajac
pocitac770:28.2.2018 22:51

Pole je práce s daty za běhu počítače, pokud počítači aspoň trochu rozumíš, tak víš, že čtení/zápis do RAM paměti je rychlejší, než z/na pevný disk. Praktické využití pole? Cokoliv, kde máš větší počet "něčeho", nějakých dat (myšleno více jak 1) stejného druhu, který chceš mít nějak srovnaný, přehledně uložený za chodu programu, příklady najdeš úplně všude, a naopak nevím, co by jsi při programování bez pole dělal... To, jestli není lepší místo pole používat soubor, či databázi je jako se ptát jestli v následujícím kódu

int i = int.Parse(Console.ReadLine());
Console.Writeline(i + 3);

Nebylo lepší ukládat i na servery Googlu, kde bude i dobře zálohované a chráněné proti hackerům.

 
Odpovědět
28.2.2018 22:51
Avatar
Petr Zajac
Člen
Avatar
Odpovídá na pocitac770
Petr Zajac:1.3.2018 10:44

Počítač jsem i programoval (databáze pod DOS, konkrétně FoxPro), kde netuším jestli se pole dali využívat. Tam jsem na každý údaj měl extra proměnou, kterou jsem po potvrzení formuláře uživatelem dával na disk, takže pole neznám a přijdou mi zatím "cizí".

 
Odpovědět
1.3.2018 10:44
Avatar
Dušan Kovářík:9.6.2018 0:10

Super článek - konečně mi vnesl pochopení do takových věcí, jako např. proč se někdy používá jeden indexer s více indexy a někdy zase více indexerů s jedním indexem. Chvíli jsem musel přemýšlet a také si hrát s kódem, než jsem si potvrdil vlastní hypotézu, že je vlastně jedno, kterou dimenzi si představuji jako řádky a kterou jako sloupce a podobně. Pokud si to budu představovat opačně a v cyklech použité metody GetLength pro odpovídající dimenze správně sladím s pořadím indexů v indexeru, tak vše bude fungovat stejně.

 
Odpovědět
9.6.2018 0:10
Avatar
Marek Dvořák:9.4.2019 16:21

Nemáte tam chybu? První hodnota matice jsou řáky a ne sloupce.

 
Odpovědět
9.4.2019 16:21
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Marek Dvořák
David Čápka:9.4.2019 16:21

Cituji článek:

samozřejmě si to můžeme určit i obráceně, např. matice v matematice se zapisují opačně

Takže ne, nemáme.

Odpovědět
9.4.2019 16:21
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
David Holohlavský:21.3.2020 23:36

Ahoj, díky za článek. ;-) Chtěl bych se zeptat, jak lze lépe vyřešit výpis zubatého pole než jsem to udělal já. Nevím jak vypsat po řádcích pole, které má proměnnou délku sloupce, proto jsem to vypisoval po sloupcích, které jsem vypsal do řádku.

// Zkrácená inicializace vícerozměrných polí
int[][] zubatePole = new int[][]
{
    new int[] {15, 2, 8, 5, 3},
    new int[] {3, 3, 7},
    new int[] {9, 1, 16, 13},
    new int[] {},
    new int[] {5}
};
// Získání velikosti pole
int sloupcu = zubatePole.Length;
int[] radku = new int[zubatePole.Length];
for (int i = 0; i < zubatePole.Length; i++)
{
    if (sloupcu != 0)
    {
        radku[i] = zubatePole[i].Length;
    }
}
// Výpis
for (int j = 0; j < sloupcu; j++)
{
    Console.Write("Sloupec {0}: ", j);

    for (int i = 0; i < radku[j]; i++)
    {
        Console.Write(zubatePole[j][i].ToString().PadLeft(3));
    }
    Console.WriteLine();
}
Console.ReadKey();
 
Odpovědět
21.3.2020 23:36
Avatar
Dominik Němeček:11.7.2020 20:49

Parádní článek, děkuji! :)

 
Odpovědět
11.7.2020 20:49
Avatar
Bambinot
Člen
Avatar
Bambinot:8. února 23:56

Ahoj,
neměl by být kód spíše takovýto:

int[, ,] kinosaly = new int [4, 4, 3];

aby odpovídal obrázku https://www.itnetwork.cz/…/3d_pole.png ?

 
Odpovědět
8. února 23:56
Avatar
Lukáš Lakota:24. února 21:12

Ahoj, prosím jak je následující citát myšlen?

První číslice udává počet sloupců, druhá počet řádků (samozřejmě si to můžeme určit i obráceně, např. matice v matematice se zapisují opačně).

C# Multidimensional Arrays tady je jasně řečeno, že se to zapisuje opačně, což jsem si ve VS ověřil. :-)

 
Odpovědět
24. února 21:12
Avatar
Václav Dachs:21. března 22:28

Ahoj, super článek! :-D Hned jsem zkoušel vícerozměrná pole využít pro Morseův kodér/dekodér.
Aplikace automaticky rozeznává text a morseovku, dále rozeznává všechny standardizované znaky (včetně @) a speciální signály.

Tady je výsledek:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace _074_MorseCode2
{
    class Program
    {
        static void Main(string[] args)
        {
            //výpis názvu aplikace
            Console.ForegroundColor = ConsoleColor.DarkCyan; //nastavení tamě tyrkysové barva textu
            Console.WriteLine("**************"); //rámeček
            Console.Write("* "); //rámeček
            Console.ForegroundColor = ConsoleColor.Green; //nastavení zelené barva textu
            Console.Write("MORSE CODE"); //název aplikace
            Console.ForegroundColor = ConsoleColor.DarkCyan; //nastavení tamě tyrkysové barva textu
            Console.WriteLine(" *"); //rámeček
            Console.WriteLine("**************"); //rámeček



            //deklarace vzorových polí
            string[][] charakters = new string[][] {
                //latinka bez diakritiky, arabské číslice, interpunkce
                new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ",", ".", ":", ";", "?", "!", "-", "/", "+", "=", "_", "\"", "(", ")", "'", "@", " " },
                //odpovídající znaky v morseovce
                new string[] { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", "--..--", ".-.-.-", "---...", "-.-.-.", "..--..", "--...-", "-....-", "-..-.", ".-.-.", "-...-", "..--.-", ".-..-.", "-.--.", "-.--.-", ".----.", ".--.-.", "" }
            };

            string[][] specialSignals = new string[][] {
                //speciální signály latinkou
                new string[] { "zacatek vysilani", "konec vysilani", "nerozumim", "rozumim", "pomaleji", "cekejte", "omyl", "opakuji", "sos" },
                //speciální signály morseovkou
                new string[] { "-.-.-.-.", "...-.-", ".......", "----.-", "-.-.-..", ".-...", ". . . . . .", ".. .. .. .. .. ..", "...---... " },
                //ekvivalenty speciálních signálů po překódování z latinky
                new string[] { "--.. .- -.-. .- - . -.-  ...- -.-- ... .. .-.. .- -. ..", "-.- --- -. . -.-.  ...- -.-- ... .. .-.. .- -. ..", "-. . .-. --- --.. ..- -- .. --", ".-. --- --.. ..- -- .. --", ".--. --- -- .- .-.. . .--- ..", "-.-. . -.- . .--- - .", "--- -- -.-- .-..", "--- .--. .- -.- ..- .--- ..", "... --- ...  " },
                //ekvivalety speciálních signálů překódovaných z morseovky
                new string[] {"eeeeee", "iiiiii"}
            };

            string[,] diacriticalChars = new string[,] {
                //znaky s diakritikou
                { "á", "č", "ď", "é", "ě", "í", "ň", "ó", "ř", "š", "ť", "ú", "ů", "ý", "ž" },
                //ekvivalenty znaků bez diakritiky
                { "a", "c", "d", "e", "e", "i", "n", "o", "r", "s", "t", "u", "u", "y", "z" }
            };

            //vytvoření regulárního výrazu pro zjištění jestli jde o morseovku
            Regex r = new Regex("[a-z0-9,!?:;+-/@()=]");

            //cyklus pokrčování programu
            bool toContinue = true; //deklarace řídící proměnné pro pokračování programu
            while (toContinue) //dokud je v continue true bude opakovad chod programu
            {
                //reset barev
                Console.ResetColor();

                //načtení zprávy ke zpracování
                Console.ForegroundColor = ConsoleColor.Green; //nastavení tmavě zelené barvy textu
                Console.Write("\nZadejte zprávu ke zpracování: "); //výpis textu
                Console.ResetColor(); //nastavení bílé barvy textu
                string message = Console.ReadLine().Trim().ToLower(); //deklarace proměnné + uložení vstupu od uživatele + ustřihnutí mezery před a za řetězcem + převod řetězce na malé znaky

                //automatické rozpoznání textové a morseovy zprávy + zpracování
                if (r.IsMatch(message)) //pokud jde o zprávu textovou
                {
                    //incializace proměnné pro uložění zakódované zprávy
                    string morseCodeMessage = "";

                    //cyklus nahrazujicí diakritické znaky nediakritickými
                    for (int i = 0; i < diacriticalChars.GetLength(1); i++)
                    {
                        message = message.Replace(diacriticalChars[0, i], diacriticalChars[1, i]);
                    }

                    //výpis upravené zprávy
                    Console.ForegroundColor = ConsoleColor.Green; //nastavení tmavě zelené barvy textu
                    Console.Write("Vaše zpráva po úpravě k převodu do morseovky: ");
                    Console.ResetColor(); //nastavení bílé barvy textu
                    Console.WriteLine(message);

                    //založení pole pro uložení jednotlivých znaků zprávy
                    string[] messageCharakters = new string[message.Length]; //založí pole s velikostí podle délky zprávy

                    //rozbití zprávy na jednotlivé znaky
                    for (int i = 0; i < message.Length; i++) //pro všechny pozice v poli
                    {
                        messageCharakters[i] = message[i].ToString(); //vloží znak převedený na string z pozice i v message na pozici i v poli charakters
                    }

                    //iterace znaky abecedy čisel a interpunkce
                    foreach (string alphabeticChar in messageCharakters) //pro každý znak v poli znaka
                    {
                        string morseCodeChar = "#"; //deklarace proměnné + uložení výchozího znaku - použije se pokud znak není ve vzorovém poli
                        int index = Array.IndexOf(charakters[0], alphabeticChar); //deklarace proměnné + uložení indexu pozice znaku ve vzorovém poli
                        if (index >= 0) //pokud je znak nalezen ve vzorovém poli
                        {
                            morseCodeChar = charakters[1][index]; //vložení znaku ze vzorového pole do proměnné morseCodeChars
                        }
                        morseCodeMessage += morseCodeChar + " "; //přičte do zprávy znak
                    }

                    //cyklus nahrazující sekvenci znaků za zvláštní signál
                    for (int i = 0; i < specialSignals[2].Length; i++)
                    {
                        if (morseCodeMessage.Contains(specialSignals[2][i])) //pokud najde sekvenci znaků v pomocném poli
                        {
                            morseCodeMessage = morseCodeMessage.Replace(specialSignals[2][i], specialSignals[1][i]); //nahrazení přeložené sekvence standardizovanými sekvencemi
                        }
                    }

                    //výpis morseovy zprávy
                    Console.ForegroundColor = ConsoleColor.Green; //nastavení tmavě zelené barvy textu
                    Console.Write("Zakódovaná zpráva: ");
                    Console.ForegroundColor = ConsoleColor.DarkCyan; //nastavení tmavě tyrkysové barvy textu
                    Console.WriteLine(morseCodeMessage);
                }
                else //pokud jde o zprávu v morseovce
                {
                    //deklarace proměnné pro uložení dekódované zprávy
                    string alphabeticMessage = "";

                    //rozbití zprávy na jednotlivé znaky
                    string[] messageCharakters = message.Split(' ');

                    //iterace znaky morseovky
                    foreach (string morseCodeChar in messageCharakters) //pro každý morseův znak v poli messageCharakters
                    {
                        string alphabeticChar = "#"; //deklarace proměnné + uložení výchozího znaku - použije se pokud znak není ve vzorovém poli
                        int index = Array.IndexOf(charakters[1], morseCodeChar); //deklarace proměnné + uložení indexu pozice znaku ve vzorovém poli
                        if (index >= 0) //pokud je znak nalezen ve vzorovém poli
                        {
                            alphabeticChar = charakters[0][index]; //vložení znaku ze vzorového pole do proměnné alphabeticChar
                        }
                        else //pokud není nalezen znak v poli alphabetNumericChars
                        {
                            index = Array.IndexOf(specialSignals[1], morseCodeChar); //uložení indexu pozice speciálního signálu
                            if (index >= 0) //pokud je znak nalezen ve vzorovém poli
                            {
                                alphabeticChar = specialSignals[0][index]; //vložení speciálního signálu
                            }
                        }
                        alphabeticMessage += alphabeticChar; //přičte do zprávy znak
                    }

                    //kontrola speciálního signálu omyl
                    if (alphabeticMessage.Contains("eeeeee")) //pokud dekódovaná zpráva obsahuje sekvenci znaků signálu omyl
                    {
                        alphabeticMessage = alphabeticMessage.Replace("eeeeee", "omyl"); //nahradí sekvenci slovem
                    }

                    //kontrola speciálního signálu opakuji
                    if (alphabeticMessage.Contains("iiiiii")) //pokud dekódovaná zpráva obsahuje sekvenci znaků signálu opakuji
                    {
                        alphabeticMessage = alphabeticMessage.Replace("iiiiii", "opakuji"); //nahradí sekvenci slovem
                    }

                    //výpis dekódované zprávy
                    Console.ForegroundColor = ConsoleColor.Green; //nastavení tmavě zelené barvy textu
                    Console.Write("Dekódovaná zpráva: ");
                    Console.ForegroundColor = ConsoleColor.DarkCyan; //nastavení tmavě tyrkysové barvy textu
                    Console.WriteLine(alphabeticMessage);
                }

                //cyklus hlídající platnost vstupu od uživatele
                bool validChoice = false; //deklarace + nastavení hodnoty řídící proměnné
                while (!validChoice) //dokud validChoice není nastaveno na true
                {
                    //dotaz na pokračování
                    Console.ForegroundColor = ConsoleColor.Green; //nastavení tmavě zelené barvy textu
                    Console.Write("Chcete pokračovat další zprávou? [a/n]: ");
                    Console.ResetColor();
                    switch (Console.ReadKey().KeyChar.ToString().ToLower())
                    {
                        default:
                            Console.ForegroundColor = ConsoleColor.Red; //nastavení červené barvy
                            Console.WriteLine("\nNeplatná volba!");
                            break;
                        case "a":
                            validChoice = true;
                            toContinue = true;
                            break;
                        case "n":
                            validChoice = true;
                            toContinue = false;
                            break;
                    }

                    //odřádkování
                    Console.WriteLine();
                }
            }
            //výzva k ukončení aplikace
            Console.ForegroundColor = ConsoleColor.DarkCyan; //nastavení tyrkysové barvy textu
            Console.WriteLine("\nDěkuji za použití aplikace MORSE CODE. Aplikaci ukončíte stiskem libovolné klávesy.");

            //čekání na stisk klávesy
            Console.ReadKey();
        }
    }
}
Odpovědět
21. března 22:28
S úsměvem jde všechno lépe :-)
Avatar
Odpovídá na Václav Dachs
Václav Dachs:22. března 8:36

Koukám, že jsem přehlédl nějaké chybky v komentářích, které vznikly, když mi do jejich psaní zasahoval synátor :-) no co už :-P

Odpovědět
22. března 8:36
S úsměvem jde všechno lépe :-)
Avatar
Odpovídá na David Holohlavský
Václav Dachs:6. dubna 21:28

Já výpis zubatého pole řešil takto:

//deklarace a inicializace zubatého pole
int[][] zubatePole = new int[][] {
   new int[] {15,2,8,5,3},
   new int[] {3,3,7},
   new int[] {9,1,16,13},
   new int[] {},
   new int[] {5}
};

//výpis zubatého pole vodorovně
Console.WriteLine("\nVýpis zubatého pole:");
for (int i = 0; i < zubatePole.Length; i++) { //zubatePole.Length vrátí počet polí v poli
   //výpis obsahu každého pole v poli
   Console.Write($"Sloupec {i}:");
   for (int j = 0; j < zubatePole[i].Length; j++) //zubatePole[i].Length vrátí počet položek v aktuálním poli
      Console.Write(zubatePole[i][j].ToString().PadLeft(3)); //výpis položky
   Console.WriteLine(); //odřádkování
}
Odpovědět
6. dubna 21:28
S úsměvem jde všechno lépe :-)
Avatar
Odpovídá na David Holohlavský
Václav Dachs:6. dubna 22:08

případně ještě výpis pole svisle:

//deklarace a inicializace zubatého pole
int[][] zubatePole = new int[][] {
   new int[] {15,2,8,5,3},
   new int[] {3,3,7},
   new int[] {9,1,16,13},
   new int[] {},
   new int[] {5}
};

Console.WriteLine("\nVýpis zubatého pole svisle:");
int zarovnani = 5;
//zjištění indexu nejdelšího pole v poli
int index = 0;
for (int i = 0; i < zubatePole.Length; i++) {
   if (zubatePole[i].Length > index)
      index = i;
}
//výpis
for (int j = 0; j < zubatePole[index].Length; j++) {
   for (int i = 0; i < zubatePole.Length; i++) {
      if (j < zubatePole[i].Length)
         Console.Write(zubatePole[i][j].ToString().PadLeft(zarovnani));
      else {
         for (int k = 0; k < zarovnani; k++)
            Console.Write(" ");
      }
   }
   Console.WriteLine();
}

//ukončení aplikace
Console.ReadKey();
Odpovědět
6. dubna 22:08
S úsměvem jde všechno lépe :-)
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 30 zpráv z 30.