Jak snadno pracovat

s řetězci?

Řetězce a znaky aneb všechno jsou to čísla

Co jsou to řetězce?

Vedle možnosti pamatovat si v průběhu programu čísla (normální číselné proměnné) naprostá většina programovacích jazyků nabízí i prostředky, jak si zapamatovat kus textu. A jeden takový zapamatovaný kus textu se obecně nazývá textový řetězec.

Počítače ale samozřejmě nic jako text nechápou. Řetězce proto berou jako pole znaků. A znaky? Znaky jsou jako všechno v počítačích prostě čísla.

Pomineme-li hodně zajímavých, ale pro naše úlohy naprosto zbytečných, složitostí ohledně různých kódování (mapování znaků na čísla), tak si můžeme představit, že pro anglickou abecedu (a několik normálních znaků jako čárky tečky a tak) platí následující. Jeden znak – jak jej chápe počítač – vždy odpovídá znaku, jak jej chápeme i my.

Pro znaky mimo anglickou abecedu je situace trochu složitější. V závislosti na kódování může být jedno písmeno, jak jej chápeme my, složené klidně z několika znaků. Tak jej bude chápat většina programovacích jazyků.

Řetězce jako čísla

Řetězec "Ahoj Petre." tedy většina programovacích jazyků chápe jako pole čísel, kde první hodnota odpovídá číselné reprezentaci písmena "A", druhé reprezentaci "h", a tak dále.

V některých jazycích (například C-čku) odpovídá zakódovaný řetězec poli, které je o jedna delší než původní text. Poslední znak je pak takzvaná ukončovací nula, aby bylo poznat, kde řetězec v paměti končí.

V jiných (třeba C#, Java, Python) řetězec není čisté pole, ale složitější struktura, která si svojí délku pamatuje někde vedle.

To je ovšem zase detail, který pro naše potřeby není důležitý. Nám bohatě stačí, že řetězec z písmen anglické abecedy, odpovídá poli čísel. A ne ledajakých čísel. Prakticky vždy se můžeme spolehnout, že písmeno 'b' bude odpovídat číslu o jedna vyššímu než písmeno 'a'. Stejně tak písmeno 'Z' číslu o 25 většímu než 'A'.

O moc víc logiky v kódování bohužel nenalezneme. Už tak nemusí platit, že na sebe třeba čísla velkých a malých písmen navazují.

Ukázky v programovacích jazycích

Pro zjištění jestli je např. třetí znak ze vstupu písmeno anglické abecedy a pokud je, tak vypsání znaku těsně následujícím, musíme udělat něco takového:

Python
nasRetezec = input()

nasZnak = nasRetezec[2]
cisloNasehoZnaku = ord(nasZnak)

cislo_a = ord('a')
cislo_z = ord('z')
cislo_A = ord('A')
cislo_Z = ord('Z')

if (cisloNasehoZnaku >= cislo_a and cisloNasehoZnaku <= cislo_z)
  or (cisloNasehoZnaku >= cislo_A and cisloNasehoZnaku <= cislo_Z):
     print(chr(cisloNasehoZnaku + 1)) 
Javascript
const nasRetezec = prompt("Zadejte řetězec:");
const cisloNasehoZnaku = nasRetezec.charCodeAt(2);

const cislo_a = 'a'.charCodeAt(0);
const cislo_z = 'z'.charCodeAt(0);
const cislo_A = 'A'.charCodeAt(0);
const cislo_Z = 'Z'.charCodeAt(0);

if ((cisloNasehoZnaku >= cislo_a && cisloNasehoZnaku <= cislo_z)
|| (cisloNasehoZnaku >= cislo_A && cisloNasehoZnaku <= cislo_Z))
    output = String.fromCharCode(cisloNasehoZnaku + 1);
C#
string nasRetezec = Console.ReadLine();
char nasZnak = nasRetezec[2];
byte cisloNasehoZnaku = (byte)nasZnak;

byte cislo_a = (byte)'a';
byte cislo_z = (byte)'z';
byte cislo_A = (byte)'A';
byte cislo_Z = (byte)'Z';

if ((cisloNasehoZnaku >= cislo_a && cisloNasehoZnaku <= cislo_z) ||
    (cisloNasehoZnaku >= cislo_A && cisloNasehoZnaku <= cislo_Z))
  {
     Console.WriteLine((char)(cisloNasehoZnaku + 1));
  }
C++
#include <string>
#include <iostream>

...

string nasRetezec;
getline(std::cin, nasRetezec);

char nasZnak = nasRetezec[2];

if ((nasZnak >= 'a' && nasZnak <= 'z') || (nasZnak >= 'A' && nasZnak <= 'Z'))
std::cout << (char) (nasZnak + 1) << std::endl;
Java
BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
String nasRetezec = buffer.readLine();

char nasZnak = nasRetezec.charAt(2);
int cisloNasehoZnaku = nasZnak;

int cislo_a = 'a';
int cislo_z = 'z';
int cislo_A = 'A';
int cislo_Z = 'Z';

if ((cisloNasehoZnaku >= cislo_a && cisloNasehoZnaku <= cislo_z)
      || (cisloNasehoZnaku >= cislo_A && cisloNasehoZnaku <= cislo_Z)) {
      System.out.println((char)(cisloNasehoZnaku + 1));
   }

C

size_t n = 0;
char * nasRetezec = NULL, nasZnak;

if (getline(&nasRetezec, &n, stdin) > 2) {
  nasZnak = nasRetezec[2];

  if ((nasZnak >= 'a' && nasZnak <= 'z')
  || (nasZnak >= 'A' && nasZnak <= 'Z'))
  printf("%c\n", nasZnak + 1);
}

free(nasRetezec);

Pozn.: V některých jazycích (třeba C#) je explicitní převod ze znaku na číslo zbytečný. Znaky v nich totiž jdou s čísly porovnávat přímo (např. 'a' < 'c' či 'a' < 100) a někdy je možné je přičtením čísla bez explicitního přetypování i posunout. Tím, že do kódu převod napíšete přímo, ale nikdy nic nezkazíte.

Máš na to!

I ty můžeš vyhrát! Nebo to aspoň zkusit :)