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

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

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ů

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