/ janturon.cz / Výuka / C / Vstup a výstup

Vstup a výstup

Rozdíl mezi C a C++

Jazyk C vznikl dlouho před vynálezem dnes tak oblíbeného objektového programování. Toto rozšíření do něj přenáší C++. Většinu programů napsaných v C bez úpravy spustíte v kompilátoru jazyka C++ (naopak to neplatí). Proto probereme nejprve C, a poté se pustíme do C++.

K čemu je C dobré

Jazyk C je mnohem nízkoúrovňovější než Javascript. Naprogramovat v něm třeba prompt dá mnohem více práce a je k tomu potřeba znát hromadu věcí. Specializace C je přímý přístup k OS a hardware, umožňuje psát velmi rychlé a efektivní programy. Pochází ze 70.let a jeho syntaxi převzaly jazyky jako C#, Java, PHP, nakonec i samotný Javascript. Nepropadejte ale naději, že vše půjde hladce: je to mnohem přísnější jazyk než Javascript. Nabídne vám mnohem více možností (prakticky vše, co HW a OS nabízí), ale také toho mnohem více vyžaduje.

Jak se tvoří program v C

První krok je stejný jako u Javascriptu: v textovém editoru napíšete zdrojový kód a uložíte ho do souboru, jemuž se dává přípona .c. Tím podobnost končí.

C je kompilovaný jazyk: ke svému běhu nepotřebuje žádný prohlížeč, překládá se přímo do spustitelného kódu daného OS (.exe pro Windows). Je tedy zapotřebí kompilátor, který zdrojový kód přeloží do instrukcí cílového zařízení.

Než ale ke kompilaci dojde, je zdrojový kód upraven preprocesorem. Tomu lze zadávat příkazy začínající na #, ve zdrojovém kódu tak kombinujeme dva jazyky.

Kompilátor ještě nevyrobí spustitelný kód, ale pouze objektový kód. To je binární kód, do kterého ještě musí být doplněny odkazy na případné další soubory a knihovny. Pospojování těchto odkazů má na starosti linker, kterému lze také zadat mnoho povelů na příkazové řádce. Jakékoli větší programy pro tuto činnost však používají vývojová prostředí, které příkaz pro sestavení vytvoří podle voleb, které si naklikáme. V našich programech linkeru většinou nic dramatického sdělovat nebudeme.

Volba vhodného kompilátoru

Popsaný proces tvorby spustitelného kódu tedy usnadňují vývojová prostředí jako je MSVC, QtCreator či Dev-C++. Ty nabízejí hromadu voleb, které mohou být zpočátku zdrcující. Začneme proto nejjednodušeji, jak jsme zvyklí z Javascriptu: v poznámkovém bloku či PS Padu, kompilovat budeme na příkazové řádce kompilátorem MinGW. Až vám to přestane stačit (zhruba v době vytvoření vaší první knihovny), přejděte na lepší vývojové prostředí (doporučuju začít na Dev-C++), s nabytými zkušenostmi tam většinu věcí intuitivně poznáte.

Kompilátor MinGW je možné nainstalovat i na klíčenku, což vám umožní psát doslova přenositelný kód (ten, který lze zkompilovat pro různé systémy).

Na školách se často používá i Borland C++ Builder. Jeho nevýhoda je, že je placený, (srovnatelné kvality jako ostatní IDE zdarma) a přitom málo rozšířený.

První program

Jako obvykle Hello, world: vytvořte soubor hello.c a vepište zdrojový kód:

#include "stdio.h" void main() { puts("hello, world"); }

Hned první příkaz patří preprocesoru: říká, aby ke zdrojovému kódu přidal funkce knihovny pro vstup a výstup stdio.h (standard input and output). Seznam těch funkcí najdete zde. Funkce začínající na f slouží ke čtení a zápisů souborů (ejhle, javascript se soubory pracovat neuměl!) ostatní funkce až na to f mají stejný název i účel a čtou standardní vstup (pro nás klávesnice) a zapisují na standardní výstup (pro nás konzole).

Při spuštění programu se vykoná funkce main. Oproti Javascriptu při definici vynecháváme function, zato musíme slíbit typ návratové hodnoty. Pokud funkce nic nehodlá vracet, typem je void.

Řetězce v C

Řetězce lze vyjádřit jako pole znaků: char data[32] (C potřebuje znát velikost pole už v době kompilace). Pole znaků i řetězce jsou v paměti reprezentovány jako posloupnost znaků 1B = 1znak ukončena znakem \0 označující konec řetězce. Napíšeme-li char data[32] = "Hello";, změní se prvních 6B v místě paměti, kde bylo pole vytvořeno. Nyní již můžeme napsat zdravící program:

#include "stdio.h" void main() { char name[32]; puts("What is your name?"); gets(name); printf("Hello, %s",name); }

Funkce printf slouží k tisku proměnných: znaky %s se nahradí obsahem proměnné zadané jako další parametr.

Funkce gets načte jméno uživatele do proměnné name. Zadá-li více než 31 znaků (např. Taumatawhakatangihangakoauauotamateapokaiwhenuakitanatahu), program nejspíš spadne kvůli zápisu do nealokované paměti: gets se pokusí zapsat za oněch 32B, o které jsme požádali. Spadnout ale nemusí, pokud máme "štěstí" a v přepsané paměti není nic důležitého. To je zákeřné. Naučme se psát bezpečné programy:

#include "stdio.h" void main() { char name[32]; puts("What is your name?"); fgets(name,32,stdin); printf("Hello, %s",name); }

Funkce přečte nejvýše 31 znaků ze standardního vstupu, zbytek tam ponechá. Všimněte si, že se standardním vstupem lze zacházet jako se souborem. To je inspirováno Unixem, kde každé ovladatelné zařízení má vytvořen svůj speciální soubor, přes který ho lze ovládat. Pokud je zadáno více než 31 znaků, některé zůstanou ve vstupním zařízení a kdybychom chtěli přečíst druhé jméno, nečeká se na vstup, ale dosadí se ony zbylé znaky. Proto je vhodné po každém čtení standardní vstup vyčistit:

for(int c=1; c!='\n'; c=getchar()) if(c==EOF) break;

Všimněte si, že znaky se zapisují do apostrofů a lze pro ně použít typ int (4B kvůli kompatibilitě s vícebytovými znaky).

Někde se můžete setkat s jednodušším fflush(stdin);, jejíž chování ale není standardem definováno. Pod MinGW na Windows to fungovat bude, ale kód nebude přenositelný.

 

Otázky