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 46203×

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ů

1.12.2016 22:13 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 8. prosince od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Sraz bude tentokrát tématický. Bude retro! K vidění budou přístroje jako Psion 5mx nebo Palm Z22. Ze svobodného hardwaru pak Openmoko nebo čtečka WikiReader. Přijďte se i vy pochlubit svými legendami, nebo alespoň na pivo. Moderní hardware má vstup samozřejmě také povolen.
Komentářů: 1

4.9.2016 20:13 /Pavel `Goldenfish' Kysilka
PR: Dne 22.9.2016 proběhne v Praze konference Cloud computing v praxi. Tématy bude např. nejnovější trendy v oblasti cloudu a cloudových řešení, provozování ERP v cloudu, o hostování různých typů softwaru, ale třeba i o zálohování dat nabízeném podnikům formou služby.
Přidat komentář

1.9.2016 11:27 /Honza Javorek
Česká konference o Pythonu, PyCon CZ, stále hledá přednášející skrz dobrovolné přihlášky. Máte-li zajímavé téma, neváhejte a zkuste jej přihlásit, uzávěrka je již 12. září. Konference letos přijímá i přednášky v češtině a nabízí pomoc s přípravou začínajícím speakerům. Řečníci mají navíc vstup zadarmo! Více na webu.
Přidat komentář

27.8.2016 8:55 /Delujek
Dnes po 4 letech komunitního vývoje vyšla diaspora 0.6.0.0
diaspora* je open-source, distribuovaná sociální síť s důrazem na soukromý
Více v oficiálním blog-postu
Přidat komentář

24.8.2016 6:44 /Ondřej Čečák
Poslední týden CFP LinuxDays 2016; pokud byste rádi přednášeli na LinuxDays 2016 8. a 9. října v Praze, můžete svůj příspěvek přihlásit, následovat bude veřejné hlasování.
Přidat komentář

9.8.2016 22:56 /Petr Ježek
Zařazení souborového systému reiser4 do jádra 4.7 znamená konečně konec patchování jádra jen kvůli možnosti použít reiser4.
Přidat komentář

12.7.2016 13:14 /František Kučera
Spolek OpenAlt zve na 130. distribuovaný sraz příznivců svobodného softwaru a otevřených technologií (hardware, 3D tisk, SDR, DIY, makers…), který se bude konat ve čtvrtek 21. července od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

11.7.2016 16:53 /Redakce Linuxsoft.cz
Konference LinuxDays hledá přednášející. Přihlášky poběží do konce prázdnin, v září bude hlasování a program. Více na https://www.linuxdays.cz/2016/cfp/.
Přidat komentář

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

> Poslední diskuze

10.12.2016 11:01 / jeorge
kitchen designer

7.12.2016 8:10 / Hamon
scottish cottages

4.12.2016 22:54 / František Kučera
Dárek

9.11.2016 7:42 / Mane
hardwood floor waxing

8.11.2016 13:38 / Mira
Konfigurace maldet na Centos serveru

Více ...

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