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

> C/C++ (5) - Funkce printf podruhé

Dnes dokončíme povídání o funkci printf a dojde i na jednu oblíbenou programátorskou chybu.

18.10.2004 10:00 | Jan Němec | Články autora | přečteno 47627×

Pokročilé použití printf

V minulém dílu jsem ukázal jednoduché příklady na printf. V řídících sekvencích formátovacího řetězce jsem používal pouze povinné části, kterými jsou úvodní znak procento a typ. Jak již víme, řídící sekvence může být složitější:

%[příznaky][minimální šířka][přesnost][modifikátor typu]typ

Příznak může mít jednu z hodnot uvedených v tabulce. Dá se jím ovlivnit zarovnání vypsaného parametru, pokud je jeho šířka menší, než je žádoucí. Zarovnávací příznaky se proto používají hlavně ve spojení s další nepovinnou částí řídící sekvence - minimální šířkou. Příznakem lze také vynutit znaménko před číslem (např. +2 místo 2). U záporných čísel se znaménko pochopitelně vypisuje i bez příznaku automaticky. Příznak # slouží k názornějšímu výpisu parametru. Například v šestnáctkové soustavě se předřadí 0x a u reálných čísel je ve výpisu vždy desetinná tečka.

PříznakVýznam
#Vypíše typ více explicitně.
0Zleva zarovnat nulami
-Zprava zarovnat mezerami
mezeraZleva zarovnat mezerami
+Před číslem vždy znaménko

Význam položky minimální šířka je celkem zřejmý. Jde o celé číslo a pokud je vypisovaný prvek příliš krátký, text se rozšíří. Způsob rozšíření lze ovlivnit položkou příznak. Jako šířku lze uvést i znak *, šířka potom není uvedená ve formátovacím řetězci, ale jako další parametr funkce printf předcházející tomu, který chceme vypsat. Jedna řídící sekvence tak zkonzumuje dva parametry funkce printf. Ukážeme si to na příkladech.

Další na řadě je přesnost. Začíná vždy tečkou a následuje celé číslo nebo podobně jako v případě minimální šířky znak * - odkaz na hodnotu z parametru. Používá se hlavně u reálných čísel a znamená počet cifer za desetinou tečkou. Méně obvyklé je použití u celých čísel - počet všech cifer a u řetězců - maximální počet znaků, který se má vytisknout.

Nejméně významnou položkou je modifikátor typu, během sedmi let programování v C jsem se s ním v praxi nesetkal. Zájemce proto odkazuji na manuálové stránky a přistoupím raděj k příkladům.

#include <stdio.h>
int main(void) {
  /* 1 */
  printf("Pro opakování: 1 = %i\n", 1);
  /* 2 */
  printf("255 = %#x = %x\n", 255, 255);
  /* 3 */
  printf("1 = %i = %10i = % 10i = %-10i = %010i\n", 1, 1, 1, 1, 1);
  /* 4 */
  printf("%+i = %i, %+i = %i\n", 1, 1, -1, -1);
  /* 5 */
  printf("%f, %.0f, %#.0f\n", 8.3, 9.7, 5.4);
  /* 6 */
  printf("Slepice dělá %-10.*s.\n", 6, "kokokodák");
  return 0;
}

Program vypíše na standardní výstup následující text:

Pro opakování: 1 = 1
255 = 0xff = ff
1 = 1 =          1 =          1 = 1          = 0000000001
+1 = 1, -1 = -1
8.300000, 10, 5.
Slepice dělá kokoko    .

Nejprve (1) jsem zopakoval z minula jednoduchou sekvenci %i na výpis jednoho intu. Příznakem # jsem ukázal (2) předsazení 0x před šestnáctkový výpis. Potom (3) dokumentuji různé způsoby výpisu jedničky. Nejprve je ve formátovacím řetězci napsaná natvrdo, potom jako parametr, přičemž řídící sekvence neobsahuje nepovinné části. V posledních čtyřech výpisech jedničky ji rozšířím na deset znaků. Nejdřív nechám výpis bez příznaků (výchozí zarovnání, zarovná se doprava) a potom jedničku obložím zleva a zprava mezerami a nakonec zleva nulami. V příkladu (4) ukazuji vynucení znaménka + před kladným číslem a potom (5) výpis reálných čísel s přesností na 0 desetinných míst, tedy vlastně zaokrouhlení na celá čísla ve výpisu. Příznakem # si můžeme vynutit desetinou tečku. Pokud pochopíte poslední příklad (6), umíte printf. Vypisuji řetězec (%s), ze kterého se vezme jen počet znaků daný předchozím parametrem (%.*s), má navíc specifikovanou minimální šířku 10 (%10.*s), a pokud tato šířka bude větší než počet vypsaných znaků řetězce (to je náš případ), vloží se doprava patřičný počet mezer.

Doufám, že jste se nenechali poněkud komplikovanou funkcí printf odradit od Céčka. Rozhodně si nevtloukejte syntaxi řídící sekvence do hlavy. Pro úspěšné programování v C vám postačí znát význam %i, %sman 3 printf.

S printf jsou spojené závažné chyby programátorů s nepříjemnými následky. Je dost nebezpečné, že (typicky nastavený a běžný) překladač nekontroluje syntaxi formátovacího řetězce a počet a druh parametrů. Obecně to ani nelze, neboť formátovací řetězec nemusí být zadán jako konstanta, ale jako proměnná nebo obecně výraz typu const char *. Zde se právě skrývá nebezpečí, zamyslete se nad následujícím kusem kódu:

  char *s;
  s = ziskej_retezec_od_uzivatele();
  printf(s); /* Špatně!!! Dobře je printf("%s", s) */

Může jít třeba o kus www serveru a funkce ziskej_retezec_od_uzivatele vrací požadovaný soubor z URL v GET nebo POST dotazu, voláním printf se píše do logu (třeba s pomocí přesměrování). Programátor serveru vše odladí ze svého prohlížeče na URL typu http://www.mujserver.cz/index.html a nasadí do ostrého provozu. Problém nastane, až nějaký vtipálek začne posílat dotazy místo na index.html třeba na %s. Co se stane? Server zavolá printf("%s") a funkci printf pak chybí jeden parametr, ukazatel na char, řetězec, který se má vypsat kvůli sekvenci %s. Při volání printf žádná taková hodnota předána nebyla, ale to printf neví. Za ukazatel na char bude považovat data, která na místě v paměti určeném pro předávání parametrů zbyla z dřívějška a z paměti, kam tento "ukazatel" míří bude zkoušet načíst nulou ukončený řetězec. Chování programu pak závisí na architektuře, operačním systému, překladači a hlavně náhodě, na Linuxu obvykle spadne s hláškou Segmentation fault, ale běžný je i výpis nějakého nesmyslného řetězce.

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

Doufám, že jsem podrobným výkladem funkce printf a jejích záludností čtenáře neodradil a nezastrašil. V řadě věcí jsme trochu předběhli, ale psát programy bez výstupu by asi nikoho nebavilo. V dalším dílu se podíváme na operátory.

Verze pro tisk

pridej.cz

 

DISKUZE

serial 18.10.2004 18:23 Pavel Bařina
pouziti %i 19.10.2004 08:51 Martin Fiala
hvezdicka 25.10.2004 23:36 Josef Kufner
Ako inak funkcia printf a jej prototyp..... 20.2.2013 17:54 Nikolas Patrik




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

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ář

15.4.2017 15:20 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě IoT a radiokomunikace? Přijď na sraz spolku OpenAlt, který se bude konat ve středu 19. dubna od 18:30 v Šenkovně (Sokolská 60, Praha 2).
Přidat komentář

5.3.2017 19:12 /Redakce Linuxsoft.cz
PR: 23. března proběhne v Praze konferenci na téma Cloud computing v praxi. Hlavními tématy jsou: Nejžhavější trendy v oblasti cloudu a cloudových řešení, Moderní cloudové služby, Infrastruktura současných cloudů, Efektivní využití cloudu, Nástrahy cloudových řešení a jak se jim vyhnout.
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