Přeskočit obsah

Lekce 8 - Řetězce¤

Zatím jsme se zařízením po nahrání programu komunikovali jednostranně: pomocí 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 string.

  • Řetězec je vždy uzavřený do uvozovek "", '' nebo ``
    let str : string = "ahoj";  // vytvoří řetězec
    
  • Řetězce můžeme spojovat pomocí +
    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é
    //! 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";
    
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á:

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 "Potenciometr naměřil X.", kde X je aktuální hodnota naměřená z POT0.

Řešení
import * as gpio from "gpio";
import * as adc from "adc";


const BTN_LEFT = 18;

const POT0_PIN = 2;

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

adc.configure(POT0_PIN);

gpio.on("falling", BTN_LEFT, () => {
    console.log("Potenciometr naměřil " + adc.read(POT0_PIN) + ".");
});

Č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í 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.

Ukázka práce s řetězcem s readline
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
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 Jmenuješ se " a jméno, které jsme mu zadali.

Řešení
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.

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.