LINUXSOFT.cz Přeskoč levou lištu

ARCHIV



   

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

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ů

28.11.2018 23:56 /František Kučera
Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1

12.11.2018 21:28 /Redakce Linuxsoft.cz
22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář

6.11.2018 2:04 /František Kučera
Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

4.10.2018 21:30 /Ondřej Čečák
LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář

18.9.2018 23:30 /František Kučera
Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

9.9.2018 14:15 /Redakce Linuxsoft.cz
20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business. Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář

12.8.2018 16:58 /František Kučera
Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář

16.7.2018 1:05 /František Kučera
Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář

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

> Poslední diskuze

31.7.2023 14:13 / Linda Graham
iPhone Services

30.11.2022 9:32 / Kyle McDermott
Hosting download unavailable

13.12.2018 10:57 / Jan Mareš
Re: zavináč

2.12.2018 23:56 / František Kučera
Sraz

5.10.2018 17:12 / Jakub Kuljovsky
Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?

Více ...

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