Programovanie v jazyku C++

Štandardné vstupy a výstupy


cout, cin, cerr

Pre zjednodušenie práce so vstupmi a výstupmi programov ponúka C++ tri objekty, ktoré reprezentujú štandardný vstup, výstup a štandardný chybový výstup na konzolu. Tieto objekty sú deklarované v súbore <iostream.hpp>, ktorý musíme do programu zaradiť pomocou príkazu predprocesora #include, ak plánujeme tieto objekty v programe využívať. Ak neplánujete využiť vlastnosti týchto objektov, môžete samozrejme ďalej používať funkcie vstupu a výstupu jazyka C deklarované v <stdio.h>.

Nie je ale vhodné kombinovať spoločné používanie objektových a neobjektových vstupov a výstupov. Každá z foriem vstupu a výstupu má vlastný vyrovnávací zásobník, ktorý sa vyprázdňuje na základe podnetov, ktoré nemusia byť generované priamo programom. Pri súčasnom používaní objektového a klasického výstupu tak môže dôjsť k pomiešaniu a zmene poradia výstupov.

Objekt cout reprezentuje znakovo orientovaný výstup na konzolu. Objekt "rozumie" správe << nasledovanej menom premennej (objektu), konštantou alebo manipulátorom. S jednoduchým spôsobom manipulácie s preddefinovaným objektom cout sme sa stretli v prvom Vašom prograne. Správy posielané objektu cout môžu mať rôzny tvar. V starších verziach C++ sa môžeme stretnúť s takouto štruktúrou správ:

exam0100.cpp

#include <stream.hpp>     // v stream.hpp su deklarovane funkcie pre
                          // manipulaciu zo standardnymi objektami
void main()
{
  cout<<"cislo v desiatkovej sustave   : " << dec(15) <<"\n";
  cout<<"cislo v osmickovej sustave    : " << oct(15) <<"\n";
  cout<<"cislo v hexadecimalnej sustave: " << hex(15) <<"\n";
  cout<<"netlacitelny znak (ESC)       : " << char(27)<<"\n";

  cout<<"cislo s plavajucou desatinnou ciarkou: " << 3.14159 << "\n";
  cout<<"formatovanie vystupu v style printf  : " <<
         form("toto je retazec - %s\n","nejaky retazec");
}

Argumenty funkcie form majú ten istý tvar, ako argumenty funkcie printf. Tento spôsob manipulácie s objektom cout je z hľadiska ANSI normy povolený, ale je označovaný ako zastaralý. Pri kompilácii tohoto príkladu sa môžete stretnúť s chybovým hlásením, že linker nepozná funkcie použité v programe a vyžaduje prilinkovanie knižníc. Pri kompilátore Zortech C++ tento problém vyriešite nasledujúcim spôsobom

ztc -b -g exam0100.cpp oldstrs.lib

V novších verziách C++ sa udomácnilo používanie manipulátorov. Manipulátor je povel pre objekt cout, na základe ktorého objekt zmení svoje chovanie, napríklad prejde z módu zobrazovania čísel v dekadickom tvare do zobrazenie v hexadecimálnom tvare. Najbežnejším manipulátorom je endl, ktorý spôsobí vyprazdnenie zásobníka objektu na obrazovku a prechod na nový riadok. Veµkou výhodou je, že objekt pozná typ zobrazovanej entity a automaticky prispôsobí výstup danému typu. Toto platí pre štandardné dátové typy, ak vytvoríme nový dátový typ, musíme objekt cout "naučiť", ako má objekt nového dátového typu zobrazovať. Vlastnosti objektu cout demonštruje nasledujúci program:

exam0101.cpp

#include <iostream.hpp>

void main()
{
  char  c='Q';
  int   x=794;
  float f=3.14;
  char *s="Textovy retazec";

  cout<<c<<endl;                    
  cout<<x<<endl;
  cout<<f<<endl;
  cout<<s<<endl;

  cout<<hex<<x<<endl;      // pouzitie manipulatora   
}


Manipulátory umožňujú viac možností pri formátovaní výstupu ako pri klasickom spôsobe. V C++ je definovaná skupina štandardných manipulátorov:

V prípade potreby  je ale možné vytvoriť si vlastné manipulátory, ktoré sa budú vzťahovať na Vami vytvorené dátové typy.

exam0102.cpp

#include <iostream.hpp>

void main()
{
  cout<<"cislo v desiatkovej sustave   : " << 15 << endl;
  cout<<"cislo v osmickovej sustave    : " << oct << 15 <<endl;
  cout<<"cislo v hexadecimalnej sustave: " << hex << 15 <<endl;
  cout<<"netlacitelny znak (ESC)       : " << char << 27 <<endl;
}
 

Praktickou vlastnosťou jazyka C++ je reťazenie textových reťazcov. Ak používate textový editor, ktorý vám umožňuje písanie len s obmedzeným počtom znakov na riadok a potrebujete napríklad tlačiť po celej obrazovke, môžete využiť to, že dve po sebe nasledujúce úvodzovky sú kompilátorom ignorované.

exam0103.cpp

#include <iostream.hpp>

void main()
{
  cout<<"Tento retazec je prilis dlhy na jeden riadok "
        "da sa ale bez problemov rozdelit, pokial"
        " sa medzi dvoma uvodzovkami nachadzaju len oddelovace \n";
}

Objekt cerr má tie isté vlastnosti ako cout. Reprezentuje štandardný chybový výstup. Tým je štandardne konzola, ale môže byť presmerovaný na iné systémové zariadenie. Objekt cin reprezentuje znakovo orientované vstupné zariadenie. Objekt "rozumie" správe nasledovanej menom premennej. Po načítaní vstupných dát zo vstupu, štandardne je to konzola, objekt si uloží vstupné údaje do svojho zásobníka. Zo zásobníka vyberie postupnosť znakov po prvý oddelovač a konvertuje ich na dátový typ, ktorý je argumentom správy . V prípade, že konverzia nebola úspešná, cin priradí premennej nulu (alebo nulový smerník) a o neúspešnosti prevodu informuje nastavením vnútorných flagov. Ukážku použitia cin demonštrujeme na nasledujúcom príklade. Jednoduchým programíkom vytvoríme konvertor dekadického čísla na oktálové a hexadecimálne. Manipulátor showbase zobrazí pri hexadecimálnom čísle znaky 0x, prí oktálovom čísle zobrazí nulu pred číslom.

exam0104.cpp

#include <iostream.hpp>

void main()
{
  int cislo=0;
  cout<<"Zadaj cislo: ";
  cincislo;
  cout<<"Hexadecimalna hodnota: "<< hex << showbase << cislo <<"\n";
  cout<<"Oktalova hodnota     : "<< oct << cislo <<"\n";
  cout<<defaults;
}

S objektom cin sa dá rôzne čarovať. Je možné napríklad načítať jeden znak a ak nám z nejakého dôvodu jeho hodnota nevyhovuje, môžeme ho zastrčiť nazad do vstupu. V prípade, ak chceme pomocou cin načítať nie jedno slovo, ale napríklad celú vetu, musíme použiť iný spôsob čítania zo vstupu. cin pri použití operátora načíta len po prvý oddelovač a zbytok dát zostane uložený vo vstupnom zásobníku. Načítanie sekvencie znakov demonštruje nasledujúci príklad:

exam0105.cpp

#include <iostream.hpp>

void main()
{
char buf[100];
char trash;

while(1) // nekonecna slucka, program ukoncite stlacenim CTRL+C
{
cin.get(buf,100); // nacita znaky, az pokial nenajde
// ukoncovaci znak '\n', tento nie je
// ulozeny do buf a zostava vo vstupnom zasobniku
cin.get(trash); // nacitanie ukoncovacieho znaku
// ak ukoncovaci znak nenacitate, bude branit
// dalsiemu nacitaniu riadku
cout<<buf<<endl;
} // end while
} // end main

Vstup a výstup z preddefinovaných objektov je možné presmerovať na iné systémové zariadenie (COM, PRN ... ) alebo súbor. Presmerovanie sa realizuje veµmi jednoducho. Najprv ale vytvorme jednoduchý programík, ktorý načíta nejaké číslo zo štandardného vstupu, zvýši jeho hodnotu a pošle ho na štandardný výstup.

exam0106.cpp

#include <iostream.hpp>

void main()
{
 int num;
 cinnum;
 cout<<num+1;
}

Predpokladajme, že potrebujete vstup a výstup dát presmerovať z a do súborov. Presmerovanie je možné urobiť v povelovom riadku operačného systému, v ktorom spúšťate Váš program. Vytvorte súbor vstup.dat, ktorý bude obsahovať ibe jediné celé číslo. V povelovom riadku odošlite príkaz:

exam0106.exe < vstup.dat > vystup.dat

Výstup môžete presmerovať aj v rámci nejakého Vášho programu. Jednou z možností je odovzdanie riadenia operačnému systému v argumente funkcie system.

exam0107.cpp

#include <stdlib.h >

void main()
{
  // ... nejaky ozrutny kus Vasho programu
  system("exam0104 < vstup.dat > vystup.dat");
}