Projektová výuka OOP s využitím C++ jazyka Ing.Jindřich Petrucha Ph.D.
1
Obsah 1.Úvod .................................................................................................................................... 2 2. Příklady zaměřené na aplikaci vědeckotechnického výpočtu............................................ 4 3. Příklady zaměřené na aplikaci cyklu a číselné řady.......................................................... 13 4. Příklady zaměřené na práci s polem ................................................................................ 20 5. Příklady zaměřené na práci s polem záznamů jako databází........................................... 34 Souhrnný projekt................................................................................................................. 41 6. Aplikace PHP jazyka OOP varianta ...................................................................................... 43 6.1 PHP Příklady zaměřené na aplikaci vědeckotechnického výpočtu ............................... 44 6.1.1 Zadání příkladu –PHP OOP výpočet plochy kruhu .................................................. 44 6.1.2 Zadání příkladu –PHP OOP plocha a obvod kruhu .................................................. 45 6.1.3 Zadání příkladu -PHP OOP kruh výstup v tabulce ................................................... 47 6.1.4 Zadání příkladu –PHP OOP výpočet kruhu v cyklu ................................................. 49 6.1.5 Zadání příkladu –PHP OOP výpočet obdelníku s formulářem HTML ...................... 51 6.1.6 Zadání příkladu –PHP OOP výpočet obdelníku a kruhu – volání různých tříd ........ 54 6.2 PHP OOP - výpočty pro numerickou matematiku – výpočet integrálu.......................... 56 6.2.1 Zadání příkladu – PHP OOP výpočet určitého integrálu ......................................... 56 7. Aplikace variannty OOP s použitím Microsoft visual studio 2008 ...................................... 61 8. OOP C++ projekty s využitím numerických metod............................................................... 78 8.1 C++ numerický výpočet určitého integrálu .................................................................... 78 8.1.1 C++ Obdelníková metoda........................................................................................ 78 8.1.2 C++ lichoběžníková metoda .................................................................................... 82 8.1.3 C++ simpsonova metoda ......................................................................................... 86 8.2 Numerické metody pro hledání kořenů funkcí .............................................................. 90 8.2.1 C++ metoda půlení intervalu................................................................................... 90 8.2.2 C++ metoda tečen ................................................................................................... 93 8.2.3 C++ metoda sečen ................................................................................................... 95 8.2.3 kontrolní otázky....................................................................................................... 97 9. Závěr ..................................................................................................................................... 98 Použitá literatura...................................................................................................................... 98
1.Úvod Jednotlivé kapitoly jsou zaměřeny na vysvětlení použití jednotlivých příkazů C++ jazyka v programu, který realizuje zadané požadavky. Základní požadavky jsou zadány velmi obecně 2
a cílem je vysvětlit postup, který vede k vytvoření objektů pomocí tříd OOP, které realizují zadané požadavky. Při analýze je použita metoda dekompozice na menší celky, ze kterých je možné naprogramovat členské funkce. Tyto členské funkce realizují pomocí vnitřních proměnných navržený algoritmus. Jednotlivé algoritmy jsou popsány pomocí textu, který vysvětluje postup jednotlivých kroků, které směřují pro dosažení řešení. Některé algoritmy realizují postupy numerické matematiky pro získání potřebného řešení. Cílem je naučit studenta přemýšlet o realizaci těchto algoritmů v členských funkcích jednotlivých tříd a navrhnout proměnné, které tyto algoritmy provádějí. V závěru jednotlivých příkladů je část věnovaná testování programu s ukázkou vstupů a výstupů dat. V této oblasti se studenti mají zamyslet nad smyslem výsledků, nad přesností dosaženou pomocí počítače. Některé výstupy dat nejsou prováděny na obrazovku, ale jsou zapisovány do souborů tak bylo možné uchovávat výsledky programů pro další potřebné akce. Z jednotlivých příkladů vychází zadání celkového projektu, na kterém by měl student ukázat na schopnost syntézy jednotlivých prvků do společného celku, ve kterém realizuje cílový softwarový produkt. Součástí závěrečného projektu je dokumentace vysvětlující jednotlivé části a postupy, které vedly k výslednému řešení.
3
2. C++ příklady zaměřené na aplikaci vědeckotechnického výpočtu Jednotlivé příklady ukazují na možnosti aplikace algoritmu postupného výpočtu jedné nebo více hodnot podle určitého vzorce. Algoritmus předpokládá zadání hodnoty ze vstupu, buď z klávesnice, nebo ze souboru a provedení výpočtu s využitím aritmetických operátorů a matematických funkcí. Z hlediska problému výpočtu je zde nutné uvažovat o správnosti vstupů, které jsou často omezeny a zajištění jejich správnosti může být složitější než samotný algoritmus výpočtu. Jednotlivé příklady postupují od jednoduchých variant ke složitějším s ukázkou vytváření tříd a jednotlivých objektů pro výpočet.
2.1 Zadání příkladu C++ výpočet obdelníku Vypočtěte plochu obdélníku při zadání jedné strany obdélníku z klávesnice a druhá strana je konstantně zadána hodnotou 10. Strany obdélníku jsou celá čísla. Cíl Ukázka funkcí pro vstup dat z klávesnice a výstup dat na obrazovku. Použití varianty cout cin s ukázkou konce řádku. Analýza Pro výpočet použijeme vzorec obsah = a * b; stranu a zadáme z klávesnice a strana b bude přiřazena při deklaraci proměnné. Použité vzorce obsah = a * b; Použité algoritmy Sekvenční postup shora dolů, zadání hodnoty z klávesnice a provedení výpočtu do proměnné obsah. Hodnota se zobrazí po výpočtu pomocí povelu cout. Zdrojový kód program #include
using namespace std; int main() { int a; //Vytvori celociselnou promennou typu int int b = 10; //promenne prirazena hodnota 10 int obsah;
4
cout << "Zadejte stranu a obdelniku: "; cin >> a; //priradi promenne vyska hodnotu obsah = a * b; cout << "\nObsah obdelniku je " << obsah; cout << "\n"; system("PAUSE"); //zastaveni vypisu a cekani na stisk klavesy return 0; }
Vstupy a výstupy dat
Na obrazovce je znázorněna hodnota vstupu strany a na dalším řádku se nachází výpočet jako výstupní hodnota. Hodnota strany obdélníku není testovaná na číselnou hodnotu ani rozsah.
2.2 Zadání příkladu C++ - koule Vypočtěte povrch a objem koule s využitím členských funkcí objektově orientovaného programování. Jako vstupní parametr použijte poloměr koule. Výstupní hodnoty vypište na obrazovku. Cíl Použít členské funkce s určitou třídou s ukázkou vstupní hodnoty poloměr do proměnné deklarované v určité třídě a použití jednotlivých členských funkcí ve výpočtu. Analýza Použijeme vytvoření třídy s názvem koule a dále definujeme dvě členské funkce objem a plocha, které budou pracovat s proměnnou poloměru, která bude deklarována jako public /veřejná v naší třídě/. Další členskou funkcí bude vložení poloměru koule do proměnné v definované třídě. Od třídy koule v hlavním programu vytvoříme instanci třídy k1, která bude pracovat s jednotlivými členskými funkcemi. V hlavním programu je zadání vstupního parametru koule z klávesnice. 5
Použité vzorce Vzorec pro objem koule
Vzorec pro povrch
Použité algoritmy • • • • • •
Sekvenční postup shora dolů Zobrazení textu pro zadání vstupní hodnoty poloměru Zadání poloměru Vložení do proměnné v instanci třídy Provedení výpočtu pomocí členské funkce Zobrazení výsledku
Zdrojový kód program //priklad pro objem a plochu koule #include using namespace std; class koule { public:
//oznaceni tridy OOP // veřejně přístupna data
double r; //polomer koule //prototypy jednotlivych clenskych funkci double objem(); double povrch(); void zadej(double polomer); };
double koule::objem() //clenska funkce koule { double vypocet; vypocet=4/3*3.14*r*r*r; return vypocet; } double koule::povrch() //clenska funkce koule { double vypocet; vypocet=4*3.14*r*r; return vypocet; } void koule::zadej(double polomer) {
6
r=polomer; } //hlavni program int main() { double hodnota; //hodnota plomeru koule koule k1; //instance objektu koule cout << "vloz polomer koule: " << endl; cin >>hodnota; k1.zadej(hodnota); //volani clenske funkce cout << "objem koule: " << k1.objem()<< endl; cout << "povrch koule: " << k1.povrch()<< endl; system("PAUSE"); }
Vstupy a výstupy dat
Na obrazovce je znázorněna hodnota zadaného poloměru koule a vypočtené hodnoty povrchu a objemu koule. Výstupní hodnoty jsou formátovány pomocí funkce cout podle jednotlivých datových typů.
2.3 Zadání příkladu C++ koule s testováním vstupní hodnoty Modifikace předchozího příkladu pro výpočet povrchu a objemu koule s testováním hodnoty vstupu poloměru jako čísla většího než nula.
Cíl Vysvětlení jednotlivých členských funkcí s testem vstupní hodnoty poloměru koule v členské funkci. Aplikace třídy a instance třídy v hlavním programu. Analýza
7
Budou použity předcházející třídy z příkladu výpočtu koule. Do členské funkce pro zadání poloměru je doplněna část pro testování vstupní hodnoty pokud tato hodnota neodpovídá požadované podmínce, vypíše se text s chybovým hlášením. Použité vzorce Vzorec pro objem koule
Vzorec pro povrch
Použité algoritmy • • • • • • •
Sekvenční postup shora dolů Zobrazení textu pro zadání vstupní hodnoty poloměru Zadání poloměru Testování hodnoty vstupního parametru Vložení do proměnné v instanci třídy Provedení výpočtu pomocí členské funkce Zobrazení výsledku
Zdrojový kód programu //priklad pro objem a plochu koule #include using namespace std;
class koule { public:
//oznaceni tridy OOP // veřejně přístupna data
double r; //polomer koule //prototypy jednotlivych clenskych funkci double objem(); double povrch(); void zadej(double polomer); };
double koule::objem() //clenska funkce koule { double vypocet; vypocet=4/3*3.14*r*r*r; return vypocet; } double koule::povrch() //clenska funkce koule
8
{ double vypocet; vypocet=4*3.14*r*r; return vypocet; } void koule::zadej(double polomer) { if (polomer>=0)r=polomer; else cout << "chybna vstupni hodta polomeru koule: " <<
endl;
} //hlavni program int main() { double hodnota; //hodnota plomeru koule koule k1; //instance objektu koule cout << "vloz polomer koule: " << endl; cin >>hodnota; k1.zadej(hodnota); //volani clenske funkce cout << "objem koule: " << k1.objem()<< endl; cout << "povrch koule: " << k1.povrch()<< endl; system("PAUSE"); }
Vstupy a výstupy dat
Na obrázku jsou výstupy dat při chybném vstupu dat.
Na obrazovce je znázorněn postup nejprve s vložením chybné hodnoty parametru poloměru koule -5 a na další obrazovce je výstup objemu a povrchu koule pro případ správné hodnoty parametru. 9
2.4 Zadání příkladu C++ povrch a objem kužele Vypočtěte povrch a objem kužele při zadání vstupních parametrů z klávesnice a výstupem dat hodnot povrchu a objemu na obrazovku.
S Strana výpočet Pomocí Pythagorovi věty
Cíl Aplikace třídy pro realizaci výpočtu s více vstupními parametry a ukázka testování vstupu od uživatele pomocí cyklu v členské funkci třídy.
Analýza V třídě class kuzel vytvoříme členské funkce objem a povrch pro realizaci výpočtu podle vzorců. V členské funkci zadej_hodnoty se postupně zadají parametry výšky a poloměru kužele . V členské funkci povrch se provede výpočet s použitím vzorců a využitím vnitřních v,r typu public.
Použité vzorce objem=3.14*v*r*r; strana s= sqrt(r*r+v*v); povrch=(3.14*r*(r+s))/3;
v-výška r-poloměr Použité algoritmy 10
• • •
Zadání hodnoty Provedení výpočtu Zobrazení dat
Zdrojový kód programu //priklad pro objem a plochu kuzele #include //matematická knihovna #include <math.h> using namespace std; class kuzel { public:
//oznaceni tridy OOP // veřejně přístupna data
double r,v; //polomer kuzele a vyska //prototypy jednotlivych clenskych funkci double objem(); double povrch(); void zadej_hodnoty(); };
double kuzel::objem() //clenska funkce kuzele { double vypocet; vypocet=3.14*v*r*r; return vypocet; } double kuzel::povrch() //clenska funkce { double vypocet,s; s= sqrt(r*r+v*v); vypocet=(3.14*r*(r+s))/3; return vypocet; } void kuzel::zadej_hodnoty() //členská funkce { do // cyklus zadani pozadovane hodnoty { cout << "vloz vysku kuzele koule/0-100/: " << endl; cin >>v; if ((v<0) || (v>100))cout << "chybna vstupni hodnota " << }while((v<0) || (v>100));
endl;
do { cout << "vloz polomer kuzele koule/0-100/: " << endl; cin >>r; if ((r<0) || (r>100))cout << "chybna vstupni hodnota " << }while((r<0) || (r>100)); }
11
endl;
//hlavni program int main() { kuzel u1; //instance objektu koule u1.zadej_hodnoty(); //volani clenske funkce cout << "objem kuzele: " << u1.objem()<< endl; //vypis dat cout << "povrch kuzele: " << u1.povrch()<< endl; system("PAUSE"); }
Vstupy a výstupy dat
Na obrazovce je znázorněn postup při zadávání hodnot vstupních parametrů, nejprve chybné záporné hodnoty a dále správné hodnoty s výpočtem dat.
12
3. C ++ příklady zaměřené na aplikaci cyklu a číselné řady 3.1 Zadání příkladu C++ číselná řada Naprogramujte pomocí objektově orientovaného programování příklad, jehož výstupem je číselná řada 1 2 4 9 16 … nalezněte algoritmus pro výpis dalších členů této číselné řady a navrhněte členské funkce pro zobrazení tabulky jednotlivých členů této číselné řady. Cíl Pochopení algoritmu pro práci s cyklem a vytvoření třídy s členskými funkcemi pro vytvoření požadované řady. Analýza Vytvoříme třídu s členskou funkcí „tabulka“ s parametrem, který udává, kolik členů číselné řady chceme vytvořit. Další členská funkce provede součet členů této řady ve stejném cyklu jako byl proveden výpočet pro zobrazení jednotlivých členů této řady. Použité vzorce n-tý člen řady = n * n;
Použité algoritmy • Cyklus zobrazení řady. • Cyklus pevným n počtem opakování • V těle cyklu výpočet členu řady a zobrazení hodnoty Ukázka cyklu výpočtu int i; for (i=1;i<=pocet;i++) cout << i <<"-"<< i*i<< endl;
pro součet hodnot použit stejný typ cyklu int i,sum=0; for (i=1;i<=x;i++)sum+=i*i; cout <<"soucet " <<x << "clenu je:"<< sum<< endl;
Zdrojový kód programu //priklad pro ciselnou radu #include
13
using namespace std; class rada { public:
//oznaceni tridy OOP // veřejně přístupna data
//prototypy jednotlivych clenskych funkci void tabulka(int pocet); int soucet(int x); };
void rada::tabulka(int pocet) //clenska funkce { int i; for (i=1;i<=pocet;i++) cout << i <<"-"<< i*i<< endl; } int rada::soucet(int x) //clenska funkce { int i,sum=0; for (i=1;i<=x;i++)sum+=i*i; cout <<"soucet " <<x << "clenu je:"<< sum<< endl; } //hlavni program int main() { rada r1; //instance objektu koule cout << "zacatek programu: " << r1.tabulka(5); r1.soucet(5);
endl;
system("PAUSE"); }
Vstupy a výstupy dat
Obrázek ukazuje výstup 5 členů číselné řady.
14
3.2 Zadání příkladu C++ fibonaciho posloupnost Naprogramujte pomocí objektově orientovaného programování příklad, jehož výstupem je číselná řada fibonacciho 0,1,1,2, 3,5,8,13,.. nalezněte algoritmus pro výpis dalších členů této číselné řady a navrhněte členské funkce pro zobrazení tabulky jednotlivých členů této číselné řady. Cíl Ukázka algoritmu, ze složitější částí výpočtu jednotlivých členů číselné řady a s aplikací výpočtu součtu členů této řady. Analýza Pro výpis použijeme cyklus od třetího členu fibonacciho posloupnosti, do proměnných a,b, vložíme první dva členy a v těle cyklu provádíme postupně výpočet nového členu číselné řady. Hodnota počtu členů číselné řady bude parametrem členské funkce pro výpis řady. Použité vzorce a=x(n-2) b=x(n-1) clen=a+b Fibonacciho posloupnost je číselná řada kde každé číslo je součtem dvou předchozích čísel. První dvě čísla jsou pevně dána hodnotami 0 a 1. Řada 0,1,1,2,3,5,8,13….
Použité algoritmy Zadání prvních dvou členů číselné řady Cyklus výpočtu dalších členů řady výpočtem Po výpočtu provedení posunu v proměnných pro výpočet dalšího členu číselné řady. Ukázka klíčové části algoritmu int i,a,b; a=0; b=1; cout << 1 <<"-"<< a<< endl;//prvni clen rady
15
cout << 2 <<"-"<< b<< endl;//druhy clen rady for (i=3;i<=pocet;i++) { //vypocet clen=a+b; cout << i <<"-"<< clen<< endl; //posun clenu a=b; b=clen; }
Zdrojový kód programu //priklad pro ciselnou radu #include using namespace std; class rada_f { public:
//oznaceni tridy OOP // veřejně přístupna data
int clen; //ciselny clen rady //prototypy jednotlivych clenskych funkci void tabulka(int pocet); int soucet(int x); };
void rada_f::tabulka(int pocet) //clenska funkce { int i,a,b; a=0; b=1; cout << 1 <<"-"<< a<< endl;//prvni clen rady cout << 2 <<"-"<< b<< endl;//druhy clen rady for (i=3;i<=pocet;i++) { //vypocet clen=a+b; cout << i <<"-"<< clen<< endl; //posun clenu a=b; b=clen; } } int rada_f::soucet(int x) //clenska funkce { int i,a,b,sum=1; a=0; b=1;
16
for (i=3;i<=x;i++) { //vypocet clen=a+b; sum+=clen;//soucet dat a=b; b=clen; } cout <<"soucet " <<x << "clenu je:"<< sum<< endl; } //hlavni program int main() { rada_f r1; //instance objektu rady cout << "zacatek programu: " << r1.tabulka(10); r1.soucet(10);
endl;
system("PAUSE"); }
Vstupy a výstupy dat
Na obrazovce je znázorněno 10 členů fibonacciho posloupnosti s ukázkou součtu členů číselné řady. Úkol: Testujte kolik členů řady je schopen zobrazit správně váš počítač.
3.3 Zadání příkladu C++ tabulka výpočtu faktoriálu
17
Naprogramujte pomocí objektově orientovaného programování příklad, jehož výstupem je číselná řada faktoriálu funkce navrhněte algoritmus pro výpis dalších členů číselné řady a navrhněte členské funkce pro zobrazení tabulky jednotlivých členů této číselné řady. Cíl Ukázat výpočet faktoriálu funkce pomocí členské funkce určité třídy. Volání této funkce bude uvnitř další funkce pro výpis tabulky v cyklu. Analýza Provádění v cyklu a postupné zmenšování hodnoty n. Vytvoření dvoučlenských funkcí pro výpočet a pro realizaci součtu řady.
Použité vzorce faktorial=faktorial*n; Použité algoritmy Výpočet faktoriálu pomocí členské funkce int rada_fac::h_factorial(int n) //clenska funkce vypocet faktorialu n { int faktorial=1; while(n>0) { faktorial=faktorial*n; n--; } return faktorial; }
Vytváření řady v tabulce pomocí vnitřní funkce dané třídy. Zdrojový kód programu //priklad pro ciselnou radu #include using namespace std; class rada_fac //oznaceni tridy OOP { public: // veřejně přístupna data int clen; //ciselny clen rady //prototypy jednotlivych clenskych funkci int h_factorial(int n) ; void tabulka(int pocet);
18
};
int rada_fac::h_factorial(int n) //clenska funkce vypocet faktorialu n { int faktorial=1; while(n>0) { faktorial=faktorial*n; n--; } return faktorial; }
void rada_fac::tabulka(int pocet) //clenska funkce vypocet faktorialu n { int i; for (i=1;i<=pocet;i++) cout << i <<"-"<< h_factorial(i)<< endl; } //hlavni program int main() { rada_fac f1; //instance objektu koule cout << "zacatek programu: " << endl; cout << "hodnota faktorialu: " <<3<<"!="<< f1.h_factorial(3) << endl; f1.tabulka(5);
system("PAUSE"); }
Vstupy a výstupy dat
Na obrazovce je 5 členů řady s výpočtem faktoriálu. Úkol: Testujte kolik členů řady je schopen zobrazit správně váš počítač.
19
Faktoriál lze řešit také pomocí rekurzivního volání funkce navrhněte úpravu programu pro toto řešení problému.
4. Příklady zaměřené na práci s polem Tyto příklady ukazují možnost aplikace algoritmu s využitím pole, které uchovává prvky pole v paměti a lze s ním provádět operace dovolující abstrakci na úroveň práce s maticemi jako v matematice.
4.1 Zadání příkladu C++ třída pro práci s polem Naprogramujte pomocí objektově orientovaného programování příklad, jehož výstupem jsou hodnoty jednorozměrného pole celých čísel. Tyto hodnoty jsou nastaveny pomocí funkce z hlavního programu.
Cíl Ukázat práci s indexy pole a rozdělení činnosti v členských funkcí definované třídy. Analýza Deklarujeme pole v třídě objektu a tímto polem provádíme jednotlivé operace pomocí členských funkcí. Použité vzorce Je použito indexování prvků pole pomocí indexu pole, tento index je proměnná hodnota. Použité algoritmy Pevný cyklus typu for pro výpis hodnot pole. Zdrojový kód programu //priklad pro pole #include using namespace std; class polex { public:
//oznaceni tridy OOP // verejne pristupna data
20
int pocet; int x[10]; //data pole //prototypy jednotlivych clenskych funkci polex(); //konstruktor void vypis(); //vypise hodnoty pole na obrazovku void vloz(int n,int hodnota); //vlozi hodnotu do pole podle indexu pole }; polex::polex() //konstruktor pro pole { int i; pocet=10; for (i=0;i<pocet;i++) x[i]=0;//data pro primku }
void polex::vypis() //clenska funkce { int i; for (i=0;i<pocet;i++) cout << i <<"-"<< x[i]<< endl; } void polex::vloz(int n,int hodnota) //clenska funkce { if ((n>=0)&&(n<=pocet)) x[n]=hodnota;//test na rozsah indexu pole else cout << "error"<< endl; } //hlavni program int main() { polex prac; //instance objektu pro data grafu a vystup cout << "zacatek programu pro praci s polem: " << prac.vloz(5,81);//vlozeni hodnoty do pole prac.vypis();//vypis na obrazovku system("PAUSE"); }
Vstupy a výstupy dat
21
endl;
Na obrazovce je výstup hodnot pole v cyklu, kdy první číslo je index pole a druhé číslo je nastavená hodnota. Ve výpisu je vidět nastavená hodnota prvku s indexem 5 na hodnotu 81. Ostatní prvky pole byly vynulovány v konstruktoru objektu na začátku programu.
4.2 Zadání příkladu C++ řazení pole Naprogramujte pomocí objektově orientovaného programování příklad, jehož výstupem jsou hodnoty jednorozměrného pole celých čísel. Tyto hodnoty jsou seřazeny jednoduchou řadící metodou a zobrazeny na obrazovku. Hodnoty pole jsou zadány z klávesnice.
Cíl Ukázat práci s indexy pole a řadícího algoritmu buble sort. Analýza Deklarujeme pole v třídě objektu a tímto polem provádíme jednotlivé operace pomocí členských funkcí. Řadící algoritmus je naprogramován pomocí dvou cyklů. Použité vzorce Je použito indexování prvků pole pomocí indexu pole, tento index je proměnná hodnota. Použité algoritmy Algoritmus řadící metody je následující: 22
Nastav proměnou vymena na hodnotu nula Dělej cyklus dokud proměnná výměna je nastavena na hodnotu jedna Zdrojový kód programu //priklad pro pole #include using namespace std; class polex { public:
//oznaceni tridy OOP // verejne pristupna data
int pocet; int x[10]; //data pole //prototypy jednotlivych clenskych funkci polex(); //konstruktor void vypis(); //vypise hodnoty pole na obrazovku void vloz(int n,int hodnota); //vlozi hodnotu do pole podle indexu pole void serad(); }; polex::polex() //konstruktor pro pole { int i; pocet=10; for (i=0;i<pocet;i++) x[i]=0;//data pro primku }
void polex::vypis() //clenska funkce { int i; for (i=0;i<pocet;i++) cout << i <<"-"<< x[i]<< endl; } void polex::vloz(int n,int hodnota) //clenska funkce { if ((n>=0)&&(n<pocet)) x[n]=hodnota;//test na rozsah indexu pole else cout << "error"<< endl; } void polex::serad() //clenska funkce { int i,vymena,pomocna; do { vymena=0; for (i=0;i<pocet-1;i++) { if (x[i]>x[i+1]) { pomocna=x[i]; x[i]=x[i+1];
23
x[i+1]=pomocna; vymena=1; } }//for }while(vymena==1); }
//hlavni program int main() { int pom,i; polex prac; //instance objektu pro data grafu a vystup cout << "zacatek programu pro praci s polem: " << for (i=0;i<10;i++) { cout << "zadej prvek pole " << i <<"="; cin >> pom; prac.vloz(i,pom);//vlozeni hodnoty do pole }
endl<<
endl;
prac.serad();//serazeni cout << "serazene pole: " << endl; prac.vypis();//vypis na obrazovku system("PAUSE"); }
Vstupy a výstupy dat
Na obrazovce je deset vstupních hodnot vložených do pole pomocí členské funkce. Další akcí je seřazení pole od nejmenšího prvku po největší prvek.
Úkol: 24
Modifikujte předcházející příklad použitím jiné varianty třídění.
4.3 Zadání příkladu C++ s využitím výstupu GOOGLE API Vytvořte program v OOP C++ pro výstup hodnot jednorozměrného pole do grafu, který je vytvořen na WWW stránce pomocí HTML kodu a javascriptu s využitím GOOGLE API chart s variantou line grafu. Hodnoty grafu navrhněte tak, aby bylo možné nastavit v programu jednotlivé prvky pole a realizovat vytvoření grafu pomocí členské funkce. Cíl Využít grafického rozhraní WWW stránek pro grafický výstup dat. Seznámit se s možností parametrů při vytváření grafů s využitím prvků GOOGLE API a jejich nastavením. Propojit lokální výpočet hodnot s internetovými technologiemi. Analýza Program navrhneme takovým způsobem, že data grafu uložíme do pole, jehož prvky vložíme do grafu. Při vytváření samotného grafu vyjdeme z ukázky line grafu v Html kodu, kde vnitřní část souboru, kde jsou samotná data, dynamicky vytvoříme z našeho programu. Statický soubor GOOGLE API
Varianty grafu V následující tabulce jsou různé varianty, které modifikují parametry jednotlivých sloupců datové tabulky. Tabulka vysvětluje možnosti datových sloupců při postupném rozšiřování datových řad.
25
Tvar HTML souboru, který realizuje graf dvou číselných řad : <script type="text/javascript" src="https://www.google.com/jsapi"> <script type="text/javascript"> google.load("visualization", "1", {packages:["corechart"]}); google.setOnLoadCallback(drawChart); function drawChart() { var data = google.visualization.arrayToDataTable([ ['Year', 'Sales', 'Expenses'], ['2004', 1000, 400], ['2005', 1170, 460], ['2006', 660, 1120], ['2007', 1030, 540] ]); var options = { title: 'Company Performance' }; var chart = new google.visualization.LineChart(document.getElementById('chart_div')); chart.draw(data, options); }
Vnitřní část pro vytváření dat je následující 26
['Year', 'Sales', 'Expenses'], ['2004', 1000, 400], ['2005', 1170, 460], ['2006', 660, 1120], ['2007', 1030, 540] ]);
Tato část představuje dvě číselné řady, v prvním sloupci je text, který se zobrazí na ose x, dále následují dvě čísla, oddělena čárkou což jsou hodnoty grafu. ['2004', 1000, 400], V našem případě budeme vytvářet pouze jednu číselnou řadu, a proto použijeme variantu v programu s označením čísla na ose x a číselnou hodnotu ['1', ['2', ['3', …
12], 25], 3],
Ukázka kodu
sprintf(pom,",['%d',%d]\n",i,x[i]);//vlozeni dat z pole do souboru Použité vzorce Nebudou použity žádné vědecko technické výpočty. Použité algoritmy Pro realizaci projektu si rozdělíme výstupní soubor HTML na dvě části. První část bude představovat řádky po text var data = google.visualization.arrayToDataTable([
který vytváří datovou tabulku pro graf. Tento soubor nazveme px1.html. Druhá část, kterou nazveme px2.html bude představovat řádky od místa ]); var options = {
kde se uzavírá datová tabulka a následují možnosti grafu. Tuto část si můžeme staticky nastavit podle našich požadavků s libovolným textem. Zde můžeme použít jednotlivé tagy HTML stránek pro změnu grafiky stránek a využít kaskádové styly. Místo kde se umístí graf je uvedeno značkami:
Velikost grafu se mění parametricky podle šířky a výšky obrázku. V našem programu se budeme zabývat pouze změnou vstupních dat pro graf.
27
Střední část dat pro objekt tabulky GOOGLE API vytvoří naše členská funkce v OOP programu. for (i=1;i<20;i++) { sprintf(pom,",['%d',%d]\n",i,x[i]);//vlozeni dat z pole do souboru fputs(pom,fo); }
Vytvoření dat pro graf provedeme vložením jednotlivých řádků, které představují datovou tabulku pro objekt GOOGLE API. Výhodou je možnost modifikovat počet číselných řad pomocí oddělovače čárky. V našem případě použijeme pouze jednu číselnou řadu.
Zdrojový kód programu //priklad pro vystup grafu pomoci GOOGLE API GRAPH #include #include <stdio.h> using namespace std; class vystup_html //oznaceni tridy OOP { public: // verejne pristupna data int pocet; int x[20]; //data do grafu //prototypy jednotlivych clenskych funkci void nastav_lin(); //nastavi data od 0-19 void vypis(); //vypise hodnoty pole na obrazovku void vloz(int n,int hodnota); //vlozi hodnotu do pole podle indexu pole void graf(); //vytvori vystupni soubor }; void vystup_html::nastav_lin() //clenska funkce pro pole { int i; pocet=20; for (i=0;i<pocet;i++) x[i]=i;//data pro primku }
void vystup_html::vypis() //clenska funkce { int i; for (i=0;i<pocet;i++) cout << i <<"-"<< x[i]<< endl; } void vystup_html::vloz(int n,int hodnota) //clenska funkce { if ((n>=0)&&(n<=pocet)) x[n]=hodnota;//test na rozsah indexu pole else cout << "error"<< endl;
28
} void vystup_html::graf() { FILE *fi,*fo; char pom[1000]; int i; fi=fopen("px1.html","r");//prvni cast souboru po data fo=fopen("vystup.html","w");//vystupni soubor vystup.html while (!feof(fi)) { fgets(pom,1000,fi); fputs(pom,fo); } fputs("\n['rada', 'hodnota']\n\n",fo);//hlavicka dat for (i=1;i<20;i++) { sprintf(pom,",['%d',%d]\n",i,x[i]);//vlozeni dat z pole do souboru fputs(pom,fo); } fclose(fi); fi=fopen("px2.html","r"); //druha cast souboru HTML s google api while (!feof(fi)) { fgets(pom,1000,fi); fputs(pom,fo); } //uzavreni souboru fclose(fi); fclose(fo); } //hlavni program int main() { vystup_html h1; //instance objektu pro data grafu a vystup cout << "zacatek programu pro vystup HTML grafu GOOGLE API: " << h1.nastav_lin(); //nastaveni hodnot na primku h1.vloz(5,81);//vlozeni hodnoty do pole h1.vypis();//vypis na obrazovku h1.graf();//vytvoreni grafu v souboru vystup.html system("PAUSE"); }
Vstupy a výstupy dat
29
endl;
4.4 Zadání příkladu C++ pole řetězců Vytvořte třídu pomocí C++ příkazů pro práci z řetězci s možností porovnávání a výpisu jednotlivých znaků. Cíl Ukázka funkcí pro práci s řetězci s možností přístupu k určitému znaku.
Analýza Použijeme funkce pro práci s řetězci Délka řetězce 30
Ukázka kodu: // string::length #include #include <string> int main () { std::string str ("Test string"); std::cout << "The size of str is " << str.length() << " characters.\n"; return 0; }
Přístup k určitému znaku // string::at #include #include <string> int main () { std::string str ("Test string"); for (unsigned i=0; i<str.length(); ++i) { std::cout << str.at(i); } return 0; }
Porovnání řetězců navzájem http://www.cplusplus.com/reference/string/string/compare/ Returns a signed integral indicating the relation between the strings: value relation between compared string and comparing string 0 They compare equal Either the value of the first character that does not match is lower in the compared string, or <0 all compared characters match but the compared string is shorter. Either the value of the first character that does not match is greater in the compared string, >0 or all compared characters match but the compared string is longer.
Ukázka kodu // comparing apples with apples #include #include <string> int main () { std::string str1 ("green apple"); std::string str2 ("red apple"); if (str1.compare(str2) != 0) std::cout << str1 << " is not " << str2 << '\n'; if (str1.compare(6,5,"apple") == 0) std::cout << "still, " << str1 << " is an apple\n"; if (str2.compare(str2.size()-5,5,"apple") == 0) std::cout << "and " << str2 << " is also an apple\n"; if (str1.compare(6,5,str2,4,5) == 0) std::cout << "therefore, both are apples\n";
31
return 0; }
Použité algoritmy Sekvenční postup v cyklu pro výpis řetězce znak po znaku. Zdrojový kód program C++ //priklad pro jednorozmerne pole znaku varianta string #include #include <string> using namespace std; class retezce //oznaceni tridy OOP { public: // veøejnì pøístupna data int pocet; string ret1,ret2; //ciselny clen rady //prototypy jednotlivych clenskych funkci void vloz1(string pom); void vloz2(string pom); void vypis(); void porovnej(); void znaky(); };
void retezce::vloz1(string pom) //clenska funkce { ret1=pom; } void retezce::vloz2(string pom) //clenska funkce { ret2=pom; }
void retezce::vypis() //clenska funkce vypocet faktorialu n { cout << "retezec1: " <<
ret1
<< "
retezec2: " <<
ret2<< endl;
} void { if if if }
retezce::porovnej() //clenska funkce (ret1.compare(ret2)==0)cout << "jsou shodne " << endl; (ret1.compare(ret2)>0)cout << "prvni je vetsi " << endl; (ret1.compare(ret2)<0)cout << "druhy je vetsi " << endl;
void retezce::znaky() //clenska funkce { for (unsigned i=0; i
32
{ cout << i <<" - " << ret1.at(i)<< endl; } } //hlavni program int main() { string x; retezce px; //instance objektu cout << "zacatek programu: " << cout << "vloz retezec: " ; cin >> x;
endl;
px.vloz1(x); px.vloz2(x); px.porovnej(); px.vypis(); px.vloz2("ahoj"); px.porovnej(); px.vypis(); px.znaky(); system("PAUSE"); }
Vstup výstup dat
33
5. Příklady zaměřené na práci s polem záznamů jako databází Následující příklady spojují některé prvky analýzy z předcházejících příkladů a ukazují na vytváření projekt z meších celků samostatně odladěných v předchozích příkladech.
Zadání příkladu Realizujte program v OOP C++ pro vytvoření pole záznamů se dvěma položkami kniha 40 znaků maximálně a cena typu double. Maximální počet záznamů je 1000. Vytvořte menu pro změnu záznamu a výpis jednotlivých záznamů. Realizujte konstruktor třídy, který naplní záznamy počáteční hodnotou. V destruktoru se jednotlivé záznamy zapíší do textového souboru knihy.txt. Jednotlivé členské funkce dovolí načíst data z textového pole. Cíl Práce s jednorozměrným polem záznamů, vytvoření koncepce pro práci s třídami pro jednoduchý databázový projekt. Realizace destruktoru, který automaticky uloží změněné záznamy do textového souboru knihy.txt. Jedná se o pochopení práce s polem záznamů a možnosti přímé editace načtených záznamů.
Analýza Použijeme datovou strukturu proměnných podle zadání struct zaznam{ char kniha[40]; double cena; }seznam[1000]; Tato struktura vytvoří seznam 1000 záznamů s možností přímého přístupu k seznamu pomocí odkazu seznam[i].kniha, kde hodnota „i“ představuje index záznamu pole. Položka cena je číselná s dvojnásobnou přesností.
34
Použité vzorce Pro výpočty se používají algoritmy cyklu pro výpočet počtu záznamů do proměnné počet. Použité algoritmy Algoritmus načtení záznamu z textového souboru knihy.txt – sekvenční čtení dat. • Otevření souboru pro čtení • Test na konec souboru o Načtení záznamu kniha cena • Uzavření souboru • Zaznamenání počtu knih do proměnné počet Klíčové části void knihovna::nacti_data() //deklarace vně třídy { FILE *f; int i=0; //promena resi pocet zaznamu f=fopen("knihy.txt", "r"); while (!feof(f)) { fscanf(f, "%s", seznam[i].kniha); fscanf(f, "%lf", &seznam[i].cena); if (feof(f))break;//test pro posledni enter i++; if (i==1000)break; 35
} fclose(f); pocet=i; cout << "pocet knih je:"<
Klíčové části knihovna::~knihovna() // destruktor { FILE *f; int i; //ulozeni dat do souboru pri zaniku objektu f=fopen("knihy.txt", "w"); for (i=0;i<pocet;i++)//cyklus vlozeni zaznamu text mezera cislo fprintf(f, "%s %lf\n", seznam[i].kniha,seznam[i].cena); //zapis dat fclose(f); } Algoritmus hlavního programu • Načtení dat • Cyklus zobrazení menu dokud není akce číslo 0 o Zobraz menu • Konec programu Klíčové části Načtení dat z textového souboru knihy.nacti_data(); //nacte data do objektu instance tridy vytvoření menu pomocí cyklu do while do { cout<<"MENU:"<<endl; //zobraz menu cout<<"*****"<<endl; 36
cout<<"1-seznam knih"<<endl; cout<<"2-zmenit zaznam:"<<endl; cout<<"0-konec programu:"<<endl<<endl; cin >> volba; switch(volba) { case 1:knihy.vypis();break; //vypise data case 2: cout<<"cislo zaznamu:";cin >> j; //cislo zaznamu pro editaci knihy.zadej(j);break; } }while(volba!=0);
Zdrojový kód programu #include <stdio.h> #include using namespace std; class knihovna { //oznaceni tridy OOP public: // veřejně přístupna data // struct zaznam{ char kniha[40]; double cena; }seznam[1000]; int pocet; //pocet zaznamu nactenych ze souboru knihovna() // konstruktor { int i; for (i=0;i<1000;i++) { strcpy(seznam[i].kniha,"-"); //kopírování řetězce seznam[i].cena=0; } }; ~knihovna(); // destruktor ,vola se automaticky když trida konci, zanika void zadej(int cislo); 37
void vypis(); void nacti_data(); };
void knihovna::vypis() { for (int i=0;i<pocet;i++) //vypise data v cyklu cout << "kniha:" <999))cout << "chyba rozsahu:" << c << endl; else { cout << "vloz knihu: " << endl; cin >> seznam[c].kniha; cout << "vloz cenu: " << endl; cin >> seznam[c].cena; } } void knihovna::nacti_data() //deklarace vně třídy { FILE *f; int i=0; //promena resi pocet zaznamu f=fopen("knihy.txt", "r"); while (!feof(f)) { fscanf(f, "%s", seznam[i].kniha); fscanf(f, "%lf", &seznam[i].cena); if (feof(f))break;//test pro posledni enter i++; if (i==1000)break; } fclose(f); pocet=i; cout << "pocet knih je:"<
knihovna::~knihovna() // destruktor 38
{ FILE *f; int i; //ulozeni dat do souboru pri zaniku objektu f=fopen("knihy.txt", "w"); for (i=0;i<pocet;i++)//cyklus vlozeni zaznamu text mezera cislo fprintf(f, "%s %lf\n", seznam[i].kniha,seznam[i].cena); //zapis dat fclose(f); } //hlavni program int main() { int volba,j; //volba z menu knihovna knihy; //promenna instance tridy knihy.nacti_data(); //nacte data do objektu instance tridy do { cout<<"MENU:"<<endl; //zobraz menu cout<<"*****"<<endl; cout<<"1-seznam knih"<<endl; cout<<"2-zmenit zaznam:"<<endl; cout<<"0-konec programu:"<<endl<<endl; cin >> volba; switch(volba) { case 1:knihy.vypis();break; //vypise data case 2: cout<<"cislo zaznamu:";cin >> j; //cislo zaznamu pro editaci knihy.zadej(j);break; } }while(volba!=0); system("PAUSE"); }
Vstupy a výstupy dat
39
Textový soubor knihy.txt obsahuje tyto záznamy: babicka 250 aaa 89 Na obrázku výstupu obrazovky je vidět načtení dat z textového souboru knihy, který obsahuje dva záznamy. Po načtení se zobrazí menu s možností výpisu knihy, tato akce je zobrazena na následujících řádcích. Akcí číslo 2 došlo ke změně záznamu s pořadovým číslem 1 na knihu „tolkien“ a cenu 520. Po ukončení programu obsahuje textový soubor knihy.txt tyto záznamy. Textový soubor knihy.txt obsahuje tyto záznamy: babicka 250 tolkien 520
40
Souhrnný projekt Závěrečný projekt realizuje myšlenky objektově orientovaného programování do výsledného celku společně s dokumentací a testováním programu. Součástí závěrečného projektu má být analýza datových struktur společně s návrhem vlastního algoritmu řešení. Zaměření projektu Vytvoření datové struktury /např. pole zákazníků, faktury, odběratelů dodavatele, sklady …/ Návrh datových položek /nejméně 5 položek různých datových typů/ Metody objektu: Změny datové struktury Vyhledávání v datech Třídění Tiskové sestavy Výpočty Uložení dat do textových souborů Dokumentace projektu /textový editor word/ Zadání projektu Analýza Diagram tříd Popis dat a proměnných programu Schémata a další diagramy /vývojové diagramy/ Popis vstupních a výstupních obrazovek Popis ovládání programu Testování programu na množině vstupů Zdrojový kód programu Klíčové části s komentářem
Literatura: Čada, O. Objektové programování. Praha: Grada 2009, ISBN 978-80-247-2745-5 Internetové zdroje http://www.cplusplus.com/reference/
41
42
6. Aplikace PHP jazyka OOP varianta Úvod Jednotlivé kapitoly jsou zaměřeny na vysvětlení použití jednotlivých příkazů PHP jazyka v programu, který realizuje zadané požadavky. Základní požadavky na program jsou zadány velmi obecně a cílem je vysvětlit postup, který vede k vytvoření objektů pomocí tříd OOP, které realizují zadané požadavky. Při analýze je použita metoda dekompozice na menší celky, ze kterých je možné naprogramovat členské funkce. Tyto členské funkce realizují pomocí vnitřních proměnných navržený algoritmus. Jednotlivé programy jsou postupně rozpracovány od jednoduchého základní řešení po řešení s využitím algoritmů numerické matematiky s vysvětlením vzorců použitých při řešení.
43
6.1 PHP Příklady zaměřené na aplikaci vědeckotechnického výpočtu Jednotlivé příklady ukazují na možnosti aplikace algoritmu postupného výpočtu jedné nebo více hodnot podle určitého vzorce. Jednotlivé hodnoty jsou zadány přímo v programu a vdalších příkladech je ukázána možnost požití vstupních formulářů pro zadání hodnot. Jednotlivé příklady postupují od jednoduchých variant ke složitějším s ukázkou vytváření tříd a jednotlivých objektů pro výpočet podle zadaného vzorce nebo určeného algoritmu.
6.1.1 Zadání příkladu –PHP OOP výpočet plochy kruhu Napište program pomocí jazyka PHP v OOP variantě pro výpočet plochy kruhu. Vytvořte potřebné třídy a metody pro realizaci na serveru v prostředí internetu. Cíl Ukázka deklarace třídy s jednotlivými vlastnostmi se zadáním hodnoty poloměru kruhu přímo v programu při vytváření instance objektu. Analýza Pro výpočet použijeme vzorec obsah = 3.14 * r*r; třída: kruh - class kruh metody: • plocha – vrací hodnotu výpočtu plochy kruhu • nastav_polomer – nastaví hodnotu vnitřní proměnné na požadovanou hodnotu použita vnitřní proměnná $polomer; objekt odvozený od třídy kruh $k1 = new kruh();
Použité algoritmy Sekvenční postup shora dolů se zobrazením výsledku na obrazovce. Poloměr zadán konstantní hodnotou 10 při vytváření objektu. Zdrojový kód programu PHP
44
var $polomer; function nastav_polomer($x) { $this->polomer = $x; } function plocha() { $p= 3.14 * $this->polomer * $this->polomer; return $p; } }
$k1 = new kruh(); $k1->nastav_polomer(10); echo "Plocha kruhu je: " .$k1->plocha();
?>
Vstupy a výstupy dat
Na obrazovce je znázorněna hodnota výpočtu plochy kruhu jako výsledek výpočtu v metodě třídy.
6.1.2 Zadání příkladu –PHP OOP plocha a obvod kruhu Napište program pomocí jazyka PHP v oop variantě pro výpočet plochy a obvodu kruhu. Vytvořte potřebné třídy a metody pro realizaci na serveru v prostředí internetu. Cíl
45
Ukázka deklaraci třídy s jednotlivými vlastnostmi se zadáním hodnoty poloměru kruhu přímo v programu. Jedná se o rozšíření předešlého příkladu o další výpočet se zobrazením zadané hodnoty ve vnitřní proměnné třídy kruh pomocí určité metody . Analýza Pro výpočet použijeme vzorec obsah = 3.14 * r*r; obvod= 2*3.14 * r;
třída: kruh - class kruh metody: • plocha – vrací hodnotu výpočtu plochy kruhu • obvod – vrací hodnotu výpočtu obvodu kruhu • nastav_polomer – nastaví hodnotu vnitřní proměnné na požadovanou hodnotu • Info_polomer – vrací hodnotu nastavenou ve vnitřní proměnné polomer použita vnitřní proměnná $polomer; objekt odvozený od třídy kruh $k1 = new kruh();
Použité algoritmy Sekvenční postup shora dolů se zobrazením výsledku na obrazovce.
Zdrojový kód programu PHP class kruh { var $polomer; function nastav_polomer($x) { $this->polomer = $x; } function plocha() { $p= 3.14 * $this->polomer * $this->polomer; return $p; } function obvod() { $o= 3.14 * 2 * $this->polomer; return $o; } function info_polomer() { return $this->polomer; } }
46
$k1 = new kruh(); $k1->nastav_polomer(10); echo "
zadany polomer kruhu je: " .$k1->info_polomer(); echo "
Plocha kruhu je: " .$k1->plocha(); echo "
obvod kruhu je: " .$k1->obvod();
?>
Vstupy a výstupy dat
Výstupní obrazovka se zobrazením vstupní hodnoty poloměru a hodnot výpočtu.
6.1.3 Zadání příkladu -PHP OOP kruh výstup v tabulce Napište program pomocí jazyka PHP v oop variantě pro výpočet plochy a obvodu kruhu v tabulce s postupným voláním metod objektu třídy kruh. Cíl Ukázka volání metod třídy v cyklu s využitím tagů HTML pro tvorbu tabulky jako výstupu z programu. Analýza Pro výpočet použijeme vzorec obsah = 3.14 * r*r; obvod= 2*3.14 * r; třída: kruh - class kruh metody: • plocha – vrací hodnotu výpočtu plochy kruhu 47
• obvod – vrací hodnotu výpočtu obvodu kruhu • nastav_polomer – nastaví hodnotu vnitřní proměnné na požadovanou hodnotu • Info_polomer – vrací hodnotu nastavenou ve vnitřní proměnné polomer použita vnitřní proměnná $polomer; objekt odvozený od třídy kruh $k1 = new kruh();
Použité algoritmy Cyklus výpočtu od hodnoty 1 až 10 , v těle cyklu se nastaví hodnota poloměru pomocí metody a v řádku tabulky se zobrazí hodnoty plochy a obvodu kruhu pomocí dalších metod třídy kruh. polomer = $x; } function plocha() { $p= 3.14 * $this->polomer * $this->polomer; return $p; } function obvod() { $o= 3.14 * 2 * $this->polomer; return $o; } function info_polomer() { return $this->polomer; } } $k1 = new kruh(); echo ""; echo "polomer | plocha | obvod |
"; for ($i = 1; $i <= 10; $i++) { $k1->nastav_polomer($i); echo "".$k1->info_polomer()." | ".$k1>plocha()." | ".$k1->obvod()." |
"; }
48
echo "
"; ?>
Vstupy a výstupy dat
Výstup z PHP skriptu zobrazuje výslednou tabulku s poloměrem, plochou a obvodem kruhu.
6.1.4 Zadání příkladu –PHP OOP výpočet kruhu v cyklu Napište program pomocí jazyka PHP v oop variantě pro výpočet plochy a obvodu kruhu v tabulce s postupným voláním vlastností objektu třídy kruh a výpočtem hodnot součtu uvnitř cyklu. Cíl Ukázka volání metod třídy v cyklu s využitím tagů pro tvorbu tabulky a sumací vypočtených hodnot. Analýza Pro výpočet použijeme vzorec obsah = 3.14 * r*r; obvod= 2*3.14 * r; třída: kruh - class kruh 49
metody: • plocha – vrací hodnotu výpočtu plochy kruhu • obvod – vrací hodnotu výpočtu obvodu kruhu • nastav_polomer – nastaví hodnotu vnitřní proměnné na požadovanou hodnotu • Info_polomer – vrací hodnotu nastavenou ve vnitřní proměnné polomer použita vnitřní proměnná $polomer; objekt odvozený od třídy kruh $k1 = new kruh();
Použité algoritmy Cyklus výpočtu od hodnoty 1 až 10 , v těle cyklu se nastaví hodnota poloměru a v řádku tabulky se zobrazí hodnoty plochy a obvodu kruhu. V proměnné suma1 a suma2 se sčítají postupně hodnoty plochy a obvodu kruhu.
polomer = $x; } function plocha() { $p= 3.14 * $this->polomer * $this->polomer; return $p; } function obvod() { $o= 3.14 * 2 * $this->polomer; return $o; } function info_polomer() { return $this->polomer; } }
$k1 = new kruh(); $suma1 = 0; $suma2 = 0; echo ""; echo "polomer | plocha | obvod |
";
50
for ($i = 1; $i <= 10; $i++) { $k1->nastav_polomer($i); echo "".$k1->info_polomer()." | ".$k1>plocha()." | ".$k1->obvod()." |
"; $suma1 += $k1->plocha(); $suma2 += $k1->obvod(); } echo "soucet | $suma1 | $suma2 |
"; echo "
";
?>
Vstupy a výstupy dat
Na obrazovce jsou ve spodní části zobrazeny hodnoty jednotlivých sečtených ploch a obvodů z jednotlivých řádků tabulky.
6.1.5 Zadání příkladu –PHP OOP výpočet obdelníku s formulářem HTML Vypočtěte plochu obdélníku při zadání jednotlivých stran obdélníku z klávesnice ve formuláři HTML.
51
Cíl Ukázka deklaraci třídy s jednotlivými vlastnostmi v kombinaci s použitím HTML povelů pro vytvoření formuláře a převzetí jednotlivých parametrů pro výpočet. PHP skript volá sám sebe a zjišťuje hodnoty zadané ve formuláři. Podle těchto hodnot se provádí výpočet. Analýza Pro výpočet použijeme vzorec obsah = a * b; stranu a , b zadáme do formuláře s metodou POST a dále použijeme ve výpočtu ukázka kódu
Použité algoritmy Sekvenční postup shora dolů, zadání hodnot z klávesnice a provedení výpočtu volání určité metody. Hodnota se zobrazí po výpočtu výstupem na formuláři. Zdrojový kód programu PHP a = $x; $this->b = $y; } function plocha() { $plo= $this->a * $this->b; return $plo; } function obvod() { $o= 2*($this->a + $this->b); return $o; } } ?>
52
vypocet Obdelniku
nastav_strany($x,$y); echo "
strany obdelniku: $x , $y"; echo "
Plocha obdelniku je: " .$o1->plocha(); echo "
obvod obdelniku je: " .$o1->obvod(); } ?>
Vstupy a výstupy dat
53
Zobrazení zadání vstupních hodnot pro výpočet.
Na obrazovce je znázorněna hodnota vstupních stran obdélníku a výpočet plochy a obvodu obdélníku z těchto vstupních hodnot.
6.1.6 Zadání příkladu –PHP OOP výpočet obdelníku a kruhu – volání různých tříd Vypočtěte plochu obdélníku při zadání jednotlivých stran obdélníku jako konstanty v programu v kombinaci s výpočtem plochy kruhu. Cíl Ukázka deklarací 2 tříd obdelníku a kruhu v jednom skriptu v kobinace dvou objektů různé třídy. Jednotlivé objekty zadávají rozné hodnoty a mají jiné vnitřní proměnné. Analýza Pro výpočet použijeme vzorec obsah = a * b; obsah = 3.14 * r*r; Použité algoritmy Sekvenční postup shora dolů, zadání hodnot v programu a provedení výpočtu volání určité metody. Hodnota se zobrazí po výpočtu výstupem na formuláři.
54
Zdrojový kód programu PHP polomer = $x; } function plocha() { $p= 3.14 * $this->polomer * $this->polomer; return $p; } }
class obdelnik { var $a; var $b;
function nastav_strany($x,$y) { $this->a = $x; $this->b = $y; } function plocha() { $plo= $this->a * $this->b; return $plo; } } $k1 = new kruh(); $o1 = new obdelnik(); $k1->nastav_polomer(10); echo "Plocha kruhu je: " .$k1->plocha(); $o1->nastav_strany(5,8); echo "
Plocha obdelniku je: " .$o1->plocha(); ?>
Vstupy a výstupy dat
55
Na výstupu jsou vidět hodnoty výpočtu z obou objektů odvozených od třídy kruh a obdelník.
6.2 PHP OOP - výpočty pro numerickou matematiku – výpočet integrálu
Tyto výpočty ukazují psotupy, které představují algoritmy pro výpočet určitého integrálu pomocí numerické matematiky. Jednotlivé algoritmy jsou převedeny do programovacího jazyka PHP varianty OOP tak aby výpočet byl součásti navržené třídy. V jednotlivých příkladech jsou nejprve analyzovány postupy a použité vzorce, které jednotlivé příklady používají a dále je ukázka konkrétní varianty výpočtu. Jednotlivé výsledky jsou testovány a porovnány s výsledky, které jsou výstupem programu wolfram alpha.
6.2.1 Zadání příkladu – PHP OOP výpočet určitého integrálu Vypočtěte hodnotu určitého integrálu pomocí navržené numerické metody (lichoběžníková metoda, simpsonova metoda) a zobrazte výsledek. Cíl Ukázka deklarace třídy integral s metodami numerického algoritmu pro výpočet. Vysvětlení principu výpočtu v cyklu s postupným výpočtem. Analýza Pro výpočet použijeme vzorec zadání mezí a,b integrálu pro funkci f(x) Lichoběžníková metoda
Simpsonova metoda
56
třída: integral - class integral metody: • výpočet hodnoty funkce function f($x) • nastavení mezí function nastav_meze($x,$y) • numerickým výpočet integrálu function integral_s()
Použité algoritmy • • • •
Zadání mezí hodnot integrálu Výpočet kroku Cyklus postupné sumace dle vzorců a sčítání plochy pod křivkou Zobrazení hodnoty integrálu jako součet lichoběžníků pod křivkou funkce f(x)
Zdrojový kód programu PHP
function nastav_meze($x,$y) { $this->a = $x; $this->b = $y; } function integral_s() { $krok=(($this->b)-($this->a))/100; $suma=0; for($i=0; $i<100;$i ++ ) //cyklus vypoctu integralu { $bb=$this->a+$krok; //simpsonova metoda //$sim=($bb-$this->a)/6 * ($this->f($this->a)+4*$this->f(($this>a+$bb)/2)+$this->f($bb)); //lichobeznikova metoda $licho=(($this->f($bb)+$this->f($this->a))/2) * $krok; $suma+=$licho; //hodnota integralu $this->a+=$krok;
57
} return $suma; } } $i1 = new integral(); $i1->nastav_meze(0.5,3); echo "integral je: " .$i1->integral_s(); ?>
Zobrazení hodnoty vypočteného intgrálu funkce 5x2-15x+20.
function nastav_meze($x,$y) { $this->a = $x; $this->b = $y; } function integral_s() {
$krok=(($this->b)-($this->a))/100; $suma=0; for($i=0; $i<100;$i ++ ) //cyklus vypoctu integralu { $bb=$this->a+$krok;
58
$sim=($bb-$this->a)/6 * ($this->f($this->a)+4*$this->f(($this>a+$bb)/2)+$this->f($bb)); //$licho=(($this->f($bb)+$this->f($this->a))/2) * $krok; $suma+=$sim; //hodnota integralu $this->a+=$krok; } return $suma; } } ?> vypocet integralu - simpsonova metoda y=5*x*x-15*x+20
nastav_meze($a,$b); echo "hodnota integral funkce je: " .$i1->integral_s(); echo "
overeni na http://www.wolframalpha.com/input/?i=integrate+5*x*x15*x%2B20+from+0.5+to+3"; } ?>
Vstupy a výstupy dat
59
60
7. Aplikace variannty OOP s použitím Microsoft visual studio 2008 Aplikace visual studia do projektů MSC představuje rozšíření aplikace algoritmů OOP do prostředí s vizuálními komponentami. Tyto komponenty představují objekty jejich vlastnosti lze nastavovat při vytváření projektu určitého programu. Toto dovoluje nastavit vizuální zobrazení (barvy, velikosti písma, naplnění počátečními údaji apod. ) před samotným spuštěním programu. Startovací stránka visual studia
Vytváření projektu
Možnost výběru varianty programu a místa uložení výsledného projektu
61
Počáteční spuštění s prázdným formulářem.
Zobrazení vlastností objektu na pravé straně obrazovky s možností nastavení vlastností ručně před spuštěním programu.
62
Zdrojový kód aplikace formular.h s kodem v C++. #pragma once
namespace prac1 { using namespace System; using namespace System::ComponentModel; using namespace System::Collections;
63
using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; /// <summary> /// Summary for Form1 /// /// WARNING: If you change the name of this class, you will need to change the /// 'Resource File Name' property for the managed resource compiler tool /// associated with all .resx files this class depends on. Otherwise, /// the designers will not be able to interact properly with localized /// resources associated with this form. /// public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: Add the constructor code here // } protected: /// <summary> /// Clean up any resources being used. /// ~Form1() { if (components) { delete components; } } private: System::Windows::Forms::Label^ label1; private: System::Windows::Forms::Button^ button1; protected: private: /// <summary> /// Required designer variable. /// System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// void InitializeComponent(void) { this->label1 = (gcnew System::Windows::Forms::Label()); this->button1 = (gcnew System::Windows::Forms::Button()); this->SuspendLayout(); // // label1
64
// this->label1->AutoSize = true; this->label1->ForeColor = System::Drawing::SystemColors::ActiveCaption; this->label1->Location = System::Drawing::Point(85, 54); this->label1->Name = L"label1"; this->label1->Size = System::Drawing::Size(90, 13); this->label1->TabIndex = 0; this->label1->Text = L"Ahoj kluci a holky"; // // button1 // this->button1->Location = System::Drawing::Point(88, 166); this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(75, 23); this->button1->TabIndex = 1; this->button1->Text = L"akce"; this->button1->UseVisualStyleBackColor = true; this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click); // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(292, 266); this->Controls->Add(this->button1); this->Controls->Add(this->label1); this->Name = L"Form1"; this->Text = L"Form1"; this->ResumeLayout(false); this->PerformLayout(); } #pragma endregion private: System::Void button1_Click(System::Object^ System::EventArgs^ e) {
sender,
this->label1->Text = L"programujeme ve visual C"; } }; }
65
66
#pragma once
namespace ctverec { using using using using using using
namespace namespace namespace namespace namespace namespace
System; System::ComponentModel; System::Collections; System::Windows::Forms; System::Data; System::Drawing;
/// <summary> /// Summary for Form1 /// /// WARNING: If you change the name of this class, you will need to change the /// 'Resource File Name' property for the managed resource compiler tool /// associated with all .resx files this class depends on. Otherwise, /// the designers will not be able to interact properly with localized /// resources associated with this form. /// public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: Add the constructor code here // } protected: /// <summary> /// Clean up any resources being used. /// ~Form1() { if (components) { delete components; } } private: System::Windows::Forms::Button^ button1; protected: private: System::Windows::Forms::Label^ label1; private: System::Windows::Forms::TextBox^ textBox1; private: System::Windows::Forms::Label^ label2; private: /// <summary> /// Required designer variable. /// System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code /// <summary>
67
/// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// void InitializeComponent(void) { this->button1 = (gcnew System::Windows::Forms::Button()); this->label1 = (gcnew System::Windows::Forms::Label()); this->textBox1 = (gcnew System::Windows::Forms::TextBox()); this->label2 = (gcnew System::Windows::Forms::Label()); this->SuspendLayout(); // // button1 // this->button1->Location = System::Drawing::Point(84, 178); this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(75, 23); this->button1->TabIndex = 0; this->button1->Text = L"stisk"; this->button1->UseVisualStyleBackColor = true; this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click); // // label1 // this->label1->AutoSize = true; this->label1->Location = System::Drawing::Point(81, 69); this->label1->Name = L"label1"; this->label1->Size = System::Drawing::Size(35, 13); this->label1->TabIndex = 1; this->label1->Text = L"label1"; // // textBox1 // this->textBox1->Location = System::Drawing::Point(84, 109); this->textBox1->Name = L"textBox1"; this->textBox1->Size = System::Drawing::Size(100, 20); this->textBox1->TabIndex = 2; this->textBox1->Text = L"0"; // // label2 // this->label2->AutoSize = true; this->label2->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 14, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(238))); this->label2->ForeColor = System::Drawing::Color::Red; this->label2->Location = System::Drawing::Point(36, 30); this->label2->Name = L"label2"; this->label2->Size = System::Drawing::Size(206, 24); this->label2->TabIndex = 3; this->label2->Text = L"Vypocet plochy ctverce"; // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
68
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(292, 266); this->Controls->Add(this->label2); this->Controls->Add(this->textBox1); this->Controls->Add(this->label1); this->Controls->Add(this->button1); this->Name = L"Form1"; this->Text = L"Form1"; this->ResumeLayout(false); this->PerformLayout(); } #pragma endregion private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { //vypocet double a,plocha; a=System::Convert::ToDouble(this->textBox1->Text); plocha=a*a; this->label1->Text =System::Convert::ToString(plocha); } }; }
69
Zadání Vypočtěte hodnotu plochy a obvodu kruhu ze vstupního parametru, kterým je poloměr kruhu. Analýza V dalším příkladu rozšíříme variantu výpočtu na dvě výstupní hodnoty, kterými bude plocha kruhu a obvod kruhu. Vstupním parametrem bude poloměr kruhu. Při kliknutí na tlačítko „vypocet“ se provede výpočet výstupních hodnot, které se zobrazí v objektech pro výstup , v tomto případě objekt label. Klíčová část výpočtu převede hodnotu vstupního parametru poloměru na číselnou hodnotu a pak provede výpočet hodnot plochy a obvodu. Tyto hodnoty jsou dále převedeny na text a vloženy do objektů label. Část zdrojového kódu je následující: double plocha,obvod,r; r=System::Convert::ToDouble(this->textBox1->Text); plocha=3.14*r*r; this->label4->Text =System::Convert::ToString(plocha); obvod=2*3.14*r; this->label5->Text =System::Convert::ToString(obvod);
Jednotlivé převody mezi datovými typy string a double jsou prováděny pomocí systémové funkce System::Convert::ToDouble a funkce System::Convert::ToString. Grafické rozložení jednotlivých položek na formuláři je znázorněno na následujícím obrázku. Jednotlivé objekty typu label přetáhneme myší na formulář a přidělíme jím potřebné vlastnosti (např. barev fontů a podobně). Něktré objekty slouží pouze pro zabrazení informace o zadávaném parametru. Do objektů label4 a label5 jsou vkládány vystupní hodnoty. Z toho důvodu je důležité nastavit vlastnost „text“ na požadovanou hodnotu.
70
Ve zdrojovém kódu jsou vyznačeny objekty label s vlastností typu text. Velká část programu je generována automaticky při vkládání objektů na formulář. Zdrojový kód programu: #pragma once
namespace kruh1 { using using using using using using
namespace namespace namespace namespace namespace namespace
System; System::ComponentModel; System::Collections; System::Windows::Forms; System::Data; System::Drawing;
/// <summary> /// Summary for Form1 /// /// WARNING: If you change the name of this class, you will need to change the /// 'Resource File Name' property for the managed resource compiler tool /// associated with all .resx files this class depends on. Otherwise, /// the designers will not be able to interact properly with localized /// resources associated with this form. /// public ref class Form1 : public System::Windows::Forms::Form {
71
public: Form1(void) { InitializeComponent(); // //TODO: Add the constructor code here // } protected: /// <summary> /// Clean up any resources being used. /// ~Form1() { if (components) { delete components; } } private: System::Windows::Forms::Label^ label1; protected: private: System::Windows::Forms::Button^ button1; private: System::Windows::Forms::Label^ label2; private: System::Windows::Forms::Label^ label3; private: System::Windows::Forms::TextBox^ textBox1; private: System::Windows::Forms::Label^ label4; private: System::Windows::Forms::Label^ label5; private: System::Windows::Forms::Label^ label6;
private: /// <summary> /// Required designer variable. /// System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// void InitializeComponent(void) { this->label1 = (gcnew System::Windows::Forms::Label()); this->button1 = (gcnew System::Windows::Forms::Button()); this->label2 = (gcnew System::Windows::Forms::Label()); this->label3 = (gcnew System::Windows::Forms::Label()); this->textBox1 = (gcnew System::Windows::Forms::TextBox()); this->label4 = (gcnew System::Windows::Forms::Label()); this->label5 = (gcnew System::Windows::Forms::Label()); this->label6 = (gcnew System::Windows::Forms::Label()); this->SuspendLayout(); // // label1 // this->label1->AutoSize = true; this->label1->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 14, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
72
static_cast<System::Byte>(238))); this->label1->ForeColor = System::Drawing::SystemColors::ActiveCaption; this->label1->Location = System::Drawing::Point(79, 43); this->label1->Name = L"label1"; this->label1->Size = System::Drawing::Size(128, 24); this->label1->TabIndex = 0; this->label1->Text = L"vypocet kruhu"; // // button1 // this->button1->Location = System::Drawing::Point(83, 158); this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(75, 23); this->button1->TabIndex = 1; this->button1->Text = L"vypocet"; this->button1->UseVisualStyleBackColor = true; this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click); // // label2 // this->label2->AutoSize = true; this->label2->Location = System::Drawing::Point(26, 80); this->label2->Name = L"label2"; this->label2->Size = System::Drawing::Size(39, 13); this->label2->TabIndex = 2; this->label2->Text = L"plocha"; // // label3 // this->label3->AutoSize = true; this->label3->Location = System::Drawing::Point(28, 106); this->label3->Name = L"label3"; this->label3->Size = System::Drawing::Size(37, 13); this->label3->TabIndex = 3; this->label3->Text = L"obvod"; // // textBox1 // this->textBox1->Location = System::Drawing::Point(83, 132); this->textBox1->Name = L"textBox1"; this->textBox1->Size = System::Drawing::Size(100, 20); this->textBox1->TabIndex = 4; // // label4 // this->label4->AutoSize = true; this->label4->Location = System::Drawing::Point(83, 80); this->label4->Name = L"label4"; this->label4->Size = System::Drawing::Size(35, 13); this->label4->TabIndex = 5; this->label4->Text = L"label4"; // // label5 // this->label5->AutoSize = true; this->label5->Location = System::Drawing::Point(83, 106); this->label5->Name = L"label5";
73
this->label5->Size = System::Drawing::Size(35, 13); this->label5->TabIndex = 6; this->label5->Text = L"label5"; // // label6 // this->label6->AutoSize = true; this->label6->Location = System::Drawing::Point(29, 132); this->label6->Name = L"label6"; this->label6->Size = System::Drawing::Size(44, 13); this->label6->TabIndex = 7; this->label6->Text = L"polomer"; // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(292, 266); this->Controls->Add(this->label6); this->Controls->Add(this->label5); this->Controls->Add(this->label4); this->Controls->Add(this->textBox1); this->Controls->Add(this->label3); this->Controls->Add(this->label2); this->Controls->Add(this->button1); this->Controls->Add(this->label1); this->Name = L"Form1"; this->Text = L"Form1"; this->ResumeLayout(false); this->PerformLayout(); } #pragma endregion private: System::Void button1_Click(System::Object^ System::EventArgs^ e) {
sender,
double plocha,obvod,r; r=System::Convert::ToDouble(this->textBox1->Text); plocha=3.14*r*r; this->label4->Text =System::Convert::ToString(plocha); obvod=2*3.14*r; this->label5->Text =System::Convert::ToString(obvod); } }; }
Na následující obrazovce vidíme spuštěný program s hodnotou zadaného poloměru kruhu
74
Zadání Realizujte výpočet plochy a obvodu kruhu se zadáním vstupního parametru poloměru kruhu. V projektu navrhněte zaznamenání výpočtu do objektu listbox. Analýza Projektu navazuje na předcházející příklad, který rozšiřuje o nový objekt, kterým je listbox. Jednotlivé výpočty se budou provádět stejným způsobem jako v předchozím případě, a dále se provede uložení výstupních hodnot do řetězce, který se uloží do listboxu. Klíčová část zdrojového kódu se zvýrazněním vložení hodnot do listboxu: private: System::Void button1_Click(System::Object^ System::EventArgs^ e) {
sender,
double plocha,obvod,r; r=System::Convert::ToDouble(this->textBox1->Text); plocha=3.14*r*r; this->label4->Text =System::Convert::ToString(plocha); obvod=2*3.14*r; this->label5->Text =System::Convert::ToString(obvod); this->listBox1->Items->Add("obvod="+this->label5->Text+"plocha="+this>label4->Text); }
Garafický navrh jednotlivých objektů typu label, textBox a listbox je nanásledujícím obrázku. Jednotlivé vlastnosti objektu listbox můžeme vidět v pravé části obrazovky při vývoji projektu.
75
Na obrázku je ukázka výpočtu plochy a obvodu kruhu s postupným vložením tří výpočtů do listboxu. Po každém výpočtu dochází k zobrazení hodnot v objektech label a dále vložení do objektu listbox.
private: System::Void button1_Click(System::Object^ System::EventArgs^ e) {
sender,
double plocha,obvod,r; r=System::Convert::ToDouble(this->textBox1->Text); plocha=3.14*r*r; this->label4->Text =System::Convert::ToString(plocha); obvod=2*3.14*r; this->label5->Text =System::Convert::ToString(obvod);
76
this->listBox1->Items->Add("obvod="+this->label5>Text+"plocha="+this->label4->Text); }
private: System::Void listBox1_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e) { int x; x=listBox1->SelectedIndex; this->label4->Text =System::Convert::ToString(x); }
77
8. OOP C++ projekty s využitím numerických metod Následující části textu ukazují na řešení různých numerických metod pomocí C++ objektového programování. Cílem jednotlivých příkladů je vytvořit třídy s potřebnými metodami, které dovolují řešit problematiku výpočtu s využití numerické matematiky. Pro jednotlivé příklady je uveden princip metody a dále uveden ukázkový příklad pro výpočet. Pro ověření výpočtu je použit server woframalpha.com, který dovoluje provádět jednotlivé výpočty online. Výhodou je zadání vzorce funkce do vstupního řádku a program zobrazí hodnoty výpočtu s grafickým zobrazením počítané funkce.
8.1 C++ numerický výpočet určitého integrálu Numerický výpočet určitého integrálu vychází z postupného sčítaní hodnot podle výpočtových vzorců, které jsou vyjádřeny pro jednotlivé výpočtové metody. Výpočet se provádí v cyklu ve kterém je stanoven krok, který rozděluje interval horní a dolní meze na menší dílky, ve kterých se provádí výpočet. Celkový výsledek závisí na počtu dílků (velikosti zvoleného kroku). V našich příkladech je hodnota krok stanovena na 1/100 intervalu, abychom mohli sledovat různou přesnost výpočtu podle stanovených vzorců.
8.1.1 C++ Obdelníková metoda Tato metoda rozdělí interval od hodnoty a po hodnotu b na obdélníky, kdy spodní základna obdélníku je na ose x a představuje hodnotu kroku. Svislá hodnota obdélníku je funkční hodnota v místě kroku. Tímto způsobem postupně sčítáme obdélníky na určeném intervalu a tím dostáváme hodnotu určitého integrálu. Integrál tedy vyjadřuje plochu pod křivkou. V tomto případě plochu jednotlivých obdélníků. Analýza programu Vytvoření třídy integral class integral •
Použití dvou proměnných třídy, která představují meze a,b
• • • • •
double a; //horni mez integrace double b; //dolni dolni mez integrace Vytvoření metody pro výpočet integrálu integrace funkce vracející reálné číslo double integrace_o(); Použití pomocné metody f ve které napíšeme vzorec funkce pro výpočet integrálu
•
double f(double x);
Použitý vzorec:
78
Obr.: rozdělení intervalu pro určitou funkci na jednotlivé obdélníky
Algoritmus vyjádřený vývojovým diagramem.
79
Zdrojový kód: /*obdelníková metoda*/ #include using namespace std; class integral //oznaceni tridy OOP { public: // veřejně přístupna data double a; //horni mez integrace double b; //dolni dolni mez integrace //prototypy jednotlivych clenskych funkci double integrace_o(); void zadej(double x,double y); double f(double x); }; double integral:: f(double x) { double vysledek; vysledek=3*x*x-25*x+15; return vysledek; } double integral::integrace_o() //numericka integrace { int i; double bb; double krok,suma,obdel; krok=(b-a)/100; suma=0; for(i=0; i<100;i ++ ) //cyklus vypoctu integralu { bb=a+krok; /* vzorec vypoctu*/ obdel=f(bb)*krok; suma+=obdel; a+=krok; } //cout << "\nsuma integral = " << suma; return suma; } void integral::zadej(double x,double y)
80
{ a=x; b=y; } //hlavni program int main() { double x,y; //hodnota stran integral i1; //instance objektu cout << "vloz horni mez a : " << endl; cin >>x; cout << "vloz dolni b : " << endl; cin >>y; i1.zadej(x,y); //volani clenske funkce cout << "integral je: " << i1.integrace_o()<< endl;
system("PAUSE"); }
Výstup z programu s hodnotou určitého integrálu.
Integrovaná funkce: 3*x*x-25*x+15; a=0, b=6 Následující obrázek ukazuje hodnotu určitého integrálu s grafem průběhu funkce od dolní po horní mez intervalu. Hodnota integrálu = -144. Rozdíl 145.249 – 144 = 1.249
81
8.1.2 C++ lichoběžníková metoda Tato metoda používá stejného principu výpočtu pouze s tím rozdílem, že vzorec pro výpočet plochy není obdélník, ale lichoběžník. Tím se dopouští menší chyby při výpočtu plochy pod křivkou a hodnota výpočtu je přesnější. Analýza programu: Vytvoření třídy integral class integral •
Použití dvou proměnných třídy, která představují meze a,b
• • • • •
double a; //horni mez integrace double b; //dolni dolni mez integrace Vytvoření metody pro výpočet integrálu integrace funkce vracející reálné číslo double integrace_l(); Použití pomocné metody f ve které napíšeme vzorec funkce pro výpočet integrálu
•
double f(double x);
82
Algoritmus výpočtu: Je použit cyklus postupného sčítání lichoběžníků podle uvedeného vzorce. Způsob výpočtu je stejný jako u obdélníkové metody. Použité vzorce
Obr. Zobrazení jednotlivých lichoběžníků pod grafickým průběhem zadané funkce Zdrojová kód programu: /*lichobeznikova metoda*/ #include using namespace std; class integral //oznaceni tridy OOP { public: // veřejně přístupna data double a; //horni mez integrace double b; //dolni dolni mez integrace //prototypy jednotlivych clenskych funkci double integrace_l(); void zadej(double x,double y); double f(double x); }; double integral:: f(double x) { double vysledek; vysledek=3*x*x-25*x+15; return vysledek; }
83
double integral::integrace_l() //numericka integrace { int i; double bb; double krok,suma,lichobeznik; krok=(b-a)/100; suma=0; for(i=0; i<100;i ++ ) //cyklus vypoctu integralu { bb=a+krok; /* vzorec vypoctu*/ lichobeznik=(bb-a) * ((f(a)+f(bb))/2); suma+=lichobeznik; a+=krok; } //cout << "\nsuma integral = " << suma; return suma; } void integral::zadej(double x,double y) { a=x; b=y; } //hlavni program int main() { double x,y; //hodnota stran integral i1; //instance objektu cout << "vloz horni mez a : " << endl; cin >>x; cout << "vloz dolni b : " << endl; cin >>y; i1.zadej(x,y); //volani clenske funkce cout << "integral je: " << i1.integrace_l()<< endl;
system("PAUSE"); }
Pro trigonomické funkce je nutné připojit další knihovnu ve které jsou vzorce pro výpočet. #include #include <math.h>
84
Kvadratická rovnice 3*x*x-25*x+15 Hodnota integrálu = -144. Rozdíl 143.989 – 144 = 0.011 Je vidět, že vzorec pro lichoběžníkovou metodu přesněji počítá plochu pod křivkou, Ukázka pro integraci funkce sinus(x) od 0 po 6.28 Funkce sinus 0 – 6.28
Hodnota integrálu = 5.07309 e -006 Program 5.07142 e-006 Rozdíl 5.07309-5.07142 = 0.0167 e -006
85
8.1.3 C++ simpsonova metoda Tato metoda je nepřesnější pro výpočet hodnot určitého integrálu. Výpočet se provádí podle vzorce, který nejlépe vyjadřuje průběh funkce a proto plocha počítaná jako výsledný interval je nejpřesnější. Analýza programu Vytvoření třídy integral class integral •
Použití dvou proměnných třídy, která představují meze a,b
• • • • •
double a; //horni mez integrace double b; //dolni dolni mez integrace Vytvoření metody pro výpočet integrálu integrace funkce vracející reálné číslo double integrace_s(); Použití pomocné metody f ve které napíšeme vzorec funkce pro výpočet integrálu
•
double f(double x);
Použité vzorce
86
/*simpsonova metoda*/ #include #include <math.h> using namespace std; class integral //oznaceni tridy OOP { public: // veřejně přístupna data double a; //horni mez integrace double b; //dolni dolni mez integrace //prototypy jednotlivych clenskych funkci double integrace_s(); void zadej(double x,double y); double f(double x); }; double integral:: f(double x) { double vysledek; vysledek=3*x*x-25*x+15; return vysledek; } double integral::integrace_s() //numericka integrace { int i; double bb; double krok,suma,simpson; krok=(b-a)/100; suma=0; for(i=0; i<100;i ++ ) //cyklus vypoctu integralu { bb=a+krok; /* vzorec vypoctu*/ simpson=((bb-a)/6) * ((f(a)+4*f((a+bb)/2))+f(bb)); suma+=simpson; a+=krok; } //cout << "\nsuma integral = " << suma; return suma; } void integral::zadej(double x,double y) { a=x;
87
b=y; } //hlavni program int main() { double x,y; //hodnota stran integral i1; //instance objektu cout << "vloz horni mez a : " << endl; cin >>x; cout << "vloz dolni b : " << endl; cin >>y; i1.zadej(x,y); //volani clenske funkce cout << "integral je: " << i1.integrace_s()<< endl;
system("PAUSE"); } Výstup z programu:
Výsledek z programu Hodnota integrálu = -144. Rozdíl 144 – 144 = 0.00 Přestože program provedl pouze 100 kroků což je velmi hrubé rozdělení intervalu, výsledek je velmi přesný. Tato metoda je použitelné pro praxi nejlépe. Při výpočtu hodnoty funkce v cyklu musíme dát pozor aby nedocházelo k dělení nulou. Například u výpočtu integrálu funkce 1/sin(x) pokud zvolíme hodnoty mezí a=0 a b=3.14 Dochází k chybě výpočtu a hodnota integrálu není definována. Tento případ lze ošetřit programátorskou kontrolou výpočtu dané funkce. Testování programu na jiné trigonometrické funkci Výstup z programu u funkce 1/si(x):
88
Ukzka výpočtu hodnoty integrálu pomocí wolframalpha.com.
89
8.2 Numerické metody pro hledání kořenů funkcí Tyto metody postupnou interací hledají kořen funkce v zadaném intervalu. Nevýhodou těchto metod je to, že naleznou nejbližší kořen funkce a nedokáží zjistit, jestli je v zadaném intervalu více dalších kořenů. Tento problém musí řešit programátor pomocí vhodného způsobu zadávání horní a dolní meze. Rychlost s jakou nalezneme kořen závisí
8.2.1 C++ metoda půlení intervalu Analýza Tato metoda postupně rozděluje zadaný interval na poloviny a hledá rozdílná znamenka funkce a podle toho dělí na polovinu levý nebo pravý interval. Použité vzorce Zadání hodnot x1 a x2 s opačnými znaménky
Vypočtená hodnota x0 A přiřazení nového bodu pro x1 nebo x2 podíváme se, ve kterém z bodů x1 a x2má funkce f(x) stejné znaménko, jako v bodě x0 •
Jde li o bod
, pak dále uvažujeme
•
Jde li o bod
, pak dále uvažujeme
90
#include #include using namespace std; class puleni { public:
//oznaceni tridy OOP // veøejnì pøístupná data
double fx(double x); // moje funkce double x1,x2,x0; // hodnoty x1,x2,x0 double epsilon; // presnost double puleni_intervalu(); // jednotliva funkce void zadej(double a,double b); }; //---------------------------------double puleni::fx(double x) { return x*x-15*x+5; } //---------------------------------double puleni::puleni_intervalu() // clenská funkce { double vypocet,pom,x0;
91
epsilon=0.001; do { x0=(x1+x2)/2; /*dopnit*/ if((fx(x0)>0)&&(fx(x2)>0)) if((fx(x0)<0)&&(fx(x1)<0)) if((fx(x0)<0)&&(fx(x2)<0)) if((fx(x0)>0)&&(fx(x1)>0))
x2=x0; x1=x0; x2=x0; x1=x0;
if(fx(x0)<0) pom=-fx(x0); else pom=fx(x0); cout<< "jednotlive kroky--> x = " << x0 << endl; // vypis jednotlivych kroku }while(pom>epsilon); return x0; } //-----------------------------------void puleni::zadej(double a,double b) { x1=a; x2=b; } //-----------------------------------// hlavni program int main() { double a,b; puleni vyp; cout << "vloz x1: " << cin >>a; cout << "vloz x2: " << cin >>b;
endl; endl;
vyp.zadej(a,b); //volani clenske funkce cout << "metoda puleni intervalu--> x = " << vyp.puleni_intervalu()<< endl;
system("PAUSE"); }
92
Výstup z programu metody půlení intervalu
8.2.2 C++ metoda tečen Analýza Použité vzorce
93
Zdrojový kód programu: #include #include using namespace std; class tecna { public:
//oznaceni tridy OOP // veøejnì pøístupná data
double fx(double x); //nase funkce double fxd(double x); //derivace fce double x0,x1,epsilon,pom,hodnota;// vypocet double tecna_tecna(); void zadej(double a); }; //------------------------------------------double tecna::fx(double x) { return x*x-15*x+5; // nase funkce } //-------------------------------------------double tecna::fxd(double x) { return 2*x-15; //zderivovaná fce } //-------------------------------------------double tecna::tecna_tecna() { epsilon=0.001; // zadani presnosti do { x1=x0-(fx(x0)/fxd(x0)); //tecny //zjisteni presnosti if (fx(x1)<0)pom=-fx(x1); else pom=fx(x1); x0=x1; cout<< "jednotlive kroky--> x = " << x1 << endl; }while(pom>epsilon); hodnota=fx(x1); return x1; } //-------------------------------------------void tecna::zadej(double a) { x0=a; } //--------------------------------------------
94
//hlavni program int main() { double a; tecna vyp; cout << "vloz x0: " << cin >>a;
endl;
vyp.zadej(a); //volani clenske funkce cout << "metoda tecen--> x = " << vyp.tecna_tecna()<< endl; cout << "metoda tecen--> fx = " << vyp.hodnota<< endl; system("PAUSE"); }
Výstup dat z programu metody tečen.
8.2.3 C++ metoda sečen Analýza:
http://cs.wikipedia.org/wiki/Metoda_se%C4%8Den Použité vzorce:
95
Zdrojový kó d programu: #include #include using namespace std; class secna { public:
//oznaceni tridy OOP // veøejnì pøístupná data
double fx(double x); // moje funkce double x1,x2,x0,pom,hodnota; // hodnoty x1,x2,x0 double epsilon; // presnost double fx(); double secna_secna(); // jednotliva funkce void zadej(double a,double b); }; //--------------------------------------double secna::fx(double x) { return x*x-15*x+5; } //-------------------------------------double secna::secna_secna() //clenská fce { epsilon=0.00001; do { x2=x1-((fx(x1)*(x1-x0))/(fx(x1)-fx(x0))); //secny if (fx(x2)<0)pom=-fx(x2); else pom=fx(x2);
96
x0=x1;//presun bodu x1=x2; cout<< "jednotlive kroky--> x = " << x2 << endl; }while(pom>epsilon); hodnota=fx(x2); return x2; } //---------------------------------------------void secna::zadej(double a,double b) { x0=a; x1=b; } //----------------------------------------------//hlavni program int main() { double a,b; secna vyp; cout << "vloz x0: " << cin >>a; cout << "vloz x1: " << cin >>b;
endl; endl;
vyp.zadej(a,b); //volani clenske funkce cout << "metoda secen--> x = " << vyp.secna_secna()<< endl; cout << "metoda secen--> fx = " << vyp.hodnota<< endl; system("PAUSE"); }
Výstup z programu Funkce x*x-15*x+5
Program provede 4 kroky v cyklu pro nalezení řešení.
8.2.3 kontrolní otázky 97
9. Závěr
Použitá literatura
98