# 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!("{} má {} 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 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::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ť 1–4 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 let znaky: Vec = text.chars().collect(); // ['a', 'h', 'o', 'j'] // N-tý znak let druhy: Option = text.chars().nth(1); // Some('h') // Prvý znak let prvy: Option = text.chars().next(); // Some('a') // Posledný znak let posledny: Option = 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::>().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 { 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 = "nie_cislo".parse(); // Err(...) // Bezpečné parsovanie let vstup = "42"; match vstup.parse::() { Ok(n) => println!("Číslo: {}", n), Err(_) => println!("Nie je číslo"), } // Alebo s .ok() let cislo: Option = 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` — 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 → 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 (s oddeľovačom) let slova: Vec = vec!["ahoj".into(), "svet".into()]; let text: String = slova.join(", "); // "ahoj, svet" // Iterátor &str → String let text: String = ["ahoj", "svet"].iter().copied().collect::>().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) -> 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 { 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 { 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 ``` **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 String ──.chars()───→ Iterator Iterator ──.collect()──→ String Vec ──.iter().collect()→ String &str ──.parse::()──→ Result T ──.to_string()───────→ String (ak T: Display) &str ──.as_bytes()────→ &[u8] ```