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

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ů

23.5.2018 20:55 /Ondřej Čečák
Od pátku 25.5. proběhne na Fakultě informačních technologií ČVUT v Praze openSUSE Conference. Můžete se těšit na spostu zajímavých přednášek, workshopů a také na Release Party nového openSUSE leap 15.0. V na stejném místě proběhne v sobotu 26.5. i seminář o bezpečnosti CryptoFest.
Přidat komentář

20.5.2018 17:45 /Redakce Linuxsoft.cz
Ve čtvrtek 31. května 2018 připravuje webový magazín BusinessIT ve spolupráci s Best Online Média s.r.o. pátý ročník odborné konference Firemní informační systémy 2018. Akce proběhne v kongresovém centru Vavruška (palác Charitas), Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00 hod. dopoledne do cca 15 hod. odpoledne. Konference je zaměřena na efektivní využití firemních informačních systémů a na to, jak plně využít jejich potenciál. Podrobnější informace na webových stránkách konfrence.
Přidat komentář

14.5.2018 7:28 /František Kučera
Květnový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 17. 5. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát na téma: Audio – zvuk v GNU/Linuxu.
Přidat komentář

7.5.2018 16:20 /František Kučera
Na stránkách spolku OpenAlt vyšla fotoreportáž Pražské srazy 2017 dokumentující srazy za uplynulý rok. Květnový pražský sraz na téma audio se bude konat 17. 5. 2018 (místo a čas ještě upřesníme).
Přidat komentář

17.4.2018 0:46 /František Kučera
Dubnový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 4. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tématem tohoto srazu bude OpenStreetMap (OSM) aneb svobodné mapy.
Přidat komentář

16.3.2018 22:01 /František Kučera
Kulatý OpenAlt sraz v Praze oslavíme klasicky: u limonády a piva! Přijďte si posedět, dát si dobré jídlo a vybrat z mnoha piv do restaurace Kulový blesk, který najdete v centru Prahy nedaleko metra I. P. Pavlova na adrese Sokolská 13, Praha 2. Sraz se koná ve čtvrtek 22. března a začínáme v 18:00. Heslo: OpenAlt. Vezměte s sebou svoje hračky! Uvítáme, když si s sebou na sraz vezmete svoje oblíbené hračky. Jestli máte nějaký drobný projekt postavený na Arduinu, nějakou zajímavou elektronickou součástku, či třeba i pěkný úlovek z crowdfundingové akce, neváhejte. Oslníte ostatní a o zábavu bude postaráno.
Přidat komentář

13.2.2018 0:41 /František Kučera
Únorový pražský sraz OpenAltu se koná 15. 2. 2018 a tentokrát se vydáme na návštěvu do jednoho pražského datacentra. Sejdeme se v 17:50 v severovýchodní části nástupiště tramvajové zastávky Koh-I-Noor. Po exkurzi se přesuneme do restaurace U Pštrosa (Moskevská 49), kde probereme tradiční témata (svobodný software a hardware, DIY, CNC, SDR, 3D tisk…) a tentokrát bude k vidění i IoT brána od The Things Network.
Přidat komentář

11.2.2018 23:11 /Petr Ježek
Hledáte lehký a rychlý prolížeč PDF souborů? Pokud vás již omrzelo čekat na načítání stránek či jiné nešvary, zkuste xreader.
Přidat komentář

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

> Poslední diskuze

20.2.2018 18:48 / Ivan Majer
portal

20.2.2018 15:57 / Jan Havel
Jak využíváte služby cloudu v podnikání?

16.1.2018 1:08 / Ivan Pittner
verejna ip od o2 ubuntu

15.1.2018 17:26 / Mira Harvalik
Re: Jak udělat HTML/Javascript swiping gallery do mobilu?

30.12.2017 20:16 / Michal Knoll
odmocnina

Více ...

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