#9 Práce s textem

Právě dnes Vám přinášíme další díl našeho kurzu programování v jazyce C. V této lekci se budeme zabývat řetězci, zejména používání vestavěných funkcí pro práci s textem, kterých není málo a proto si ukážeme jen ty nejpoužívanější nebo spíše nejužitečnější pro základní práci s řetězci.

Poprvé jsme se o řetězcích zmínili v 6. lekci, kde jsme si ukázali jejich deklaraci, vstup do programu a následné vypsání. Nyní si informace o řetězcích trochu rozšíříme.

Charakteristika řetězců

Jak jsme si již definovali v předešlé lekci (6. lekce), že řetězec je posloupnost znaků. V jazyce C bývají zapsané jako pole znaků (charů). Každý řetězec je ukončen tzv. Binární nulou. Právě díky ukončovací nule si nemusíme pamatovat velikost pole. Pole znaků procházíme pouze do výskytu ukončovací nuly. Je možné nulu posouvat na nižší úroveň v poli, čímž se řetězec zkracuje. Znaky za ukončovací nulou nejsou zpravidla dostupná, ale při pokusu o jejich vypsání se zobrazí jakési „smetí“ z paměti.

Deklarace řetězce

char string[10]; //9 znaku + ukoncovaci nula

Pokud při deklaraci rovnou přiřadíme i nějaký řetězec, velikost pole se nastaví podle počtu znaků + ukončovací nula.

char string[] = "text"; //velikost pole = 5

Inicializace řetězce

Rozdíl v inicializaci pole a řetězce:

char str1[]="abc"; //inicializace pomoci retezcove konstanty
char str2[]={'a','b','c'}; //inicializace pole znak po znaku

Druhý zápis nevloží nakonec pole ukončovací nulu. Pro správnost musíme přidat i nulu jako 4. prvek pole.

char str2[]={'a','b','c', 0};

Pokud použijeme funkci scanf pro načtení řetězce tak syntaxe vypadá následovně:

scanf("%s", string);

Víme, že u funkce scanf se k proměnné přidává operátor reference, aby fungovala správně, jelikož proměnná typu řetězec obsahuje adresu tak se tento operátor nepřidává.

Operace s řetězci

char string[] = “Lorem ipsum”;

Vypsání určitého znaku v řetězci lze bud pomocí operátoru hranaté závorky, kde se vypíše daný prvek v poli, nebo pomocí ukazatelové aritmetiky nastavíme ukazatel na konkrétní adresu a pomocí operátoru dereference vypíšeme obsah paměti na této adrese.

printf("%c\n", string[6]);
printf("%c\n", *(string+6));

Můžeme část řetězce vložit do nového, opět za pomoci ukazatele.

char* string2 = string + 6; //string2 = "ipsum"

Můžeme řetězec zkrátit vložením ukončovací nuly. Zapsáni nuly je možné dvěma způsoby, je jedno který zvolíte.

string[5] = 0;
string[5] = '\0';

Pole řetězců

Je to pole kde typ jednotlivého prvku pole je ukazatel na řetězec (char*). Nejčastější použití takového pole je pro řadu konstantních řetězců.

char* OnlineKurzy[] = {"Lekce VBA","Lekce Pascalu","Kurz C","Webdesign"};

Funkce pro práci s řetězci

Nejprve si ukážeme pár důležitých funkcí, které se nacházejí v knihovně string.h

Funkce strlen

Je to velice používaná funkce, která vrací počet znaků v řetězci. Na příkladu vidíme rozdíl mezi sizeof a strlen. V příkladu je i test ukončovací nuly, zda se opravdu v řetězci nachází.

#include <stdio.h>
#include <string.h>

int main(void)
{
    char string[] = "Lorem ipsum";
    printf("%s\n", string);
    printf("sizeof: %d\nstrlen: %d\n",sizeof(string),strlen(string));
    string[5] = '\0'; //vlozime ukoncovaci nulu doprostred retezce
    printf("%s\n", string);
    printf("sizeof: %d\nstrlen: %d\n\n",sizeof(string),strlen(string));

    printf("vypisuju ukoncovaci nulu jako znak:%c(vlozi mezeru)\n", string[11]);
    printf("vypisuju ukoncovaci nulu jako cislo:%d(vlozi cislo)\n", string[11]);

    return 0;
}

Pokud chceme nulu vypsat samostatně jako znak tak se na výpisu objeví mezera, při výpisu celého řetězce se tato mezera neobjeví, jelikož se vypisují pouze znaky před ukončovací nulou.

U funkce strlen opravdu vidíme, že řetězec má délku 11, ale funkce sizeof nám vrací číslo o 1 větší a to proto, že funkce ukazuje kolik je potřeba bytů na uchování tohoto řetězce v paměti. Víme, že na uložení jednoho znaku potřebujeme právě 1 byte a ten 12. byte navíc je právě pro ukončovací nulu.

Funkce strcpy

Slouží k překopírování jednoho řetězce do druhého.

strcpy(retezec1,retezec2);

Dle znázornění se zkopíruje retezec2 do retezce1. Důležité pravidlo pro použití této funkce je, že retezec1 musí být dostatečně velký, aby byl schopen uložit do sebe retezec2.

Funkce strcat

Tato funkce umožňuje spojit dva řetězce v jeden.

char str[256] = "Lorem";
printf("%s\n",strcat(str,"Ipsum"));

Výsledek bude vypadat: LoremIpsum.

Pravidlo pro tuto funkci je, že opět první řetězec musí mít dostatečnou velikost a to: (délka prvního řetězce) + (délka druhého řetězce) + 1 (ukončovací nula)

Funkce strcmp

Pro porovnání dvou řetězců se používá tato funkce.

strcmp(retezec1,retezec2);

Funkce vrací celočíselnou hodnotu:

  • hodnota 0 – vrací, jestliže jsou oba řetězce shodné
  • hodnota >0 – vrací, pokud první řetězec je větší než druhý
  • hodnota <0 – vrací, pokud první řetězec je menší než druhý

Výsledky jsou vyhodnoceny na základě uspořádání znaků v ASCII tabulce. Pokud tedy použijeme toto porovnání:

strcmp("A","a");

Hodnota velkých písmen je v ASCII tabulce před malými písmeny, tudíž funkce vyhodnotí výsledek na záporný.

Funkce strchr

Jedná se o vyhledávací funkci, která zjišťuje, zda řetězec obsahuje hledaný znak.

strchr(retezec,znak);

Pokud se hledaný znak v řetězci nachází potom funkce vrací hodnotu v podobě ukazatele na prvně nalezený znak, v opačném případě vrací hodnotu NULL.

Funkce strstr

Obdobná funkce jako předchozí, akorát s tím rozdílem, že funkce vyhledává, zda se v prvních řetězci nachází řetězec druhý. Pokud se takový řetězec najde, funkce vrací ukazatel na první výskyt řetězce.

Znakové funkce

V následující tabulce si ukážeme několik funkcí, které zjišťují charakteristiku znaku, všechny tyto funkce se nacházejí v knihovně ctype.h. Všechny funkce mají jeden parametr a to znak (char). Návratová hodnota pro všechny funkce je stejná, mohou nastat pouze 2 případy:

  • Funkce vrátí číslo různé od nuly pro PRAVDU
  • Funkce vrátí číslo 0 pro NEPRAVDU
Funkce Popis Znaky 1
isalnum(char) Je znak písmeno nebo číslo? A – Z, a – z, 0 – 9
isalpha(char) Je znak písmeno? A – Z, a – z
isblank(char) Je znak prádný? tabulátor (‚\t‘), mezera (‚ ‚)
iscntrl(char) Je znak řídící? znaky s ASCII hodnotu < 32 a znak s hodnoutou 127
isdigit(char) Je znak číslo? 0 – 9
isgraph(char) Má znak grafické znázornění? 0 – 9, A – Z, a – z, všechny speciální znaky
islower(char) Je znak malé písmeno? a – z
isprint(char) Je znak tisknutelný? mezera, 0 – 9, A – Z, a – z, všechny speciální znaky
ispunct(char) Je znak speciální? !“#$%&'()*+,-./:;<=>?@[\]^_`{|}~
isspace(char) Je znak „bílý“? tabulátor (‚\t‘), mezera (‚ ‚), nový řádek (‚\n‘), návrat vozíku (‚\r‘), vertikální tabulátor (‚\v‘), konec stránky (‚\f‘)
isupper(char) Je znak velké písmeno? A – Z
isxdigit(char) Je znak hexadecimalní číslo? 0 – 9, A – F, a – f

1) Tato položka zobrazuje znaky, u kterých daná funkce vyhodnotí znak na pravdivý

V knihovně ctype.h se nacházejí jěště 2 funkce, které převádějí znak buď na velké písmeno nebo naopak na malé. Ještě jednou zdůrazňuji, že převádejí znak nikoliv celé slovo (řetězec), pokud bychom chtěli použít jednu z těchto funkcí na celém řetězci, jednoduše použijeme cyklus, který projde řetězec znak po znaku a upraví jej podle potřeby.

Funkce Popis
tolower(char) převede velké písmeno na malé
toupper(char) převede malé písmeno na velké

 

K dnešní lekci to bude vše, doufám že jste se zase něco dozvěděli, můžete i články sdílet na sociálních sítích a podobně. V následujícím článku se zaměříme na soubory.

Pascal #3 Proměnná a datové typy

Proměnná

Začneme tím, že si vysvětlíme co je to proměnná. Proměnná je v podstatě místo kam si náš program ukládá nějaké data, ať už to jsou mezivýsledky, výsledky nebo hodnoty čekající na zpracování. Chápejme to tedy, jako jistý prostor kam jsme schopni ukládat data, následně k nim přistupovat a dále s nimi pracovat.

Datové typy

již tedy víme, že do proměnných můžeme ukládat nějaké data ale program, potřebuje vědět přesně, jaká data budeme ukládat, a v této chvíli přichází na scénu datové typy. V zásadě rozlišujeme tři hlavní typy

  1. Textové pod tímto si představíme jakýkoliv text nebo jeden znak.
  2. Číselné jakýkoliv údaj, se kterým jsme schopni počítat.
  3. Logické, které nabývají jenom logických hodnot TRUE nebo FALSE

Vše co jsme si doposud řekli, využijeme u deklarace proměnné. Deklaraci chápej jako vyhradit prostor. V pascalu to vypadá následovně: var nazev_promenne : prislušny_datový_typ; Na tomto řádku jsme programu řekli vše, co potřebuje. Slovně by to šlo říci nějak takhle. Vyhraď si prostor pro proměnnou nazev_promenne do které budu ukládat příslušný_datový_typ.

Jinými slovy „var“ je klíčové slovo tak aby kompilátor věděl, že deklarujete (zavádíte) novou proměnnou. Druhé slovo je „nazev“ je název proměnné může byt libovolný (pro pozdější přehlednost programu je doporučeno využívat vždy jednoznačné informativní názvy proměnných) za dvojtečkou poté následuje datový typ zjednodušeně řečeno jaké data se mohou do proměnné uložit více v následující kapitole. Abychom si to mohli napsat víc konkrétněji  pojďme se podívat na jednotlivé datové typy a jejich charakteristiky.

TEXTOVÉ datové typy

Zde se řadí typy, kde zadáváme jakékoliv znaky z ASCII tabulky. Tedy i čísla není možno však s nimi počítat, program je bere jen jako textový řetězec. Textový řetězec se v pascalu ohraničuje apostrofy ‘příklad textového řetězce !! ?? 1234‘

Rozlišujeme zde dva typy

  •     CHAR zde můžeme uložit jen a pouze jeden jediný znak. Příklad ‚A‘
  •     STRING zde můžeme uložit textový řetězec o maximální délce 255 znaků. Příklad ‚příklad textového řetězce !! ?? 1234‘

ČÍSELÉ datové typy

Do těchto datových typů budeme ukládat údaje, se kterými budeme počítat. Dělí se na:

Celočíselné (ukládáme pouze celá čísla)

  •  Byte jeho rozsah je od 0 do 255
  •  Shortint jeho rozsah je od -128 do 127
  •  Word jeho rozsah je od 0 do 65535
  •  Integer jeho rozsah je od -32768 do 32767
  •  Longint jeho rozsah je od -2147483648 do 2147483647
  •  Comp jeho rozsah je od -263+1  do 263-1

Neceločíselné (možno ukládat i čísla s desetinnou čárkou)

  •  Real jeho rozsah je od 2,9*10-39 do 1,7*1038
  •  Single jeho rozsah je od 1,5*10-45 do 3,4*1038
  •  Double jeho rozsah je od 5,0*10-324 do 1,7*10308
  •  Extended jeho rozsah je od 3,4*10-4932 do  1,1*104932

LOGICKÉ datové typy.

Do tohoto typu dat můžeme ukládat hodnoty pouze dvou stavu True a False respektive 1 a 0. Mají pouze jeden typ a tím je BOOLEAN.

Tímto jsme si tedy ukázali všechny dostupné datové typy. Teď malý příklad toho jak by to mohlo vypadat. Samozřejmě by se daly použít i jiné typy u celého čísla například typ byte. Avšak pro ukázku nám postačí:

  •   Proměnná, do které chceme uložit text  var a :string;
  •   Proměnná, do které chceme uložit znak var a :char;
  •   Proměnná, do které chceme uložit celé číslo var a:integer;
  •   Proměnná, do které chceme uložit číslo s desetinou čárkou var a :double;
  •   Proměnná, do které chceme uložit pravdivostní hodnotu var a :boolean;

V pascalu se také můžeme setkat s vlastním datovým typem interval. Proměnná v tomto datovém typu obsahuje námi již nadefinovaná data (tedy buď číslo znak, nebo logický datový typ) avšak pouze v určitém intervalu. Obecný příklad vypadá následovně.

Type x= min..max;

Var a : x;

na prvním řádku jsme si deklarovali vlastní datový typ interval. Na druhém poté deklarujeme novou proměnnou, která bude nabírat hodnot námi vytvořeného datového typu. V praxi to může vypadat takto

Type rozsah = 1..100;

Var cislo : rozsah;

Nebo

Type rozsah = ’a‘ .. ’g‘;

Var znak : rozsah;

Vidíme tedy, že do proměnné číslo můžeme zapsat čísla pouze od 1 do 100 a do proměnné pouze znaky od ‚a‘ do ‚g‘.

Ordinalita

Za zmínku také ještě stojí říct si, jaké datové typy jsou ordinální. Pojďme však od začátku a nejdříve si zaveďme pojem ordinální. Je to ve své podstatě velice jednoduché.

Ordinální prvek je takový, který má svého předchůdce a následovníka. Ordinální jsou tedy celočíselné datové typy, u kterých můžeme z jistou říct, co předchází například před číslem 10 a jaké číslo stojí za ním. Jelikož se jedná o celočíselný datový typ, je jasné, že předchůdce je 9 a následovník je 11.

Kdybychom měli to samé číslo v datovém typu neceločíselném, nemůžeme s určitostí tvrdit jaké má předchůdce a následovníky. Protože po 10 může následovat 10.1 nebo například 10.567. Neceločíselné typy jsou tedy neordinální.  Datový typ Char je také ordinální protože všichni víme, že například před písmenkem ‚B‘ přijde na řadu ‚A‘ a následovník ‚B‘ je zase ‚C‘. Posledním ordinálním typem je typ boolean jelikož nabývá pouze dvou hodnot je to jednoduché. Když nabude 1 je jasné že předchůdce je 0 a naopak.

Příště si projdeme pár příkladu týkajících se právě datových typu a ordinálních hodnot.

 

VBA – #3 Lekce – Proměnné a datové typy

V této lekci se podíváme na proměnné (bez nichž by se neobešel žádný programovací jazyk) a jejich datové typy. Každý program potřebuje své mezi výpočty nebo již hotové výsledky někam ukládat aby s nimi později mohl jakkoliv dál pracovat například vypsat na obrazovku, znovu počítat nebo cokoliv jiného proto byly vymyšleny proměnné.

Proměnná

je dočasný prostor pro ukládání dat při chodu programu. Každá proměnná se musí deklarovat (chápej jako vyhradit prostor) .

Příklad explicitně deklarované proměnné:

Dim a as integer

  1. Dim – je klíčové slovo deklarace
  2. a – je název proměnné
  3. as integer – tímto programu určujeme jaká data se budou do proměnné ukládat (datový typ)

Datové typy

každé data mají svůj typ. Některá jsou celo číselná některá jsou necelo číselná a některé jsou textová. Žádné jiné data neexistují. Každý program potřebuje znát typ dat s jakými bude pracovat a proto je rozlišujeme do několika skupin. A už při deklaraci proměnné musíme uvést jaký typ dat do ní budeme ukládat. Toto je velice důležité.

Celočíselné datové typy

Pokud budeme chtít uložit celočíselná data, použijeme jednu z následujících tří variant:

Byte

  • zabírá v paměti 1 B
  • rozsah je 0 až 255
  • Používá se tam, kde uvedený rozsah stačí.

Integer

  • Zabírá v paměti 2 B
  • rozsah je od -32768 do 32767

Long

  • Zabírá v paměti 4 B
  • Rozsah je od –2 * 109 do –2 * 109
  • tyto datové typy by se daly použít v jednoduchém příkladu
Sub soucet()
 Dim a As Integer
 Dim b As Integer
 Dim c As Integer
 a = 5
 b = 2
 c = a + b
 MsgBox c, vbOKOnly + vbInformation, "Vysledek 
End Sub 

Prvními třemi řádky jsme si deklarovali proměnné a určili jejich datový typ další dva řádky zajistili načtení hodnot (dat) do proměnných další řádek zajistil jejich výpočet a jeho načtení do proměnné c další řádek zajistil jeho vypsání pomocí msgboxu. Msgbox zvládne také vypsání proměnné to se dělá bez uvozovek (MsgBox c).

Neceločíselné datové typy

Tyto datové typy využijeme, pokud budeme vědět, že data budou s desetinou čárkou

Single

  • Reálné celé číslo s plovoucí čárkou zabírající nejvýše čtyři bajty.

Double

  • Reálné kladné číslo s plovoucí čárkou zabírající nejvýše osm bajtů. Nabízí dvojnásobnou přesnost oproti Single a větší rozsah.

Currency

  • Reálné číslo se čtyřmi desetinnými místy zabírající nejvíce osm bajtů.

Zase si je vysvětlíme na jednoduchém příkladu:

Sub Podil() 
Dim a as integer
Dim b as integer
Dim c as double
a=5
b=3
c=a/b
MsgBox c, vbOKOnly + vbInformation, "Vysledek" 
End Sub

Tím, že jsme u třetího řádku nastavili proměnnou jako double si zajistíme, že se výsledek nezaokrouhlí (což by se stalo kdyby jsme použili datový typ integer) ale vypíše se i s desetinou čárkou.

Textové (řetězcové) datové typy

String

Používáme jej k uložení textových řetězců. Řetězec musí být uzavřen do uvozovek. Do textového řetězce můžeme napsat i čísla ale nebude s nimi možno počítat. Budou brány jako znak.

Příklad:

Sub zprava()
Dim zprava as string
zprava=“libovolný textový řetězec sdělující informace uživateli“ 
MsgBox zprava, vbOKOnly + vbInformation, "Zpráva" 
End Sub

Příklad čísla ve stringu:

Sub zajimavost()
Dim a as string
Dim b as string
Dim vysledek as string
a="2"
b="3"
Vysledek=a+b
MsgBox vysledek
End Sub

Sami budete překvapení, jaký bude výsledek. Pokud program pracuje s datovým typem string, nepoužívá plus k matematickým úlohám (3+2=5) ale pouze „postaví“ dva textové řetězce za sebe (slepí je dohromady (2+3=23).

poznámka: čísla v proměnných a , b by se daly zapsat i bez uvozovek ale pro pochopení, že se jedná o datový typ string jsem raději uvedl uvozovky.

Závěr

Toto je konec 2 lekce. Můžete si vyzkoušet různé kombinování s typy proměnných a sledovat změny v chodu programu. V příští lekci se podíváme na využití dalšího windows příkazu inputbox.