Files

index.md

Bonus - Řetězce

Zatím jsme se zařízením po nahrání programu komunikovali jednostranně: pomocí #!ts console.log() jsme vypisovali různé věci na výstup, a ten jsme sledovali pomocí příkazu Monitor.

Na to, abychom za běhu mohli posílat informace do zařízení, potřebujeme nový datový typ: řetězce.

Řetězce jsou sekvence znaků, a umožňují nám předávat informace. Datový typ, který drží řetězec, se jmenuje #!ts string.

  • Řetězec je vždy uzavřený do uvozovek #!ts "", '' nebo `` ts let str : string = "ahoj"; // vytvoří řetězec
  • Řetězce můžeme spojovat pomocí #!ts +

    let str : string = "ahoj" + " " + "jak se máš?"; // vytvoří řetězec "ahoj jak se máš?" let answer : string = "dobře"; let str2 : string = "ahoj " + answer; // ahoj dobře
  • Speciálním případem jsou formátovací řetězce, kam se dosadí hodnota proměnné ts //! pozor jiné uvozovky let str3 : string = `ahoj ${answer}`; // ahoj dobře
  • Když spojíme řetězec s číslem, číslo se automaticky převede na řetězec a spojí se stejným způsobem

    let str4 : string = answer + " " + 5; // dobře 5 let num : number = 5; let str5 : string = "Je mi " + number + " let";

??? warning "Automatický převod na řetězec" Sčítání řetězců a čísel nefunguje ve všech jazycích, jde o chování specifické pro TypeScript(JavaScript) a pár podobných jazyků. Nenechte se zaskočit tím, jak se to chová: ts let result : string = "5 + 1 je: " + 5 + 1; V result bude "5 + 1 je: 51"!

5 se přidá do řetězce, a poté se tam přidá 1, nesečtou se předem.

Stejně jako ostatní typy je můžeme předávat do funkcí a vracet:

function greetName(name: string) : void { console.log("Ahoj " + name); }

Na dnešní cvičení si opět můžeme stáhnout zip.

Zadání A

Nejdříve se vrátíme k funkci console.log(), díky které jsme vypisovali různé hodnoty. Tato funkce bere jako argument řetězec; pokud argument není řetězec, předem definovaným způsobem se na řetězec automaticky převede.

Jako první úkol si vyzkoušíme spojit řetězec a číslo s tím, co už známe:

Napíšeme program, který při stisku tlačítka vypíše na výstup "Senzor naměřil X.", kde X je aktuální hodnota naměřená z ADC převodníku.

??? note "Řešení" ```ts import * as gpio from "gpio"; import * as adc from "adc";

const BTN_LEFT = 2;

const SENSORPIN: number = 4; const LIGHTNPIN: number = 47;

gpio.pinMode(BTN_LEFT, gpio.PinMode.INPUT);

adc.configure(SENSOR_PIN);

gpio.pinMode(LIGHTNPIN, gpio.PinMode.OUTPUT); gpio.write(LIGHTNPIN, 1);

gpio.on("falling", BTNLEFT, () => { console.log("Senzor naměřil " + adc.read(SENSORPIN) + "."); }); ```

Čtení ze vstupu

Aby komunikace se zařízením nebyla pouze jednostranná, a my mohli z počítače posílat nové příkazy za běhu, použijeme přiložený program readline. Podobně jako v případu LED pásku musíme vytvořit hodnotu typu readline pomocí #!ts const reader = new readline(false).

Jakmile máme vytvořený objekt typu readline, pomocí await reader.read() počkáme na vstup. Jelikož jde o speciální funkci, můžeme ji volat pouze z nové funkce, která je označena jako async function.

??? info "Ukázka práce s řetězcem s readline" ```ts import { stdout } from "stdio"; import { readline } from "./libs/readline.js";

//* řetězce async function echo() { stdout.write("Napiš nějaký text a stiskni enter.\n"); const reader = new readline(false); // vytvoří novou instanci třídy readline while (true) { // opakuje se donekonečna const line = await reader.read(); // přečte řádek z konzole stdout.write("Zadal jsi: " + line + "\n"); // vypíše řádek na konzoli stdout.write(Druhá možnost výpisu: Zadal jsi: ${line}\n); // vypíše řádek na konzoli

    if (line == "konec") {  // pokud je řádek roven "konec"
        stdout.write("Ukončuji.\n");  // vypíše text na konzoli
        break;  // ukončí cyklus
    }
}
reader.close();  // ukončí čtení z konzole

}

echo(); // zavolá funkci echo ```

??? info "Pro zájemce: Async a await" Funkce, které známe doteď, vykonávaly všechny příkazy hned, v pořadí tak, jak jsou po sobě napsané. Funkce, které čekají na nějaký vstup od uživatele, označujeme jako asynchronní (async). Funkce reader.read() po spuštění čeká na textový vstup od uživatele, a mezitím se můžou vykonávat ostatní události. Když před funkci dáme await, značíme tak, že čekáme na výsledek, a další řádek kódu se vykoná až když na vstup přijde řetězec zakončený novým řádkem.

Zadání B

Napíšeme program, který se zeptá, jak se jmenujeme, a počká na odpověď. Až program dostane odpověď, vypíše na konzoli #!ts Jmenuješ se " a jméno, které jsme mu zadali.

??? note "Řešení" ```ts import { readline } from "./libs/readline.js"

async function askName(){ console.log("Jak se jmenuješ?"); const reader = new readline(false); let name : string = await reader.read(); console.log("Jmenuješ se " + name); }

askName(); ```

Standardní funkce

Každý jazyk nabízí řadu funkcí na práci se řetězci. Můžeme je například převádět na čísla, obracet, měnit znaky, a podobně. Pro nás je zajímavé umět načíst ze vstupu číslo: to můžeme udělat tak, že pomocí funkce read() dostaneme řetězec ze vstupu, a poté na něm zavoláme funkci parseInt(), která nám ho převede na celočíselnou hodnotu.

let str : string = "20"; // Řetězec se znaky pro 20 let num : number = parseInt(str); // Převedeme řetězec na číslo, a můžeme s ním počítat let doubled : number = num * 2; // doubled bude mít hodnotu 40

Výchozí úloha V1

Napište (asynchronní) funkci, která počká na vstup od uživatele, převede ho na číslo, a poté rozsvítí LEDku na desce pomocí colors.rainbow() s hodnotou načteného čísla.

!!! tip "Pro dobrovolníky" Uživatel velice jednoduše narozdíl od počítače může udělat chybu, a napsat číslo, které nepatří do rozsahu pro tuto funkci. Pomocí while cyklu můžeme opakovat dotaz na vstup, dokud uživatel nezadá správnou hodnotu, tedy takovou, která je větší než 0 a menší než 360.

Report a bug