LINUXSOFT.cz Přeskoč levou lištu

ARCHIV



   

> C/C++ (4) - Funkce printf

Dnes se podíváme na printf, nejznámější funkci ze standardní knihovny.

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

Ukazatele a pár drobnosti

Než se pustíme do funkce printf, je třeba znát několik věcí, které jsme ještě neprobrali. Nejdůležitější jsou ukazatele (anglicky pointer), céčkové programy na nich stojí a hlavně padají. Ukazatel je fyzicky číslo, adresa v paměti. Jeho velikost záleží na architektuře, nejčastěji je stejně velký jako int, obvykle 4 byty, ale spoléhat se na to nelze. V Céčku má ukazatel vždy nějaký typ, například ukazatel na int není totéž, co ukazatel na double. Pokud typ neznáme, používá se ukazatel na void. Ukazatel se definuje pomocí hvězdičky.

int *pi;       /* proměnná pi je ukazatel na int */
void *pv;      /* proměnná pv je ukazatel na void */

Je běžným zvykem pojmenovávat proměnné typu ukazatel tak, aby začínali písmenem p (p jako pointer), někteří programátoři přidávají k úvodnímu p ještě podtržítko, například p_i, p_v a podobně.

Všechny objekty v paměti včetně funkcí mají adresu. U proměnných se dá zjistit operátorem &. Inverzním operátorem je stará známá hvězdička.

int i, j;    /* dvě proměnné typu int */
int *pi;     /* ukazatel na int */

i = 1;       /* do i dáme 1 */
pi = &i;     /* do pi dáme adresu i */
j = *pi;     /* do j dáme obsah paměti (chápaný jako int), na niž
                ukazuje pi, tedy obsah i, tedy 1 */ 

Jeden typ ukazatele už známe z minula. Je to řetězec, typ char *. Pokud napíšeme "řetězec", vyhradí překladač v datovém segmentu programu celkem alespoň osm bytů pro písmena řetězce a ukončovací nulu (připomínám: byte s číselnou hodnotou 0, nikoli znak '0'), výraz má typ const char *, je to tedy pointer na char a ukazuje na byte, který obsahuje úvodní 'ř'. Klíčové slovo const znamená, že obsah paměti, na niž pointer ukazuje nesmí být měněn.

V jazyku C přijde do kontaktu s ukazateli i začátečník. Důvodem je kromě řetězců také volání funkcí s parametry, ty se totiž předávají výhradně hodnotou. Ukážeme si to na příkladu, chceme napsat funkci, která vynuluje proměnnou.

void nula_spatne(int promenna) {
  promenna = 0;
}

void nula_dobre(int *ppromenna) {
  *ppromenna = 0;
}

int main(void) {
  int i = 1;
  nula_spatne(i);
  /* v i je pořád jedna */
  nula_dobre(&i);
  /* teprve teď je v i nula */
  return i;
}

Při volání funkce nula_spatne se vytvoří kopie proměnné i a do této kopie se vloží nula. Po skončení funkce kopie zmizí a původní proměnná zůstala nezměněná. Ve funkci nula_dobre máme v proměnné ppromenna adresu původní proměnné i, takže zápisem do paměti skutečně změníme hodnotu i a změnu nijak neovlivní ani zánik parametru ppromenna po skončení funkce. V některých jazycích (hlavně Pascal a C++) lze napsat funkci nula_dobre syntaxí podobnou nula_spatne, říká se tomu parametr předaný odkazem, ale Céčko tuto možnost nenabízí.

Funkce printf

V jazykách s vysokou teoretickou hodnotou a nízkou praktickou použitelností (Prolog) jsou výstupy takzvaně zadarmo. To znamená, že po skončení výpočtu se sám od sebe vypíše výsledek na obrazovku ve formátu, který vyhovuje autorovi normy jazyka. V jazykách vhodných pro výuku programování (Pascal) existuje magická formulka (writeln) s přehlednou, ale speciální syntaxí a touto formulkou (schválně neříkám funkcí) vypíše programátor libovolný počet hodnot různého typu. Moderní objektově orientované jazyky (Java) se snaží s problémem vypořádat pomocí metody, které převede cokoli na řetězec. Céčko je starý nízkoúrovňový jazyk pro praxi, a proto výstup řeší obyčejná funkce neobyčejné síly, která umožní výpis libovolného počtu hodnot základních typů na obrazovku ve formátu, který si určí programátor. Daní za to je mírně obtížnější syntaxe.

#include <stdio.h>

int printf(const char *format, ...);

Funkce printf je ze stdio.h, vrací počet vypsaných znaků nebo záporné číslo v případě chyby. Zajímavější než návratová hodnota, která se v programech většinou ignoruje, jsou její parametry. Prvním je formátovací řetězec, který se až na případné speciální znaky vypíše na obrazovku, následuje libovolný počet (třeba i 0) dalších parametrů. To se v C značí třemi tečkami. Kolik je parametrů, jakého jsou typu a jak a kam se mají vypsat se uvede ve formátovacím řetězci. Řídícím znakem je '%', pokud jej chcete vypsat, musí se zdvojit. Celá řídící sekvence má syntaxi

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

a typicky popisuje vložení jednoho parametru funkce printf. Téměř vždy znamená výskyt jedné řídící sekvence jeden další nepovinný parametr při volání printf. Běžně užívané typy jsou:

OznačeníTyp parametru a interpretace
iint, znaménkové číslo v desítkové soustavě
o, u, x, Xunsigned, nezáporné celé číslo v osmičkové, desítkové, šestnáctkové (s ciframi abcd nebo ABCD) soustavě
edouble, v exponenciální formě
fdouble, ve formě s desetinou tečkou
cint, zkonvertuje se na unsigned char reprezentující jeden znak
sconst char *, nulou ukončený řetězec
pvoid *, adresa paměti, číslo v šestnáctkové soustavě

Ukážeme si několik jednoduchých příkladů, všechny řídící sekvence z formátovacího řetězce budou v základním formátu %typ.

int i = -125;
const char *s = "Nějaký text";
double d = 31.4159;

/* 1. Nejjednodušší příklad bez nepovinných parametrů, */
printf("Ahoj světe\n");
/* 2. který zvládne i funkce puts, ta navíc odřádkuje. */
puts("Ahoj světe");
/* 3. Výpis čísla typu int */
printf("Minus sto dvacet pět je %i\n", i);
/* 4. Zdvojení vypisovaného procenta */
printf("Jedeme na %i%%\n", 100);
/* 5. Výpis znaku, jeho ASCII kódu ve dvou soustavách */
printf("Znak '%c' má ASCII kód %i, šestnáctkově %x\n",
  'm', 'm', (unsigned) 'm');
/* 6. Výpis řetězce, ukazatele a znaku */
printf("Řetězec s obsahuje \"%s\", je na adrese %p"
  " a začíná písmenem '%c'\n", s, (const void *) s, (int) *s);
/* 7. Výpis reálných čísel */
printf("10 pi je asi %f, což se dá napsat i jako %e\n", d, d);
/* 8. Funkce printf vrací, kolik toho vytiskla. */
printf("Vnořená printf vypsala %i znaků\n", printf("12345\n"));

Příklad vytiskne na standardní výstup následující text:

Ahoj světe
Ahoj světe
Minus sto dvacet pět je -125
Jedeme na 100%
Znak 'm' má ASCII kód 109, šestnáctkově 6d
Řetězec s obsahuje "Nějaký text", je na adrese 0x8048540 a začíná písmenem 'N'
Číslo pi je asi 31.415900, což se dá napsat i jako 3.141590e+01
12345
Vnořená printf vypsala 6 znaků

První příklad je velmi jednoduchý, vypíšeme jen jednoduchý řetězec bez řídících znaků. Funkce printf narozdíl od puts sama neodřádkuje, proto jsem musel přidat znak konce řádku do řetězce. Ve třetím příkladu je vidět výpis parametru typu int pomocí %i. Tím parametrem nemusí být jen proměnná, ale třeba konstanta (4), výsledek volání funkce (8) nebo obecně jakýkoli výraz příslušného typu. Řídících sekvencí se znakem procento může být ve volání více (5), (6) a (7), všechny běžně užívané a zde uvedené sekvence zkonzumují po jednom parametru. Důležité je, aby byly parametry správného typu. Pokud to není splněno, musíme je přetypovat (5), (6). V pátém případě využívám skutečnosti, že znaková konstanta není typu char, ale int (je to divné, ale je tomu tak). V případě %x je lepší 'm', přetypovat z intu na vyžadovaný typ unsigned, ačkoli na normálních platformách mají stejnou fyzickou reprezentaci v paměti a příklad bude fungovat i bez přetypování. V šestém případě podobně měním const char * na const void * spíše pro formu (neumím si představit platformu, kde by ukazatele na různé typy měly různé reprezentace v paměti). O něco větší smysl má přetypování charu na int (6), nicméně vzhledem ke způsobu předávání parametrů funkcím není na normálních platformách nezbytné. Vyzkoušejte si ale třeba bez přetypování vypsat double pomocí %i nebo naopak int pomocí %f a budete možná nepříjemně překvapeni.

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

Vidíte, že funkce printf je mocný nástroj a to jsme jenom na začátku. V příštím díle výklad dokončím. Zatím si můžete za domácí úkol přečíst manuálovou stránku k printf.

man 3 printf

Většině věcí byste už měli rozumět.

Verze pro tisk

pridej.cz

 

DISKUZE

parameter cez odkaz 7.10.2004 12:54 Janko Hrasko
L Re: parameter cez odkaz 7.10.2004 22:18 Jan Němec
rozdíl mezi %i a %d ? 4.8.2006 17:38 Petr Kubizňák
  L Re: rozdíl mezi %i a %d ? 4.8.2006 17:55 Aleš Hakl




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