Files
JR-priprava-na-skusku/priprava/rust_priprava8.md
Priec 5182e2f833 str
2026-02-28 23:21:09 +01:00

845 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# String, &str, char — krok za krokom
Každá kapitola: prečítaj, pozri príklady, urob úlohy. Až potom choď ďalej.
---
## Kapitola 1: Čo je čo
V Ruste existujú 3 typy pre prácu s textom:
| Typ | Čo to je | Vlastní dáta? | Veľkosť |
|-----|----------|---------------|---------|
| `String` | Vlastnený, meniteľný reťazec na heape | Áno | Rastie/zmenšuje sa |
| `&str` | Referencia na kúsok textu (string slice) | Nie (len pozerá) | Fixná |
| `char` | Jeden Unicode znak | Áno | 4 bajty vždy |
```rust
// String — vlastní dáta, môžeš meniť
let mut s: String = String::from("ahoj");
s.push_str(" svet"); // OK — je mut a vlastní dáta
// &str — len referencia, nemôžeš meniť obsah
let slice: &str = "ahoj svet";
// slice.push_str("!"); // CHYBA — &str je len pohľad
// char — jeden znak
let c: char = 'a';
let emoji: char = '🦀'; // aj emoji je jeden char
```
**Analógia:**
- `String` je ako vlastný zošit — píšeš doň, pridávaš strany
- `&str` je ako pohľad cez okno na cudzí zošit — vidíš text, ale nemôžeš ho meniť
- `char` je ako jedno písmeno
### Úlohy 1
**1a.** Ktorý typ použiješ v štruktúre? Prečo?
```rust
struct Kniha {
nazov: ???, // String alebo &str?
}
```
**1b.** Čo je zle? Oprav:
```rust
let s: &str = "ahoj";
s.push_str(" svet");
```
**1c.** Aký je typ každej premennej?
```rust
let a = "ahoj";
let b = String::from("ahoj");
let c = 'a';
let d = &b[..];
let e = b.as_str();
```
---
## Kapitola 2: Vytváranie String
Existuje veľa spôsobov ako vytvoriť String:
```rust
// 1. String::from
let s = String::from("ahoj");
// 2. .to_string() — funguje na čomkoľvek s Display
let s = "ahoj".to_string();
let s = 42.to_string(); // "42"
let s = 3.14.to_string(); // "3.14"
let s = true.to_string(); // "true"
// 3. String::new() — prázdny
let s = String::new(); // ""
// 4. format! — ako println!, ale vráti String
let meno = "Anna";
let vek = 25;
let s = format!("{}{} rokov", meno, vek);
// "Anna má 25 rokov"
// 5. .to_owned() — z &str na String
let slice: &str = "ahoj";
let owned: String = slice.to_owned();
// 6. .into() — Rust odvodí konverziu
let s: String = "ahoj".into();
```
**Ktorý použiť:**
- `String::from("...")` alebo `"...".to_string()` — oboje je rovnaké, použi čo sa ti páči
- `format!()` — keď skladáš z viacerých častí
- `String::new()` — keď budeš pridávať postupne
### Úlohy 2
**2a.** Vytvor String z čísla `42`, z boolu `false`, z float `3.14`. Vypíš ich.
**2b.** Máš premenné `meno: &str` a `vek: u32`. Vytvor String vo formáte `"Meno: Anna, Vek: 25"` pomocou `format!`.
**2c.** Vytvor prázdny String a postupne do neho pridaj 3 slová (použi `push_str`). Výsledok vypíš.
---
## Kapitola 3: Konverzie medzi String a &str
```rust
// &str → String (3 spôsoby, všetky robia to isté)
let slice: &str = "ahoj";
let owned1: String = slice.to_string();
let owned2: String = slice.to_owned();
let owned3: String = String::from(slice);
// String → &str (2 spôsoby)
let owned: String = String::from("ahoj");
let slice1: &str = &owned; // automatická dereferencia
let slice2: &str = owned.as_str(); // explicitné
// String → &str v parametroch funkcie — automaticky!
fn prijmi_str(s: &str) {
println!("{}", s);
}
let owned = String::from("ahoj");
prijmi_str(&owned); // String sa automaticky konvertuje na &str
prijmi_str("ahoj"); // &str funguje priamo
```
**Zlaté pravidlo pre funkcie:**
- Parametre píš ako `&str` — prijmeš aj String aj &str
- Návratové hodnoty a polia v štruktúrach píš ako `String` — vlastníš dáta
```rust
// DOBRÉ — parameter &str prijme oboje
fn pozdrav(meno: &str) -> String {
format!("Ahoj, {}!", meno)
}
pozdrav("Anna"); // &str → OK
pozdrav(&String::from("Boris")); // &String → OK
pozdrav(&"Cyril".to_string()); // &String → OK
// ZLÉ — parameter String núti volajúceho robiť konverziu
fn pozdrav_zle(meno: String) -> String {
format!("Ahoj, {}!", meno)
}
// pozdrav_zle("Anna"); // CHYBA — &str nie je String
pozdrav_zle("Anna".to_string()); // musíš konvertovať
```
### Úlohy 3
**3a.** Napíš funkciu `dlzka(text: &str) -> usize` ktorá vráti dĺžku. Zavolaj ju s `&str` aj so `String`.
**3b.** Napíš funkciu `opakuj(text: &str, n: usize) -> String` ktorá vráti text zopakovaný n-krát.
**3c.** Čo je zle? Oprav:
```rust
fn prvych_5(text: String) -> String {
text[..5].to_string()
}
prvych_5("ahoj svet");
```
---
## Kapitola 4: Modifikácia String
String je meniteľný. Tu sú všetky spôsoby ako ho meniť:
### Pridávanie
```rust
let mut s = String::from("ahoj");
// push_str — pridaj &str na koniec
s.push_str(" svet"); // "ahoj svet"
// push — pridaj jeden char
s.push('!'); // "ahoj svet!"
// + operátor — spája String + &str (konzumuje prvý!)
let a = String::from("ahoj");
let b = String::from(" svet");
let c = a + &b; // c = "ahoj svet", a JE ZKONZUMOVANÝ!
// println!("{}", a); // CHYBA — a bolo presunuté do c
// format! — bezpečná konkatenácia (nekonzumuje nič)
let a = String::from("ahoj");
let b = String::from("svet");
let c = format!("{} {}", a, b); // c = "ahoj svet"
println!("{}", a); // OK — a stále existuje
```
### Mazanie
```rust
let mut s = String::from("ahoj svet");
// clear — vymaž všetko
s.clear(); // ""
let mut s = String::from("ahoj svet");
// truncate — skráť na N bajtov
s.truncate(4); // "ahoj"
let mut s = String::from("ahoj");
// pop — odstráň posledný char, vráti Option<char>
let posledny = s.pop(); // Some('j'), s = "aho"
```
### Nahradenie
```rust
let s = String::from("ahoj svet ahoj");
// replace — nahraď všetky výskyty (vráti nový String)
let novy = s.replace("ahoj", "čau");
// "čau svet čau"
// replacen — nahraď len prvých N výskytov
let novy = s.replacen("ahoj", "čau", 1);
// "čau svet ahoj"
```
**Dôležité:** `replace` vracia nový String, nemení pôvodný.
### Úlohy 4
**4a.** Vytvor String `"Rust je super"`. Pridaj na koniec `" jazyk!"`. Pridaj na koniec `'🦀'`. Vypíš výsledok.
**4b.** Máš String `"ahoj_svet_rust"`. Nahraď všetky `_` medzerou. Vypíš.
**4c.** Máš String. Postupne z neho popuj znaky kým nie je prázdny. Každý vypíš.
**4d.** Čo je zle? Oprav (2 spôsoby):
```rust
let a = String::from("ahoj");
let b = String::from(" svet");
let c = a + &b;
println!("{}", a); // chyba!
```
---
## Kapitola 5: char — jeden znak
`char` v Ruste je 4 bajty a reprezentuje jeden Unicode bod (nie bajt!).
```rust
let c: char = 'a';
let emoji: char = '🦀';
let slovak: char = 'ž';
// Kontroly
c.is_alphabetic(); // true — je písmeno?
c.is_numeric(); // false — je číslica?
c.is_alphanumeric(); // true — písmeno alebo číslica?
c.is_uppercase(); // false
c.is_lowercase(); // true
c.is_whitespace(); // false — je medzera/tab/newline?
c.is_ascii(); // true — je ASCII (0-127)?
// Konverzia veľkosť
c.to_uppercase(); // iterátor! nie char (lebo 'ß' → "SS")
c.to_lowercase(); // iterátor!
c.to_ascii_uppercase(); // char — len pre ASCII znaky
c.to_ascii_lowercase(); // char
// char → String
let s: String = c.to_string(); // "a"
let s: String = String::from(c); // "a"
// char → u32 (Unicode code point)
let kod: u32 = c as u32; // 97
// u32 → char (ak je platný Unicode)
let c: Option<char> = char::from_u32(97); // Some('a')
```
**Dôležité o to_uppercase/to_lowercase:**
```rust
// to_uppercase vráti iterátor, nie char!
// Lebo niektoré znaky sa mapujú na viac znakov: ß → SS
let velke: String = 'a'.to_uppercase().collect(); // "A"
let velke: String = 'ß'.to_uppercase().collect(); // "SS"
// Pre jednoduché ASCII použi to_ascii_uppercase — vráti char
let velke: char = 'a'.to_ascii_uppercase(); // 'A'
```
### Úlohy 5
**5a.** Napíš funkciu `je_samohláska(c: char) -> bool` — true pre a, e, i, o, u (aj veľké). Použi `to_ascii_lowercase()` a `matches!` alebo porovnávanie.
**5b.** Napíš funkciu `pocet_cifier(text: &str) -> usize` — koľko znakov v texte sú číslice. Použi `.chars()` a `.is_numeric()`.
**5c.** Napíš funkciu `velkymi(text: &str) -> String` — celý text veľkými písmenami. Použi `.chars()`, `.to_ascii_uppercase()`, `.collect()`.
**5d.** Čo vráti?
```rust
println!("{}", 'A'.is_uppercase());
println!("{}", '5'.is_numeric());
println!("{}", ' '.is_whitespace());
println!("{}", 'ž'.is_ascii());
println!("{}", 'ž'.is_alphabetic());
```
---
## Kapitola 6: Iterácia cez znaky — chars()
String v Ruste je UTF-8. Jeden znak môže byť 14 bajty. Preto nemôžeš indexovať `s[0]` — nevieš koľko bajtov má znak.
```rust
let text = "ahoj";
// chars() — iterátor cez char hodnoty
for c in text.chars() {
println!("{}", c); // a, h, o, j
}
// Počet znakov
let pocet: usize = text.chars().count(); // 4
// Do Vec<char>
let znaky: Vec<char> = text.chars().collect();
// ['a', 'h', 'o', 'j']
// N-tý znak
let druhy: Option<char> = text.chars().nth(1); // Some('h')
// Prvý znak
let prvy: Option<char> = text.chars().next(); // Some('a')
// Posledný znak
let posledny: Option<char> = text.chars().last(); // Some('j')
```
**Pozor na .len() vs .chars().count():**
```rust
let text = "žaba";
println!("{}", text.len()); // 5 (bajtov! 'ž' = 2 bajty)
println!("{}", text.chars().count()); // 4 (znakov)
// Pre čisto ASCII texty sú rovnaké
let text = "ahoj";
println!("{}", text.len()); // 4
println!("{}", text.chars().count()); // 4
```
### chars() s iterátorovými metódami
```rust
let text = "Ahoj Svet 123";
// filter — len písmená
let pismena: String = text.chars().filter(|c| c.is_alphabetic()).collect();
// "AhojSvet"
// map — na veľké
let velke: String = text.chars().map(|c| c.to_ascii_uppercase()).collect();
// "AHOJ SVET 123"
// any — obsahuje číslicu?
let ma_cislo: bool = text.chars().any(|c| c.is_numeric());
// true
// all — sú všetky písmená?
let vsetky_pismena: bool = text.chars().all(|c| c.is_alphabetic());
// false
// enumerate — index + znak
for (i, c) in text.chars().enumerate() {
println!("{}: {}", i, c);
}
// take — prvých N znakov
let prvych_4: String = text.chars().take(4).collect();
// "Ahoj"
// skip — preskoč prvých N znakov
let od_5: String = text.chars().skip(5).collect();
// "Svet 123"
```
### Úlohy 6
**6a.** Napíš funkciu `prevrat(text: &str) -> String` — obráti text. Použi `.chars().rev().collect()`.
**6b.** Napíš funkciu `je_palindrom(text: &str) -> bool` — true ak sa text rovná sám sebe pozadu. Ignoruj veľkosť písmen.
**6c.** Napíš funkciu `censuruj(text: &str, zakazane: &[char]) -> String` — nahraď zakázané znaky hviezdičkou `'*'`. Použi `.chars().map().collect()`.
**6d.** Napíš funkciu `prvych_n_znakov(text: &str, n: usize) -> String`. Použi `.chars().take(n).collect()`.
**6e.** Napíš funkciu `pocet_slov(text: &str) -> usize`. Použi `.split_whitespace().count()`.
---
## Kapitola 7: Rozdeľovanie reťazcov — split, lines, split_whitespace
### split_whitespace — rozdeľ podľa medzier
```rust
let text = " ahoj svet rust ";
let slova: Vec<&str> = text.split_whitespace().collect();
// ["ahoj", "svet", "rust"] — medzery na okrajoch a duplikáty ignorované
```
### split — rozdeľ podľa oddeľovača
```rust
let text = "anna,boris,cyril";
// Podľa znaku
let mena: Vec<&str> = text.split(',').collect();
// ["anna", "boris", "cyril"]
// Podľa reťazca
let text = "ahoj--svet--rust";
let casti: Vec<&str> = text.split("--").collect();
// ["ahoj", "svet", "rust"]
// splitn — maximálne N častí
let text = "a:b:c:d:e";
let casti: Vec<&str> = text.splitn(3, ':').collect();
// ["a", "b", "c:d:e"] — rozdelí len na prvých 2 dvojbodkách
```
### lines — rozdeľ podľa riadkov
```rust
let text = "prvý riadok\ndruhý riadok\ntretí riadok";
for riadok in text.lines() {
println!("{}", riadok);
}
// prvý riadok
// druhý riadok
// tretí riadok
```
### Úlohy 7
**7a.** Máš CSV riadok `"Anna,25,Bratislava"`. Rozdeľ ho na časti. Vypíš meno, vek, mesto.
**7b.** Napíš funkciu `pocet_slov(text: &str) -> usize`. Použi `split_whitespace`.
**7c.** Máš viacriadkový text. Nájdi najdlhší riadok. Použi `.lines()` a `.max_by_key()`.
**7d.** Máš cestu `"/home/user/docs/file.txt"`. Rozdeľ podľa `/`. Vypíš posledný kúsok (filename).
---
## Kapitola 8: Hľadanie v reťazcoch
```rust
let text = "Ahoj svet, ahoj Rust!";
// contains — obsahuje podreťazec?
text.contains("svet"); // true
text.contains("Python"); // false
// starts_with / ends_with
text.starts_with("Ahoj"); // true
text.ends_with("!"); // true
text.ends_with("Rust"); // false (končí na "!")
// find — index prvého výskytu (v bajtoch!)
text.find("svet"); // Some(5)
text.find("Python"); // None
// rfind — od konca
text.rfind("ahoj"); // Some(11)
// matches — iterátor cez všetky výskyty
let pocet = text.matches("ahoj").count(); // 1 (case-sensitive!)
let pocet = text.to_lowercase().matches("ahoj").count(); // 2
```
### Úlohy 8
**8a.** Napíš funkciu `obsahuje_cislicu(text: &str) -> bool` — true ak text obsahuje aspoň jednu číslicu. Použi `.chars().any()`.
**8b.** Napíš funkciu `pocet_vyskytu(text: &str, hladany: &str) -> usize`. Použi `.matches().count()`.
**8c.** Napíš funkciu `zacina_velkym(text: &str) -> bool` — true ak prvý znak je veľké písmeno.
**8d.** Máš vektor reťazcov. Vyfiltruj len tie, ktoré obsahujú slovo "rust" (case-insensitive).
---
## Kapitola 9: Trimovanie a padding
### trim — odstráň biele znaky z okrajov
```rust
let text = " ahoj svet \n";
text.trim(); // "ahoj svet"
text.trim_start(); // "ahoj svet \n"
text.trim_end(); // " ahoj svet"
// trim_matches — odstráň konkrétne znaky
let text = "---ahoj---";
text.trim_matches('-'); // "ahoj"
let text = "***ahoj***svet***";
text.trim_matches('*'); // "ahoj***svet" (len okraje!)
```
### Padding / zarovnanie (nie metóda, ale format!)
```rust
let meno = "Anna";
// Zarovnanie vpravo (šírka 10)
let s = format!("{:>10}", meno); // " Anna"
// Zarovnanie vľavo
let s = format!("{:<10}", meno); // "Anna "
// Na stred
let s = format!("{:^10}", meno); // " Anna "
// S vlastným znakom
let s = format!("{:*>10}", meno); // "******Anna"
let s = format!("{:-^10}", meno); // "---Anna---"
```
### Úlohy 9
**9a.** Máš vstup od používateľa `" ahoj \n"`. Očisti ho trimom. Potom over, či je "ahoj".
**9b.** Máš vektor mien rôznej dĺžky. Vypíš ich zarovnané vpravo na šírku 15 znakov:
```
Anna
Boris
Cyril
```
**9c.** Napíš funkciu `ocisti(text: &str) -> String` — trim + nahraď viacnásobné medzery jednou. Hint: `split_whitespace().collect::<Vec<&str>>().join(" ")`.
---
## Kapitola 10: Slicing — &str z časti String
Môžeš vziať kúsok reťazca ako &str. Ale **pozor** — indexy sú v bajtoch, nie znakoch!
```rust
let text = "ahoj svet";
// Slice podľa rozsahu bajtov
let slice: &str = &text[0..4]; // "ahoj"
let slice: &str = &text[5..]; // "svet"
let slice: &str = &text[..4]; // "ahoj"
// NEBEZPEČNÉ pre non-ASCII!
let text = "žaba";
// &text[0..1] // PANIC! 'ž' je 2 bajty, toto by rozdelilo uprostred znaku!
// &text[0..2] // OK — "ž"
```
**Bezpečný spôsob pre ľubovoľný text:**
```rust
// Použi chars() namiesto slicingu
fn prvy_znak(text: &str) -> Option<char> {
text.chars().next()
}
fn prvych_n(text: &str, n: usize) -> String {
text.chars().take(n).collect()
}
fn od_znaku_n(text: &str, n: usize) -> String {
text.chars().skip(n).collect()
}
fn podretazec(text: &str, od: usize, do_: usize) -> String {
text.chars().skip(od).take(do_ - od).collect()
}
```
**Kedy je slice bezpečný:**
- Ak vieš, že text je čistý ASCII (anglická abeceda, čísla)
- Ak index získaš z `.find()` (ten vracia bajtový index)
```rust
let text = "ahoj svet rust";
if let Some(pos) = text.find("svet") {
let od_svet: &str = &text[pos..]; // "svet rust" — bezpečné, find vrátil správny index
}
```
### Úlohy 10
**10a.** Máš ASCII text `"Hello World"`. Vyber prvých 5 znakov slicingom. Vyber posledných 5.
**10b.** Napíš funkciu `bezpecne_prvych_n(text: &str, n: usize) -> String` — vráti prvých N znakov bez paniki (aj pre non-ASCII).
**10c.** Máš text. Nájdi pozíciu prvej medzery pomocou `.find(' ')`. Ak existuje, vráť prvé slovo ako &str slice:
```rust
fn prve_slovo(text: &str) -> &str
```
**10d.** Prečo toto panikne? Ako to opravíš?
```rust
let text = "café";
let slice = &text[0..4];
```
---
## Kapitola 11: Parsovanie — z reťazca na iné typy
```rust
// &str / String → číslo (.parse())
let cislo: i32 = "42".parse().unwrap(); // 42
let cislo: f64 = "3.14".parse().unwrap(); // 3.14
let cislo: Result<i32, _> = "nie_cislo".parse(); // Err(...)
// Bezpečné parsovanie
let vstup = "42";
match vstup.parse::<i32>() {
Ok(n) => println!("Číslo: {}", n),
Err(_) => println!("Nie je číslo"),
}
// Alebo s .ok()
let cislo: Option<i32> = vstup.parse().ok();
// číslo → String
let text: String = 42.to_string();
let text: String = format!("{}", 42);
// bool
let b: bool = "true".parse().unwrap(); // true
let b: bool = "false".parse().unwrap(); // false
```
### Úlohy 11
**11a.** Napíš funkciu `parsuj_cisla(text: &str) -> Vec<i32>` — text obsahuje čísla oddelené čiarkami (`"1,2,3,4,5"`). Rozdeľ a sparsuj. Ignoruj neplatné hodnoty.
**11b.** Napíš funkciu `parsuj_csv_riadok(riadok: &str) -> Option<(String, u32, f64)>`:
Vstup: `"Anna,25,1.5"``Some(("Anna".to_string(), 25, 1.5))`
Ak parsovanie zlyhá → None.
**11c.** Máš vstup od používateľa (String). Trim ho, parsuj na u32. Ak sa nepodarí, vyskúšaj f64. Ak ani to, vráť chybu.
---
## Kapitola 12: Pokročilé operácie
### repeat — opakuj reťazec
```rust
let s = "ha".repeat(3); // "hahaha"
let s = "-".repeat(20); // "--------------------"
```
### to_lowercase / to_uppercase
```rust
let text = "Ahoj Svet";
let male: String = text.to_lowercase(); // "ahoj svet"
let velke: String = text.to_uppercase(); // "AHOJ SVET"
// Porovnanie case-insensitive
fn rovnake_ci(a: &str, b: &str) -> bool {
a.to_lowercase() == b.to_lowercase()
}
rovnake_ci("Ahoj", "AHOJ"); // true
```
### char_indices — indexy aj znaky
```rust
let text = "žaba";
// char_indices dáva (bajtový_index, char)
for (i, c) in text.char_indices() {
println!("bajt {}: {}", i, c);
}
// bajt 0: ž
// bajt 2: a (ž zabrala 2 bajty!)
// bajt 3: b
// bajt 4: a
```
### Collect medzi typmi
```rust
// Vec<char> → String
let znaky = vec!['a', 'h', 'o', 'j'];
let text: String = znaky.into_iter().collect();
// "ahoj"
// Vec<&str> → String (s oddeľovačom)
let slova = vec!["ahoj", "svet"];
let text: String = slova.join(" ");
// "ahoj svet"
// Vec<String> → String (s oddeľovačom)
let slova: Vec<String> = vec!["ahoj".into(), "svet".into()];
let text: String = slova.join(", ");
// "ahoj, svet"
// Iterátor &str → String
let text: String = ["ahoj", "svet"].iter().copied().collect::<Vec<&str>>().join(" ");
// S itertools je jednoduchšie:
// use itertools::Itertools;
// let text = ["ahoj", "svet"].iter().join(" ");
```
### Úlohy 12
**12a.** Napíš funkciu `oddelovac(sirka: usize) -> String` — vráti riadok pomlčiek danej šírky.
**12b.** Napíš funkciu `kapitalizuj(text: &str) -> String` — prvé písmeno veľké, zvyšok malé. Hint: `.chars().next()` pre prvé, `.chars().skip(1)` pre zvyšok.
**12c.** Napíš funkciu `snake_to_camel(text: &str) -> String` — preveď `"ahoj_svet_rust"` na `"AhojSvetRust"`. Hint: split podľa `_`, každé slovo kapitalizuj, spoj.
**12d.** Napíš funkciu `je_platny_email(text: &str) -> bool`:
- Obsahuje presne jednu `@`
- Pred `@` je aspoň 1 znak
- Za `@` je aspoň 3 znaky
- Za `@` obsahuje `.`
---
## Kapitola 13: Vzory zo skúšky
### Vzor 1: Display pre štruktúru/enum
```rust
use std::fmt;
enum Stav { Novy, Aktivny, Dokonceny }
impl fmt::Display for Stav {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Stav::Novy => write!(f, "Nový"),
Stav::Aktivny => write!(f, "Aktívny"),
Stav::Dokonceny => write!(f, "Dokončený"),
}
}
}
struct Uloha { nazov: String, stav: Stav }
impl fmt::Display for Uloha {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} [{}]", self.nazov, self.stav)
}
}
// Výstup: "Upratovanie [Nový]"
```
### Vzor 2: Obesenec — zobrazenie skrytého slova
```rust
fn zobraz_slovo(slovo: &str, uhadnute: &HashSet<char>) -> String {
slovo.chars().map(|c| {
if uhadnute.contains(&c) { c } else { '_' }
}).collect()
}
// zobraz_slovo("ahoj", &{'a', 'o'}) → "a_o_"
```
### Vzor 3: Parsovanie vstupu od používateľa
```rust
fn nacitaj_cislo() -> Option<u32> {
let mut vstup = String::new();
std::io::stdin().read_line(&mut vstup).ok()?;
vstup.trim().parse().ok()
}
```
### Vzor 4: CSV / JSON parsovanie
```rust
fn parsuj_knihu(riadok: &str) -> Option<Kniha> {
let casti: Vec<&str> = riadok.split(',').collect();
if casti.len() != 3 { return None; }
let rok: u16 = casti[2].trim().parse().ok()?;
Some(Kniha {
nazov: casti[0].trim().to_string(),
autor: casti[1].trim().to_string(),
rok,
})
}
```
### Úlohy 13
**13a.** Implementuj `Display` pre enum `Priorita { Nizka, Stredna, Vysoka }` — výstup: "Nízka", "Stredná", "Vysoká".
**13b.** Implementuj `Display` pre štruktúru `Zamestnanec { meno: String, pozicia: String, plat: u32 }` vo formáte `"Anna (Programátor) - 3000€"`.
**13c.** Napíš funkciu, ktorá načíta riadok z stdin, trimne ho a vráti. Ak je prázdny po trime, vráti None:
```rust
fn nacitaj_riadok() -> Option<String>
```
**13d.** Napíš funkciu, ktorá sparsuje text `"meno:vek:mesto"` na tuple:
```rust
fn parsuj(text: &str) -> Option<(String, u32, String)>
```
---
## Prehľad konverzií
```
&str ──.to_string()──→ String
&str ──.to_owned()───→ String
&str ──String::from()─→ String
String ──&──────────→ &str
String ──.as_str()──→ &str
char ──.to_string()─→ String
char ──String::from()→ String
&str ──.chars()─────→ Iterator<char>
String ──.chars()───→ Iterator<char>
Iterator<char> ──.collect()──→ String
Vec<char> ──.iter().collect()→ String
&str ──.parse::<T>()──→ Result<T, Error>
T ──.to_string()───────→ String (ak T: Display)
&str ──.as_bytes()────→ &[u8]
```