Úvod do programovania v jazyku C

Doc. Ing. Pavel Horovčák, CSc., Prof. RNDr. Igor Podlubný, CSc.

Táto on-line príručka vznikla v rámci riešenia výskumného projektu KEGA č. 112/97 "uniWWWerzita"

  1. Úvod
  2. Preprocesor jazyka C
  3. Premenné
  4. Lexikálne prvky jazyka
  5. Riadiace štruktúry
  6. Štandardný vstup a výstup
  7. Reťazce
  8. Súbory
  9. Smerníky
  10. Datové štruktúry
  11. Triedenie
  12. Terminálové funkcie (QNX)
  13. Doporučená literatúra

1 Úvod

  1. Z histórie jazyka C
  2. Štruktúra programu v jazyku C

1.1 Z histórie jazyka C

     Programovací jazyk C vznikol na začiatku sedemdesiatych rokov v Bellových laboratóriách firmy AT&T (American Telephone and Telegraph). Autorom prvotného návrhu C je Dennis Ritchie, ktorý v tej dobe spolupracoval s Kenom Thompsonom na návrhu operačného systému UNIX. Pre jeho implementáciu sa autori rozhodli použiť jazyk dostatočne efektívny z hľadiska kódu a pritom nezávislý na konkrétnom procesore. Najprv uvažovali o použití jazyka BCPL (Basic Combined Programming Language), neskôr navrhol K. Thompson variant pod označením jazyk B (1970). V tomto jazyku boli implementované prvé časti OS UNIX. Tento jazyk bol efektívny z hľadiska prekladu, ale nebol dostatočne univerzálny - vyhovoval len na riešenie určitého okruhu problémov. D. Ritchie navrhol preto jazyk s označením C, v ktorom bolo neskôr zapísané asi 90 % kódu OS UNIX (zvyšná časť závisí na hardware konkrétneho počítača a musí byť napísaná v asembleri).

     Jazyk C nie je rozsiahly, ale nepatrí pritom medzi jazyky, vyznačujúce sa dobrou čitateľnosťou. Svojím pôvodom je zameraný na systémové programovanie. Na jednej strane je ho možné zaradiť do skupiny vyšších programovacích jazykov, na druhej strane je možné program napísaný v jazyku C preložiť do veľmi efektívneho strojového kódu (niekedy sa preto o ňom hovorí ako o štruktúrovanom asembleri). Jazyk C má pomerne málo jednoduchých pravidiel, pomocou ktorých je možné vytvárať a skladať jednotlivé úseky programov do väčších a väčších celkov.

     Jazyk C sa ďalej mierne vyvíjal. V  roku 1978 napísali Ritchie a Kernighan knihu Programovací jazyk C, ktorá sa stala štandardom staršej verzie jazyka. V dnešnej literatúre sú na tento štandard referencie pod označením Kernighan - Ritchie C, resp. K & R. V roku 1984 vzniká prvá verzia americkej národnej normy jazyka pod označením ANSI C, ktorá mala nevýhodu najmä v slabšej typovej kotrole Od tejto chvíle dochádza k určitému oddeleniu jazyka C od OS UNIX a jazyk sa začína vyvíjať ako samostatný produkt. Definitívna verzia normy ANSI C vyšla vo februári 1990 pod označením X3J11 / 90 - 013 [Richta93]. Zavedením prísnejšej typovej kontroly pri volaní funkcií a vyhodnocovaní výrazov nie je možné napr. volať funkciu skôr, ako sa uvedie jej deklarácia alebo priamo definícia.

     Jazyk C je implementovaný pre všetky typy procesorov a spolu so systémom UNIX predstavuje dnes jeden z hlavných trendov vo svete. Vznikol tiež celý rad rozšírení jazyka C - napr. Objective C pre objektové programovanie, Concurrent C pre paralelné programovanie, ale najperspektívnejším sa zdá byť objektovo orientované rozšírenie jazyka pod označením C ++ (označenie vychádza zo syntaxe jazyka C a znamená prechod na nasledujúci prvok), ktoré navrhol Bjarne Stroustrup z AT&T pri vývoji riadiaceho systému pre telefónne ústredne [Mareš94]. Do jazyka boli pridané konštrukcie pre tvorbu obecných funkcií a tried (šablony) a pre spracovanie výnimočných stavov. V súčasnej dobe ešte nie je oficiálne vydaná norma C++ a ako štandardná implementácia pre ostatné kompilátory slúži prekladač použitý na systéme USL firmy AT&T. Je to len preprocesor, ktorého výstupom je kód v jazyku C; preto sa tento preprocesor označuje ako Cfront. Komisie ANSI a ISO, ktoré pripravujú normu jazyka C++ (označuje sa ako ANSI/ISO C++), sa opierajú predovšetkým o knihu The Annotated C++ Reference Manual od Ellisa a  Stroustrupa, vydanú v r. 1990 nakladateľstvom Addison - Wesley. Táto norma bola oficiálne prijatá až okolo roku 1996. Kompilátory jazyka C++ dnes ponúkajú všetky významné firmy (Borland - Borland C++, Microsoft - Microsoft Visual C++). V súčastnosti sa kladie veľký dôraz na objektovo orientované programovanie (OOP), podporu databáz priamo cez ovládač v operačnom systéme ODBC (Open Database Connectivity), poprípade DAO (Data Access Object) a taktiež na podporu výmeny objektov medzi aplikáciami OLE (Object Link Embedding) alebo DDE (Dynamic Data Exchange).

1.2 Štruktúra programu v jazyku C

     Základnou programovou jednotkou v jazyku C je funkcia. Veľké množstvo štandardných funkcií je predom pripravených v knižniciach prekladača. Tieto funkcie vychádzajú na jednej strane z príslušnej normy ANSI, na druhej strane z "kuchyne" firmy - autora kompilátora. Každá štandardná funkcia je spravidla sprevádzaná svojím tzv. include - súborom (jedným alebo viacerými). Tento súbor má príponu .h od slova header (hlavička) a  obsahuje súhrn informácií o určitej skupine štandardných funkcií (ich definície, globálne premenné a pod). Do zdrojového textu programu sú tieto súbory zaradené pomocou príkazu preprocesora #include (podrobnejšie viď kap. 2). Rovnakým spôsobom môžu byť do zdrojového textu programu zaradené užívateľom definované funkcie (podprogramy), ktoré je tiež možné združovať do knižnice.
     Ďalším objektom, ktorý sa môže vyskytovať v štruktúre programu v jazyku C, sú globálne dátové objekty, ktoré sú dostupné vo všetkých funkciách daného programu. Doporučujeme však použitie týchto globálnych premenných vynechať, resp. obmedziť, pretože zhoršujú možnosti štruktúrovania programu.
     Program v jazyku C je teda súhrnom definícií funkcií a deklarácií globálnych objektov. Jedna z funkcií sa musí volať main (označuje hlavný program). Jazyk C je typický svojou blokovou štruktúrou (napr. telo každej funkcie tvorí jeden blok). Blokom je zdrojový text, uzavretý v dvojici zátvoriek {, }. V rámci bloku je možné pracovať s globálnymi i lokálnymi premennými, ktoré sú definované len v rámci bloku (lokálne môžu byť len dátové objekty, všetky funkcie sú vždy globálne).

Štruktúra programu v jazyku C má teda obecný tvar :

  1. Skupina hlavičkových súborov štandardných funkcií.
  2. Definície užívateľských funkcií.
  3. Deklarácie globálnych premenných.
  4. Funkcia main.
  5. Ostatné užívateľské funkcie.

     Štandardné knižničné funkcie, ktoré sa vyskytujú v zdrojovom texte programu (časť IV, resp. V), sú v celkovej štruktúre programu reprezentované svojimi hlavičkovými súbormi, spravidla uvedenými na začiatku programu (časť I).
     Najjednoduchší úvodný program pre výpis textu na obrazovku má tvar :


/*  priklad p1_1.c  uvodny program  */
#include <stdio.h>

main()
{
  printf("ahoj\n");
}

a pozostáva teda len z časti I (1. riadok) a časti IV, ktorá je tvorená jedinou štandardnou funkciou printf. Jej definícia je uvedená v súbore stdio.h. Pred programom je jeden riadok komentára.
     Ďalší príklad vykonáva kopírovanie znaku zadaného z klávesnice (štandardný vstup) na obrazovku (štandardný výstup). Kopírovanie je ukončené zadaním znaku medzera na vstupe. Príklad je uvedený v piatich postupne sa vyvíjajúcich verziách, ktoré dokumentujú základné črty a spôsoby práce v jazyku C (viď príklady pr1_2.c až pr1_6.c). Čítanie znaku zo vstupu vykonáva štandardná funkcia getchar, výstup znaku funkcia putchar. Obidve sú popísané v súbore stdio.h. Prvá verzia príkladu využíva opakovanie pomocou príkazu goto, druhá využíva štandardný príkaz while. V tretej verzii je vytvorený podprogram - funkcia copy, ktorá vykonáva samotné kopírovanie a v hlavnom programe je iba vyvolaná (bez prenosu parametrov). V štvrtej verzii sa okrem toho spočítavajú kopírované znaky a v hlavnom programe sa vypíše ich počet. Posledná verzia je doplnená ešte pomocnými výpismi na obrazovku. Kopírované znaky sú vypísané dvakrát (raz príkazom printf, druhý krát príkazom putchar).

príklad pr1_2.c
/*  pr1_2.c  kopirovanie znaku z klavesnice na obrazovku   */

#include <stdio.h>

void main(void)
{
  char z;

znovu:
  z=getchar();
  if(z != ' ')
  {
    putchar(z);
    goto znovu;
  }
}




príklad pr1_3.c
/*  priklad pr1_3.c  kopirovanie znaku z klavesnice na obrazovku   */

#include <stdio.h>

void main(void)
{
  char z;

  while((z=getchar())!=' ') putchar(z);
}




príklad pr1_4.c
/*  priklad pr1_4.c  kopirovanie znaku z klavesnice na obrazovku

podprogram copy  */
#include <stdio.h>

void copy(void);

void main(void)
{
 copy();
}

void copy(void)
{
  char z;

  while((z=getchar())!=' ') putchar(z);
}




príklad pr1_5.c
/*  priklad pr1_5.c  kopirovanie znaku z klavesnice na obrazovku

podprogram copy + pocitanie znakov  */
#include <stdio.h>

int copy(void);
void main(void)
{
  printf("Pocet nacitanych znakov:%d\n",copy());
}

int copy(void)
{
  char z;
  int pocet=0;

  while((z=getchar())!=' ')
  {
    pocet++;
    putchar(z);
  }
  if(z==' ')putchar(z);
  return(pocet);
}




príklad pr1_6.c
/*  priklad pr1_6.c  kopirovanie znaku z klavesnice na obrazovku

podprogram copy + pocitanie znakov + texty */
#include <stdio.h>

int copy(void);

void main(void)
{
  printf("\nPocet nacitanych znakov:%d\n",copy());
}

int copy(void)
{
  char z;
  int pocet=0;

  printf("Zadaj znaky (koniec medzera a Enter):\n");
  while((z=getchar())!=' ')
  {
    pocet++;
    printf("\n%d. znak:%c",pocet,z);
    putchar(z);
  }
  if(z==' ')putchar(z);
  return(pocet);
}