1 / 146

Programov ání v jazyce C

Programov ání v jazyce C. RND r. Jan Lánský, Ph.D. Katedra softwarového inženýrství MFF UK Katedra informatiky V Š FS (Autor původní verze slajd ů : RNDr. Filip Zavoral, Ph.D.) zizelevak@gmail.com http://kocour.ms.mff.cuni.cz/~lansky/. Studijní povinnosti. Zápočet

Download Presentation

Programov ání v jazyce C

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Programování v jazyce C RNDr. Jan Lánský, Ph.D. Katedra softwarového inženýrství MFF UK Katedra informatiky VŠFS (Autor původní verze slajdů: RNDr. Filip Zavoral, Ph.D.) zizelevak@gmail.com http://kocour.ms.mff.cuni.cz/~lansky/

  2. Studijní povinnosti • Zápočet • aktivní účast na cvičeních • během semestru 'domácíúkoly' (krátké prográmky) • 2 povinné • 2 dobrovolné (nejsou podmínkou zápočtu, ale lze je použít u zkoušky) • Zkouška • Musíte mě přesvědčit o vašich znalostech • Ústní na základě přípravy napsání programu • na PC s možností použít domácí úkoly (povinné i dobrovolné) • žádná další literatura (s výjimkou nápovědy) není povolena

  3. Obsah předmětu • Programování v jazyce C OOP (v C++) • ZSLS C++ C++ C C Nejdůležitější: vlastní praxe Na přednáškách se nikdo nikdy programovat nenaučil

  4. Obsah přednášky Přednáška • Překlad programů, spojování • Základní vlastnosti C a C++, odlišnosti od jiných prog. jazyků • Datové typy, operátory a řídící konstrukce • Pole a ukazatele • Standardní knihovny • Programování není zápis algoritmů Cvičení • Praktické programování • Microsoft Visual Studio .NET 2008 • Ladění programů (!) • Prosíím, já jsem napsal program a ono to řeklo 'Váš program provedl neplatnou instrukci a bude ukončen '. Co mám dělat?

  5. Pascal vs. C++ • Úvod do Programování, Programování • heslo: programování = zápis algoritmů • algoritmické myšlení, algoritmizace problému • soustředění se na řešení problému • formulace algoritmu a jeho zápis v nějakém formalismu (jazyku) • základní datové a řídící struktury • nedůležité: kontrola vstupů, uživatelské rozhraní, obedněnost, vazba na OS a HW, přenositelnost, optimalizace, udržovatelnost • výuka (v) Pascalu • dobrý jazyk pro zápis algoritmů • nezatěžuje technickými detaily (alokace paměti, vazba na OS, ...) • slabá podpora pro kontrolu vstupů, uživatelské........

  6. Pascal vs. C++ • Programování v jazyce C++, OOP • heslo: programování = vývoj software • důležité: kontrola vstupů, uživatelské rozhraní, obedněnost, vazba na OS a HW, přenositelnost, optimalizace, udržovatelnost • zvládnutí knihoven a vývojových nástrojů • výuka (v)C++ • standardní jazyk pro vývoj software • další jazyky vycházejí z C++ (Java, C#, ...) • dobrá podpora pro kontrolu vstupů, uživatelské........ • nutnost zvládnout technické detaily (alokace paměti, vazba na OS..) • velké množství hotového kódu (knihovny, komponenty, ...) 'Vše' již bylo naprogramováno

  7. Literatura • Základní učebnice a popis jazyka • Miroslav Virius: Programování v C++ (ČVUT, 2. vydání 2004) • Miroslav Virius: Pasti a propasti jazyka C++ (Brno, 2. vydání 2005) • Bjarne Stroustrup: The C++ Programming Language (3rd ed.) • Bruce Eckel: Myslíme v jazyku C++ (Thinkinkg in C++ 2nd ed.) • C++ In-depth aneb Jak správně C++ používat - pro ty, kdo již C++ nějak znají • Scott Meyers: Effective C++ (2nd ed.), More Effective C++ • Herb Sutter: Exceptional C++, More Exceptional C++ • Andrew Koenig, Barbara E. Moo: Accelerated C++ Practical Programming by Example • Nicolai Josuttis: The C++ Standard Library – A Tutorial and Reference • James Coplien:Advanced C++ Programming Styles and Idioms • Que: ANSI/ISO C++ Professional Programmer's Handbook • Andrei Alexandrescu: Modern C++ DesignGeneric Programming and Design Patterns Applied • Normy • ISO/IEC 9899: Programming languages - C (1999) • ISO/IEC 14882, ANSI:Programming languages - C++ (1998, 2003)

  8. Nevhodná literatura - nepoužívat! • Martin Beran: Učebnice Borland C++ - hrubé chyby • Jan Pokorný: Rukověť uživatele Borland C++ - staré, BC 3.1 • Vladimír Rudolf: ABC programátora v C++ - neúplné, zastaralé • Dirk Louis: C und C++ — Programierung und Referenz - chyby • Dalibor Kačmář: Jazyk C — učebnice pro střední školy – chyby • Brodský, Skočovský: Operační systém Unix a jazyk C – neúplné, zastaralé • Eric Gunnerson: Začínáme programovat v C# – C# není C++

  9. Historie • 1970-73 první verze C, společný vývoj s UNIXem • 1973přepsání jádra UNIXu do C • 1978 Kerninghan, Ritchie:The C Programming Language • 1980 standardy – ANSIX3J11, od r. 1999 ISO 9899 • 1980 AT&T - "C with Classes" • 1983poprvé název C++ (Rick Mascitti) • 1985 Stroustrup: The C++ Programming Language • 1989 ANSI X3J16 norma C++ • 2003nejnovější ISO/ANSI normaC++ • Normy se vyvíjí, aktuální překladače o několik let zpět • Implementace novinek často nekorektní nebo neefektivní (STL)

  10. hello.c • #include <stdio.h>#include <conio.h> • int main( int argc, char ** argv){ printf( "Hello\n");getch(); return 0;}

  11. hello.c • #include <stdio.h>#include <conio.h> • int main( int argc, char ** argv){ printf( "Hello\n");getch();return 0;} direktiva preprocesoru vložení souboru deklarace knihovních funkcí hlavička funkce název funkce typ návratové hodnoty formální parametry tělo funkce skutečné parametry příkaz volání funkce bez parametrů složené závorky BEGIN END

  12. Struktura programu • Program se skládá z modulů • Překládány samostatně kompilátorem • Spojovány linkerem • Modul z pohledu programátora • Soubor s příponou .cpp (.c) • Hlavičkové soubory • Soubory s příponou .h • Deklarují (a někdy i definují) identifikátory používané ve více modulech • Vkládány do modulů direktivou include • Direktivu zpracovává preprocesor čistě textově • Preprocesor je integrován v kompilátoru jako první fáze překladu • Modul z pohledu kompilátoru • Samostatná jednotka překladu • Výsledek práce preprocesoru

  13. Překlad jednoho modulu a sestavení knihovny standardní i jiné knihovní headery .h .obj .obj .obj .obj .obj .lib spustitelný program .cpp CC .obj Link .exe spojování (linkování) objektový modul (přeložený kód) kompilace

  14. Oddělený překlad - dělení na moduly • Modul - ucelená funkčí jednotka • modul.cpp (.c) - implementace • modul.h - definice rozhraní rozdělení projektu do modulů a vytváření headerů je umění, nedá se to naučit na přednášce fotbal.h hriste.h hrac.h mic.h fotbal.cpp hriste.cpp hrac.cpp mic.cpp

  15. Překlad více modulů – oddělený překlad vlastní headery knihovní headery knihovny .h .h .obj .obj .obj .obj .obj .lib .c CC .obj Link .exe kompilace jednoho modulu .obj .obj .c .obj .c .c další moduly

  16. Překladače a vývojová prostředí • Windows - překladač součástí integrovaného prostředí • MS Visual Studio - Visual C++(VC6.0, .Net, .Net2008) • integrovaný make, linker, debugger • klikabilní konfigurace • další překladače - Borland C++ Builder, Intel, Watcom • Unix (Linux) - samostatné programy, příkazová řádka • gcc • make - pro 'opravdové' programátory • pokusy o vývojová prostředí (kDevelop) raději nepoužívat

  17. Integrované vývojové prostředí .h .h .obj .obj .obj .obj .obj .lib .c .obj .c .obj CC Link .exe .obj .c editor debugger projekt

  18. Make .h .h .obj .obj .obj .obj .obj .lib .c .obj .c .obj CC Link .exe .obj .c makefile make

  19. Program a modul • Program v C++ nemá (vnořovanou) blokovou strukturu • Neexistuje "hlavní blok" • Běh programu začíná vyvoláním funkce main • Před funkcí main běží inicializace běhového prostředí, po ní úklid • Funkce main musí mít tuto hlavičku: • int main( parametry příkazové řádky) • Modul: posloupnost globálních deklarací a definic • Deklarace • Oznámení překladači, že identifikátor existuje • Určení některých vlastností (typ, parametry) • Definice • Doplnění zbývajících vlastností (kód funkce, obsah struktury) • Překladač vygeneruje kód funkce, vyhradí místo pro proměnnou

  20. Funkce vnořené funkce nelze! • Základní programová jednotka je funkce • Neexistují vnořené funkce • Začátek programu – funkce main int fce2( int a) { int fce1(int x, int y) { return x+y; } return fce1( 2*a+17); } hlavička funkce int fce1(int x, int y) { return x+y; } int fce2( int a) { return fce1( 1, 2*a+5); } int main( int argc, char** argv) { ... } tělo funkce začátek programu argumenty z příkazové řádky později

  21. Funkce - návratový typ • Typ funkce = typ návratové hodnoty • Hodnota se vrací pomocí klíčového slova return • Speciální typ void - 'prázdný' typ • ekvivalent procedury Pascalu voidfce2( char* text) { printf( text); } voidfce3( char* text) { if( ! text) return; printf( text); } typ funkce intfce1(int x, int y) { returnx+y; } návrat z funkce návrat celočíselné hodnoty

  22. Parametry funkce • Pevný počet, pevný typ • možnost proměnného počtu parametrů - printf • Parametry jsou odděleny čárkou • U každého parametru musí být uveden jeho typ • Funkce bez parametrů - void každý parametr musí mít typ int fce1(int x, int y, float z) { ... } int fce2( double a, char* str) { ... } int fce3( void) { ... } int fce4(intx, y) { ... } int fce5 { ... }

  23. Volání funkce • Shoda počtu formálních a skutečných parametrů • Kompatibilita typů formálních a skutečných parametrů • I funkce bez parametrů musí obsahovat operátor () • Návratová hodnota - lze ignorovat int fce1(int x, int y, float z) { ... } int fce3(void) { ... } int fce2( int a) { fce1( a, 1, a); fce3(); return 0; } int fce4(int x, int y, float z) { ... } int fce5( int a) { fce4; fce4( a, 1); fce4( a, 1, "ahoj"); }

  24. Lokální proměnné • Definice lokálních proměnných • C: na začátku těla funkce(přesněji: na začátku bloku) • C++: kdekoliv v těle funkce • Možná inicializace – při každém běhu funkce • neinicializovaná proměnná – náhodná hodnota !!! deklarace celočíselných proměnných int fce( void) { int p; int q, r; int s = 5; int x, z = 0, y; return z + x; } deklarace s inicializací náhodná hodnota !!!

  25. Příklad - malá násobilka definice knihovních funkcí hlavička funkce, formální parametr #include <stdio.h> int vynasob( int c) { int i = 1, v; if( c < 1 || c > 10) return -1; while( i <= 10) { v = i * c; printf( "%d * %d = %d\n", i, c, v); i = i + 1; } return 0; } int main() { int cislo = 7; vynasob( cislo); return 0; } neinicializovaná proměnná inicializovaná celočíselná proměnná okanžitý návrat z funkce kontrola parametrů 2 * 7 = 14 začátek cyklu i++ konec cyklu konec, OK hlavní program konec, OK ignorování návratové hodnoty volání funkce se skutečným parametrem The END

  26. Předávání parametrů hodnotou • Všechny parametry se předávají hodnotou • 'Výstupní' parametry pouze přes ukazatele nebo reference voidswap(int x, int y) { int pom; pom = x; x = y; y = pom; } void fce(void) { int a = 1; int b = 2; int c = 0; swap( a, b); c = 2 * a + b; } vymění se jen lokální proměnné funkce předají se pouze hodnoty (1, 2), nikoliv 'proměnné'

  27. Globální proměnné • Definice mimo tělo funkce • Viditelné v jakékoliv funkci • Možná inicializace – při startu programu • Používat s rozvahou!! • pouze pro sdílená data globální proměnná formální parametr int g = 1; void fce( int x) { int z = 2; g = g + z * x; } int main( void) { fce( 2); fce( 3); return g; } lokální proměnná co vrátí main ?? skutečný parametr

  28. Výraz • Norma: "Výraz je posloupnost operací a operátorů specifikující výpočet hodnoty" • Přiřazovací 'příkaz' je také výraz • jeho hodnotou je přiřazovaná hodnota • Výrazy mohou mít vedlejší efekty 1 a+b*sin(x) printf( "Ahoj") q = &b[17]+*p++ "retezec" a = b = 0; if( (x = fnc()) != 0) ... užitečné: test přiřazované hodnoty

  29. Příkaz • Příkaz je • výraz ukončený ';' (středníkem) • složený příkaz- posloupnost příkazů mezi '{' a '}' • programová konstrukce • if, if-else, switch, while, do-while, for, break, continue, return, goto 1; a+b*sin(x); printf( "Ahoj"); q = &b[17]+*p++; "retezec"; { 1; a+b*sin(x); printf( "Ahoj"); q = &b[17]+*p++; "retezec"; } jeden složený příkaz

  30. Podmíněný příkaz • if(výraz)příkaz • if(výraz)příkazelsepříkaz if( a > 1) { b = 0; printf( "OK"); } else { printf( "nee"); } syntakticky správně, ale dělá něco jiného if( a > 1) printf( "OK"); if( a > 1) b = 0; printf( "OK"); if( a > 1) printf( "OK"); else printf( "nee"); if( a > 1){ b = 0; printf( "OK"); }else{ printf( "nee"); } if( a > 1) b = 0; printf( "OK"); else printf( "nee"); syntakticky špatně

  31. Vnořené podmíněné příkazy Syntakticky správně, ale nepřehledné Na pohled nejasné párování if( a > 1) if( b > 0) printf( "OK"); else printf( "nee"); if( a > 1){ if( b > 0) printf( "OK"); } else { printf( "nee"); } if( a > 1){ if( b > 0) printf( "OK"); else printf( "nee"); } U vnořených podmínek vždy používat { }

  32. Vícenásobné větvení – konstrukce switch zapomenutý break syntakticky OK, ale dělá něco jiného • switch(výraz){ • casekonstanta: • posloupnost příkazů • break; • casekonstanta: • casekonstanta: • posloupnost příkazů • break; • default: • posloupnost příkazů • } switch( errc) { case 0: b = 0; printf( "OK"); break; case -1: printf( "trochu spatne"); break; case -2: case -3: printf( "hodne spatne"); break; default: printf( "jina chyba"); break; } celočíselný výraz switch( errc) { case 0: b = 0; printf( "OK"); case -1: printf( "spatne"); break; } ukončení větve switch( ch) { case '0'..'9': x += ch - '0'; break; case 'A'..'F': x += ch - 'A'; break; } pokud výraz není roven žádné z konstant interval nelze

  33. Cyklus – konstrukce while a do-while • while(výraz)příkazpodmínka na začátku • do příkazwhile(výraz) ;podmínka na konci Pozor! cyklus pokračuje pokud je podmínka platná while( a > 1) a = a / 2; tělo se vždy alespoň jednou provede do { fce( a); a = a / 2; } while( a > 1); while( a > 1) { fce( a); a = a / 2; }

  34. Cyklus – konstrukce for • for(výraz1;výraz2;výraz3)příkaz • je ekvivalentem • výraz1; • while(výraz2) { • příkaz • výraz3; • } inicializace podmínka inkrement tělo cyklu ekvivalent v jiném jazyce for( i=0; i<=9; i=i+1) { fce( i); } FOR I := 0 TO 9 DO FCE(I) i=0; while( i<=9) { fce( i); i=i+1; } jako inicializaci, podmínku i inkrement lze libovolný výraz for( init(a); i<9&& a[i] >0; a[i++]=i*2) { fce( i); } for v C++: obecnější, širší možnosti použití

  35. Ukončení cyklu - break, continue • breakokamžité ukončení celého cyklu • cyklus s podmínkou uprostřed • ošetření chybových stavů • continueukončení (jednoho) běhu těla cyklu for(;;) { errc = fce(); if( errc < 0) break; jinafce(); } n = 1; while( n<1000) { val = get(); if( val == 0) continue; n = n * val; }

  36. Goto • Nepoužívat! .... pokud k tomu není dobrý důvod • Když už, tak pouze dopředu (skok dozadu = cyklus) • Dobrý důvod: výskok z vícenásobně vnořených cyklů nelze break - ukončil by pouze vnitřní cyklus, vnější cyklus by pokračoval for( i=0; i<10; i++) { for(j=0; j<10; j++) { if( fnc( i, j) == ERROR) goto konec_obou_cyklu; } } konec_obou_cyklu: dalsi_funkce(); label návěští

  37. Celočíselné typy • Základní celočíselné typy jsou znaménkové • Pro každý typ existuje unsigned varianta • možné využití unsigned: unsigned char, pole bitů, modulová aritmetika • pokud není dobrý důvod, unsigned raději nepoužívat • char  short  int  long  long long • size_t, ptrdiff_t, wchar_t -2GB .. +2GB

  38. Logické a znakové hodnoty a typy • C: Až do r. 1999: neexistuje typ 'boolean' • Porovnání a logické operátory jsou celočíselné výrazy • FALSE(nepravda) 0 • TRUE(pravda) 1 (libovolná hodnota různá od 0) • důsledek: • if( x != 0)  if( x) • if( x == 0)  if( !x) • C++, C99 • celočíselnýtyp bool (C99:_Bool) • hodnoty true (=1), false (=0) • charnorma neurčuje signed / unsigned • korektní porovnání na nerovnost pouze 0 .. 127 • 'a' < 'ž' ? • signed char -128 .. 127 • unsigned char 0 .. 255 - 'byte' • wchar_t stddef.h: znakrozšířené sady (Unicode) časté použití: test (ne)nulovosti např. ukazatelů záleží na implementaci většinou char = signed 40 > 200 !!!200 -56

  39. Výčtový typ • enum pohlavi { p_muz, p_zena }; • pohlavi p = p_muz; • int pp = p_zena; • pohlavi q = 0; • enum flags { f1 = 1, f2 = 2, f3 = 4, f4 = 8 }; • if( x & f1) • ... • enum porty { pop3 = 111, ftp = 21, smtp = 80 }; hodnoty doplní překladač (od 0) C: celočíselné konstanty - OK C++: samostatný typ - nelze test bitů explicitní hodnoty

  40. 'Reálné' typy • float  double  long double Pozor! Reálné výpočty jsou vždy nepřesné zvýšená přesnost double x = 1; double y = x / 3; if( x == 3 * y) printf( "Presne"); else printf( "Nepresne"); malá přesnost - nepoužívat! standard pro 'reálné' výpočty pro přesné hodnoty používejte přesné typy raději nepoužívat pouze pro fyzikální nebo numerické veličiny double zustatek = 15.60; long zustatek_v_halerich = 1560;

  41. Číselné konverze • Automatické konverze (integral promotions) • Výpočty výrazů a předávání parametrů vždy v šíři alespoň int • signed char, unsigned char, signed short  signed int • unsigned short  signed int (pokud je int delší) / unsigned int • Automatické konverze u binárních operací • signed int  unsigned int  signed long  unsigned long   float  double  long double vždy když je použit menší typ než int při nestejných operandech

  42. Přehled operátorů, asociativita a priorita

  43. Základní aritmetické operátory • + - * / % • podle typu operandů  automatická konverze na větší typ • % - modulo int x=5, y=3; double a=5, b=3; modulo je pouze celočíselná operace celočíselné dělení reálné dělení

  44. Bitové a logické operátory • &| ^~ - bitové operace AND, OR, XOR, NOT • && || !- logické operace AND, OR, NOT oba op.  0 5 = 01012 3 = 00112 1 = 00012 7 = 01112 9 = 10012 15 = 11112 10 = 10102 alespoň jeden operand  0 neexistuje alespoň jeden operand = 0

  45. Zkrácené vyhodnocování, relační operátory • a && b - je-li a=0, b se nevyhodnocuje, výsledek = false (0) • a || b - je-li a=1, b se nevyhodnocuje, výsledek = true (1) • < <= >= > • == != • výraz typu int(bool) - výsledek vždy 0 nebo 1(false, true) • porovnávání na (ne)rovnost float/double ! • porovnání vs. přiřazení ! test mezí pole před přístupem k prvku pole int x[10]; // pole 0..9 if( i < 10 && x[i] != 0) y = y / x[i]; if( x==y && *x++) ... Pozor! operátory s vedlejšími efektyse nemusí provést ! POZOR!!!Přiřazení! (zde hodnota vždy = 1) if( x = 1) ...

  46. Přiřazení, inkrementace, bitový posun • = • += -= *= /= %= &= |= ^= <<= >>= • kombinované přiřazení • a op= b  a = a op b • ++ -- • a++a = a + 1, výsledkem je stará hodnota a • ++a a = a + 1 , výsledkem je nová hodnota a • přesněji: a++ (tmp = a, a = a + 1, tmp) • <<>> • bitový posun • C++ - časté použití pro jiné účely (streams) - přetěžování i += 2; x[ i+=1]/= 3; int sum = 0; int i, x[10]; ... for( i=0; i<9; sum += x[i++]) ; pozor - vždy si uvědomit, zda jde o pre- nebo post- inkrementaci

  47. Podmíněný výraz, sekvence • a ? b : c • po vyhodnocení podmínky a se vyhodnotí buď b (je-lia != 0) nebo c (je-li a == 0) • a , b • po úplném vyhodnocení a se vyhodnotí b ternární operátor if (y>0) x =y; else x = 0; x =(y>0 ? y : 0); operátor sekvence ('zapomnění') x =(tmp = y, y = y + 1, tmp); ekvivalentx = y++;

  48. Pravidla vyhodnocování • a( b,c)vedlejší efekty parametrů jsou vyhodnoceny před zavoláním fce • a && bje-li a nulový, b se nevyhodnocuje • a || bje-li a nenulový, b se nevyhodnocuje • a ? b : cpo vyhodnocení a se vyhodnotí buď b nebo c • a , bpo úplném vyhodnocení a se vyhodnotí b • Žádná další pravidla nejsou • ostatní operátory jsou vyhodnocovány v libovolném pořadí • vedlejší efekty se mohou projevit kdykoliv během výpočtu • možné výsledky: • p[0] = 0; • p[1] = 0; • p[0] = 1; i = 0; p[ i++] = i++;

  49. Fungující triky vs. chyby • Fungující triky • Test ukazatele • while ( p && p->v < v ) • p = p->next; • Volání funkce s vedlejším efektem • while ( (c = getchar()) != EOF && c != '\n' ); • Kopie řetězce • while ( *a++ = *b++ ); • Chyby • Vícenásobný výskyt modifikované proměnné • p[ i++] = i++; • Nadbytečné volání funkce s vedlejším efektem • if ( getchar() == 'A' && getchar() == 'B' ) nevím, jestli se provede

  50. Pole • Indexy polívždy začínají od 0 ! • Při přístupu se nikdy nekontrolují meze!!! • Deklarace: t x[n] - pole x o n prvcích (0..n-1) typu t • Vícerozměrné pole je pole polí • Deklarace: t x[m][n]; • Přístup: x[m][n] = a; Přepis náhodného místa v paměti ! Nepředvídatelné následky !! int x[5]; for( i=1; i <=5; i++) x[i] = i; význam: m-prvkové pole typu (n-prvkové pole typu t) int x[8][8]; for( i=0; i < 8; i++) for( j=0; j < 8; j++) x[ i ] [ j ] = i * j; Pozor!x[m,n]není prvek dvojrozměrného pole o souřadnicích m a n čárka = operátor sekvence

More Related