LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> C/C++ (29) - Standardní knihovna počtvrté

Dnes v rychlosti probereme locale a zpracování jednotlivých znaků, v druhé části článku dojde na standardní i nestandardní ukončování programu.

15.12.2005 06:00 | Jan Němec | Články autora | přečteno 18995×

Národní prostředí

Jazyk C pochází ze 70. let a je to na něm vidět. Před 35 lety jen málo lidí od počítačů napadlo, že by někdo mohl chtít používat jinou znakovou sadu, formát čísel, data a podobně, než používají Američané. Později byla do C jakási podpora národního prostředí doplněna, ale na některých překladačích dosud nefunguje nebo funguje jen částečně (což ale není problém gcc), takže pro použití v přenositelném kódu je jen obtížně použitelná. Standardní knihovna podporuje pouze terminálový vstup a výstup, přičemž řetězce jsou jen pole bytů, která se na výstup posílají v podobě binárně shodné se zápisem ve zdrojovém kódu. Lokalizace tak má jen omezené pole působnosti, neboť neřeší například problematiku fontů nebo překódování do a z unikódu. Troufl bych si proto tvrdit, že lokalizaci programu na úrovni standardní knihovny C je lepší se vyhnout.

#include <stdio.h>
#include <locale.h>

int main(void) {
  printf("%f\n", 1.45);
  setlocale(LC_ALL, "");
  printf("%f\n", 1.45);
  return 0;
}

Na počátku programu je podle normy nastavené přenositelné "C" prostředí. Funkce printf proto vypíše číslovku s desetinnou tečkou. Volání setlocale změní charakter prostředí ve všech (LC_ALL) oblastech (znaková sada, výpis čísel, ...) na výchozí (parametr "") na daném počítači. Na mém česky nainstalovaném Mandriva Linuxu 2006 s gcc 4.0.1 a glibc 2.3.5 uvedený program oddělí při druhém volání printf desetinná místa čárkou. Na českých Windows 98 s MS Visual C++ 6.0 se uvedený program choval stejně, ale níže uvedený převod národních znaků na velká písmena pomocí toupper mi fungoval pouze s gcc na Linuxu.

Lokalizace prostředí na úrovni standardní knihovny je poměrně nebezpečná záležitost. Uživatel možná rád uvidí desetinou čárku místo tečky (toho ovšem lze snadno docílit i bez speciální podpory standardní knihovny), ale pokud jiná část programu například pomocí printf generuje SQL dotazy, kde musí být oddělovačem tečka, je problém na světě. Proto, pokud programátor potřebuje nastavovat locale, je vhodné místo všech oblastí (LC_ALL) použít pouze tu, kde je to nezbytné, například LC_NUMERIC, LC_CTYPE, LC_MESSAGES a podobně. Zájemce, které se mi nepodařilo odradit, odkazuji na manuálovou stránku setlocale.

Práce se znaky

Hlavičkový soubor ctype.h obsahuje řadu funkcí a maker pro detekci typu znaku a konverzi mezi malými a velkými písmeny. Hodit by se mohly zejména tyto rutiny s dostatečně výmluvnými názvy:

int islapha(int c); /* Je znak písmeno? */
int isdigit(int c); /* Je znak číslice? */
int isalnum(int c); /* Je znak písmeno nebo číslice? */
int islower(int c); /* Je znak malé písmeno? */
int isupper(int c); /* Je znak velké písmeno? */
int isprint(int c); /* Je znak tisknutelný? */
int isspace(int c); /* Jde o "bílý" znak? (mezera, tab, ...) */
int tolower(int c); /* Velká písmena na malá, ostatní znaky nechat. */
int toupper(int c); /* Malá písmena na velká, ostatní znaky nechat. */

Co vlastně je nebo není písmeno závisí na znakové sadě a tím pádem i na locale. Ve výchozím nastavení "C" se za písmena považují pouze znaky anglické abecedy. Při nastavení českého locale, budou rutiny fungovat i pro znaky s diakritikou, ale jen s kvalitním překladačem/libc a jen pokud používáte stejnou znakovou sadu, kterou považuje překladač/libc za výchozí pro zvolené locale.

#include <ctype.h>
...

char *pc;
int silne = 0;

pc = heslo;
while (*pc) {
  if (isdigit(*pc)) {
    silne = 1;
    break;
  }
}
if (!silne) {
  puts("Slabé heslo, neobsahuje ani jednu číslici!");
}

Ukončení programu

Zatím jsme vždy ukončovali chod programu pomocí return ve funkci main. V některých případech může být tento postup nešikovný, běžným případem jsou rekurzivní nebo jiná vnořená volání funkcí, kdy program zjistí, že by se měl ukončit v nejvnitřnějším volání a je příliš komplikované zajistit návrat ze všech instancí všech funkcí. Dalším případem je ukončení programu programátorem knihovny, který nemůže ovlivnit volající kód. Standardní knihovna proto nabízí funkce abort, exit a atexit.

#include <stdlib.h>

void abort(void);
void exit(int status);
int atexit(void (*function)(void));

Funkce abort zajistí okamžité chybové ukončení programu, na linuxu signálem SIGABRT. Buffery všech otevřených souborů by měly být zapsány a soubory uzavřeny, ale programátor by na to pochopitelně neměl spoléhat. Funkce je určena především pro nestandardní ukončení programu při ladění, případně po nějaké velmi vážné chybě programu, kdy už nemá smysl snažit se cokoli zachránit a kdy je záměrem uživatele informovat následující hláškou:

[honza@localhost ~]$ ./abort
Neúspěšně ukončen (SIGABRT)
[honza@localhost ~]$

Ukončení programu mimo main nemusí vždy znamenat chybu, případně chyba není tak vážná, aby bylo nutné program ukončovat nestandardním způsobem. V tom případě použijeme funkci exit. Její volání (včetně parametru) odpovídá return ve funkci main. Jedná-li se o řádné ukončení programu, voláme exit(0), v opačném případě s nějakou nenulovou hodnotou nebo lépe exit(EXIT_SUCCESS) a exit(EXIT_FAILURE).

Občas se hodí provést na konci programu nějakou akci bez ohledu na to, zda byl programu ukončen returnem v main nebo funkcí exit. Není jednoduché toho dosáhnout, neboť program může být ukončen i z knihovny, kterou nemá programátor pod kontrolou. Naštěstí existuje funkce atexit, která zaregistruje uživatelskou funkci, jež bude runtimem zavolaná v době ukončení programu. Je-li funkcí více, volají se v opačném pořadí, než byly zaregistrovány.

#include <stdio.h>
#include <stdlib.h>

void po_main(void) {
  puts("po_main");
}

void nakonec(void) {
  puts("nakonec");
}

int main(void) {
  puts("main - začátek");
  
  puts("registruji nakonec");
  atexit(nakonec);

  puts("registruji po_main");
  atexit(po_main);

  puts("main - konec pomocí exit");

  exit(EXIT_SUCCESS); /* Jen test funkce exit, return by to zvládnul stejně. */


  puts("Sem bych se neměl dostat...");
  return 0;
}

Ladění s pomocí assert

Při vývoji větších projektů je třeba počítat s chybami. Nejobtížněji se hledají chyby typu přepsání paměti za polem nebo přístupu na neinicializovaný ukazatel, neboť se projevují jen někdy a často až dodatečně a daleko od místa chyby. Do programu se proto běžně přidává kód, který se snaží chyby odhalit již v místě jejich vzniku a zpravidla jen vypíše chybovou hlášku a ukončí program. Podobný kód však může zbytečně zdržovat již odladěný program a navíc v distribuční verzi (zejména komerčního software) může být někdy přiznání chyby a násilné ukončení programu větší zlo než chyba sama o sobě. Již víme, že s pomocí makra preprocesoru a podmíněného překladu můžeme vyvolávat ladící testy jen ve vývojové verzi programu. Standardní knihovna se nám to snaží zjednodušit a nabízí rutinu assert.

#include <assert.h>

int main(void) {

  int pole[10];
  int i;
  
  for (i = 0; i <= 10; i++) {
    assert(i < sizeof(pole) / sizeof(int));
    pole[i] = 0;
  }
  return 0;
}

V příkladu se snažím vynulovat pole, ale dopustil jsem se známé chyby "+1", kdy přistupuji o jeden prvek za konec pole. Chování programu v tomto případě není definované, záleží na tom, co se nachází za polem. Naštěstí jsem vložil do cyklu ladící test assert, který v případě nesplnění podmínky ukončí program pomocí funkce abort a vypíše chybovou hlášku:

assert: assert.c:10: main: Assertion `i < sizeof(pole) / sizeof(int)' failed.

Ladící testy můžeme snadno vypnout, pokud definujeme makro NDEBUG. Rozhodující je přitom místo (posledního) inkludu hlavičkového souboru assert.h, #define NDEBUG tedy musí předcházet #include <assert.h>. Nejlepší je ovšem definice pomocí parametru překladače:

gcc assert.c -o assert -DNDEBUG

Uvedený příklad je trochu vykonstruovaný. Programátor, který správně testuje meze polí přímo v cyklu pravděpodobně neudělá chybu v ukončovací podmínce toho samého cyklu. V praxi se spíše setkáme s testováním parametrů funkcí, užitečné je to zejména pokud jeden programátor napíše knihovnu poskytující sadu funkcí (jejichž parametrem například nesmí být NULL) a jiný programátor tuto knihovnu používá.

Pokračování příště

Standardní knihovnu jsme již probrali. V příštím dílu se zamyslíme nad tím, co ve standardní knihovně nejvíce chybí. Vydalo by to na několik dalších samostatných seriálů, proto vždy uvedu jen stručný popis a především odkaz na web, který se problematice věnuje. Ze základní syntaxe jazyka C nám chybí výčtový typ, i na něj dojde v příštím dílu.

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

14.11.2017 16:56 /František Kučera

Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tradičně první čtvrtek před třetím pátkem v měsíci: 16. listopadu od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).


Přidat komentář

12.11.2017 11:06 /Redakce Linuxsoft.cz
PR: 4. ročník odborné IT konference na téma Datová centra pro business proběhne již ve čtvrtek 23. listopadu 2017 v konferenčním centru Vavruška, v paláci Charitas, Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00. Konference o návrhu, budování, správě a efektivním využívání datových center nabídne odpovědi na aktuální a často řešené otázky, např Jaké jsou aktuální trendy v oblasti datových center a jak je využít pro vlastní prospěch? Jak zajistit pro firmu či jinou organizaci odpovídající služby datových center? Podle jakých kritérií vybrat dodavatele služeb? Jak volit součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně spravovat datové centrum? Jak eliminovat možná rizika? apod.
Přidat komentář

13.9.2017 8:00 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tentokrát netradičně v pondělí: 18. září od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

3.9.2017 20:45 /Redakce Linuxsoft.cz
PR: Dne 21. září 2017 proběhne v Praze konference "Mobilní řešení pro business". Hlavní tématy konference budou: nejnovější trendy v oblasti mobilních řešení pro firmy, efektivní využití mobilních zařízení, bezpečnostní rizika a řešení pro jejich omezení, správa mobilních zařízení ve firmách a další.
Přidat komentář

15.5.2017 23:50 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 18. května od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.5.2017 16:42 /Honza Javorek
PyCon CZ, česká konference o programovacím jazyce Python, se po dvou úspěšných ročnících v Brně bude letos konat v Praze, a to 8. až 10. června. Na konferenci letos zavítá např. i Armin Ronacher, známý především jako autor frameworku Flask, šablon Jinja2/Twig, a dalších projektů. Těšit se můžete na přednášky o datové analytice, tvorbě webu, testování, tvorbě API, učení a mentorování programování, přednášky o rozvoji komunity, o použití Pythonu ve vědě nebo k ovládání nejrůznějších zařízení (MicroPython). Na vlastní prsty si můžete na workshopech vyzkoušet postavit Pythonem ovládaného robota, naučit se učit šestileté děti programovat, efektivně testovat nebo si v Pythonu pohrát s kartografickým materiálem. Kupujte lístky, dokud jsou.
Přidat komentář

2.5.2017 9:20 /Eva Rázgová
Putovní konference československé Drupal komunity "DrupalCamp Československo" se tentokrát koná 27. 5.2017 na VUT FIT v Brně. Můžete načerpat a vyměnit si zkušenosti z oblasti Drupalu 7 a 8, UX, SEO, managementu týmového vývoje, využití Dockeru pro Drupal a dalších. Vítáni jsou nováčci i experti. Akci pořádají Slovenská Drupal Asociácia a česká Asociace pro Drupal. Registrace na webu .
Přidat komentář

1.5.2017 20:31 /Pavel `Goldenfish' Kysilka
PR: 25.5.2017 proběhne v Praze konference na téma Firemní informační systémy. Hlavními tématy jsou: Informační systémy s vlastní inteligencí, efektivní práce s dokumenty, mobilní přístup k datům nebo využívání cloudu.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

18.9.2017 14:37 / Rojas
high security vault

15.9.2017 7:33 / Wilson
new zealand childcare jobs

31.8.2017 12:11 / Jaromir Obr
Re: ukůládání dat ze souboru

30.7.2017 11:12 / Jaromir Obr
Národní znaky

27.7.2017 12:24 / Jaromir Obr
Cteni/zapis

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2017) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze