1 / 31

Počítače a programování 2

Počítače a programování 2. Tutori ál 1 8.2.2014 Jiří Šebesta. Kompletní informace naleznete na. http://www.urel.feec.vutbr.cz/~sebestaj/KPC 2E. T ÉMA. Organizace předmětu Preprocesor Funkce main() s argumenty Souborový vstup a výstup. Organizace předmětu (1/3). Rozvrh předmětu.

regis
Download Presentation

Počítače a programování 2

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. Počítače a programování 2 Tutoriál 1 8.2.2014 Jiří Šebesta • Kompletní informace naleznete na http://www.urel.feec.vutbr.cz/~sebestaj/KPC2E

  2. TÉMA Organizace předmětu Preprocesor Funkce main() s argumenty Souborový vstup a výstup

  3. Organizace předmětu (1/3) Rozvrh předmětu

  4. Organizace předmětu (2/3) Domácí úlohy

  5. Organizace předmětu (3/3) Hodnocení

  6. Proces generování spustitelného kódu Preprocesor (1/13) Úkolem preprocesoru je: • odstranit komentáře ze zdrojového kódu • vložit soubory, které mají být kompilovány • odstranit části kódu určeného direktivami #if • rozvinout předdefinovaná makra

  7. Preprocesor (2/13) Vložení jiného souboru do souboru – direktiva #include #include <jméno souboru> nový_řádek – pro vložení standardního hlavičkového souboru (musí být v adresáři pro standardní hlavičkové soubory) př. #include <stdio.h> Činnost preprocesoru lze řídit direktivami: - začínají vždy znakem# #include “jméno souboru” nový_řádek – pro vložení vlastního zdrojového (hlavičkového) souboru (musí být v adresáři projektu nebo lze specifikovat i s cestou) př. #include “my_lib.h“

  8. #include MAKRO nový_řádek – pro vložení (rozvinutí) MAKRA specifikovaného dříve uvedenou direktivou #define (viz dále) (nesmí obsahovat < > “) př. #include my_macro Preprocesor (3/13) Definice maker – direktiva #define Makro (makroinstrukce) nahrazuje posloupnost znaků posloup-ností nahrazujících znaků #defineidentifikátor řetězec nový_řádek – makro bez parametrů př. #definePI 3.1415 - za všechna PI nahradí ve zdrojovém textu 3.1415

  9. Preprocesor (4/13) Není-li řetězec uveden, identifikátor je preprocesorem ze zdrojového textu odstraněn #defineidentifikátor(seznam_parametrů) řetězec nový_řádek – makro s parametry př. #defineABS(re,im) sqrt(((re)*(re))+((im)*(im))) Každý výskyt identifikátoruje nahrazen řetězcem, to neplatí v komentářích, řetězcích mezi “ “ a mezi < > v direktivě#include Vkládání závorek je důležité pro specifikaci priority operátorů: Pokud bude makro #defineABS(re,im) sqrt(re*re+im*im) a ve zdrojovém kódu c = ABS(a+1,b-1) pak po nahrazení preprocesorem bude: c =sqrt(a+1*a+1+b-1*b-1) po zjednodušení výrazu: c =sqrt(2*a)

  10. Preprocesor (5/13) #include <stdio.h> #include <math.h> #define PI 3.1415 #define ABS(re,im) sqrt(((re)*(re))+((im)*(im))) int main() { float r =12, ar=1.6,ai=2.2; printf("Circle area is %f\n", PI*r*r); printf("Absolute value of %f + j*%f is %f\n",ar,ai, ABS(ar,ai)); return0; } Makro pro absolutní hodnotu komplexního čísla Příklad: Ex76.c

  11. Preprocesor (6/13) #include <stdio.h> #include <math.h> #define ROOT1(a,b,c) (-(b)+sqrt((b)*(b)-4*(a)*(c)))/(2*(a)) #define ROOT2(a,b,c) (-(b)-sqrt((b)*(b)-4*(a)*(c)))/(2*(a)) int main() { float fa =1.3, fb =5.6, fc =1.2; int ia =1, ib=5, ic=2; printf("Roots for eq. %3.1fx^2+%3.1fx+%3.1f=0 are %5.3f and %5.3f\n", fa, fb, fc, ROOT1(fa, fb, fc), ROOT2(fa, fb, fc)); printf("Roots for eq. %dx^2+%dx+%d=0 are %5.3f and %5.3f\n", ia, ib, ic, ROOT1(ia, ib, ic), ROOT2(ia, ib, ic)); return0; } Parametry v makru mohou reprezentovat různé datové typy – makro je univerzální (v příkladu float a int) Příklad: Ex77.c

  12. Nevhodné použití makra Preprocesor (7/13) #include <stdio.h> #define POW3(A) ((A)*(A)*(A)) int main() { intx= 10; printf("%d^3 = %d\n", x,POW3(x)); printf("%d\n",POW3(++x)); return0; } V prvním použití makra POW3 je vše v pořádku Přidruhém použití makra POW3 bude rozvoj následující: ((++x)*(++x)*(++x)) , výsledek bude 12*12*13 = 1872 (proč?) Příklad: Ex78.c

  13. Operátory # a ## v makrech Preprocesor (8/13) #include <stdio.h> #define SUM(A,B) printf("%s = %d\n",#A " + " #B,(A)+(B)) #define JOINT(A,B) A ## B int main() { int n1 = 10, n2 = 20; SUM(5,6); SUM(JOINT(n,1),JOINT(n,2)); return0; } Operátory # a ## se používají v makrech s parametry. Za operátor # se dosadí řetězec, který je stejný jako parametr makra. Operátor ## spojí své dva parametry v jeden řetězec. Příklad: Ex79.c

  14. Standardní makra (ANSI C) Preprocesor (9/13) #include <stdio.h> int main() { printf("%s\n", __TIME__); printf("%s\n", __DATE__); printf("%s\n", __FILE__); printf("%d\n", __LINE__); printf("%d\n", __STDC__); return0; } __TIME__- aktuální čas spuštění preprocesoru (vrací řetězec) __DATE__- aktuální datum spuštění preprocesoru (vrací řetězec) __FILE__- jméno souboru zpracovávaného preprocesorem (vrací řetězec) __LINE__- číslo aktuálního řádku (vrací int) __STDC__- definuje, zda překladač splňuje normu ANSI (vrací int – 1 splňuje / 0 nesplňuje) Příklad: Ex80.c

  15. Rušení platnosti maker – direktiva #undef Preprocesor (10/13) #undefidentifikátor – od daného místa se ruší platnost makra př. #definePI 3.1415 … … #undef PI … // PI se už dále nenahrazuje #define PI 3.14 … // PI se zde nahrazuje za 3.14

  16. Podmíněný překlad – direktivy #if, #endif, #elif, #else Preprocesor (11/13) #if podmínka_A zdrojový kód pro splněnou podmínku_A #elif podmínka_B zdrojový kód pro splněnou podmínku_B (nesplněna podmínka_A) #elif podmínka_C zdrojový kód pro splněnou podmínku_C (nesplněna A i B) #else zdrojový kód pro stav, kdy žádná z předchozích podmínek nebyla splněna #endif V podmínkách musí být výrazy, které může vyhodnotit preprocesor (nelze používat hodnoty proměnných atd.).

  17. Preprocesor (12/13) #include <stdio.h> #define DEBUGING 2 int main() { int a =10; #if DEBUGING==1 a++; #elif DEBUGING==2 a=a*a*a; #else a=0; #endif printf("%d\n", a); return0; } Podmíněný překlad lze využít při různých úrovních ladění Příklad: Ex81.c

  18. Podmíněný překlad – direktivy #ifdef, #ifndef Preprocesor (13/13) Pomocí #if defined lze vyhodnocovat, zda již existuje určité makro (bylo-li definováno), zkráceně#ifdef. Pomocí #if !defined lze vyhodnocovat, zda neexistuje určité makro (nebylo-li definováno), zkráceně#ifndef. Nejčastěji se používá pro ošetření násobné definice: #ifndef PI #define PI 3.1415 #endif … #ifdef PI c = 2*PI*r; #endif

  19. Funkce main() s argumenty (1/4) Definicí argumentů (parametrů) u funkce main() můžeme definovat chování programu při spuštění. Program s parametry se spouští z příkazové řádky názvem programu (projektu) následovaný parametry oddělené mezerou, např. Muj_program 10 input.txt output.txt -x • Hlavička funkce main() s argumenty • int main(int argc, char *argv[]) • proměnné argc a argv jsou lokální proměnné funkce main(), (mohou mít i libovolné jiné názvy, typ musí být zachován) • argc udává počet zadaných parametrů při spuštění programu • argv je pole řetězců s jednotlivými zadanými argumenty

  20. Funkce main() s argumenty (2/4) Po spuštění programu je do proměnné argc uložena hodnota odpovídající počtu řetězců uvedených na příkazovém řádku v okamžiku spuštění programu. Tento počet zahrnuje i vlastní název programu. Proměnná argv je dvourozměrné pole typu char (jednorozměrné pole řetězců). Do tohoto pole řetězců jsou uloženy všechny řetězce uvedené na příkazovém řádku, do argv[0] je tedy uložen název programu. Počet řetězců v poli odpovídá hodnotě uložen v proměnné argc. Délka jednotlivých řádků pole argv odpovídá délce vložených řetězců. Pokud je potřeba jako vstup programu číselná hodnota, musí se v těle funkce main() provést konverze na požadovaný číselný formát.

  21. Funkce main() s argumenty (3/4) #include <stdio.h> int main(int argc,char*argv[]) { int n; printf("Number of arguments: %d\n\n", argc); printf("List of arguments:\n"); for(n =0; n < argc; n++) printf("argv[%d] = %s\n", n, argv[n]); return0; } Příklad programu, který vypíše počet argumentů a všechny řetězce argumentů Příklad: Ex82.c

  22. Funkce main() s argumenty (4/4) #include <stdio.h> #include <stdlib.h> int main(int argc,char*argv[]) { int n, m; n = atoi(argv[1]); m = n; while(n <=1000) { printf("%3d\n", n); n += m; } return0; } Příklad programu, který vypíše všechny násobky vstupního argumentu do 1000 včetně Příklad: Ex83.c

  23. Souborový vstup a výstup (1/2) Binární vs. textový soubor • Binární soubor • - překladač neprovádí žádnou úpravu čtených a zapisovaných dat • uspořádání dat v souboru je nezávislé a specifické pro dané využití • přenositelnost binárních souborů mezi různými systémy může být omezena rozdílnou délkou základních typů v těchto různých systémech – nutno vždy vhodně ošetřit ANSI C používá tzv. bufferovaný přístup k souborům pomocí proudu (stream) nebo-li ukazatele na strukturu typu FILE (definice v knihovně stdio.h) V ANCI C není rozdíl mezi souborem a zařízením (portem) – přistupuje se stejně

  24. Textový soubor • uspořádán po řádcích, každý zakončen znakem \n • v některých OS se před \n vkládá \r(úpravu zajišťují funkce ze standardní knihovny stdio.h. • lze zobrazit libovolným editorem Souborový vstup a výstup (2/2) • FILE • uspořádán po řádcích, každý zakončen znakem \n • v některých OS se před \n vkládá \r(úpravu zajišťují funkce ze standardní knihovny stdio.h. • lze zobrazit libovolným editorem

  25. Souboru typu WAV – bezkompresní audio Souborový vstup a výstup (3/2) Struktura souboru WAV (podmnožina RIFF)

  26. Příklad: Vygenerujte soubor typu WAV, který bude obsahovat jeden tón dané frekvence, amplitudy, doby trvání a jména cílového WAV souboru (argumenty při spouštění programu) Souborový vstup a výstup (4/2) #include <stdio.h> #include <stdlib.h> #include <math.h> #define TPI 6.283 int fwrite_int(int val,char len, FILE *p) { char byte; while(len-->0) { byte = val &0xFF; fwrite(&byte, 1, 1, p); val >>=8; } return0; } Pomocná funkce pro zápis různě dlouhých dat hlavičky do WAV souboru

  27. int main(int argc, char*argv[]) { doubleph, deltaph, tdur, ampl, freq; intnumsa, srate; unsigned char sig; FILE *ptrf; if(argc ==5) { srate =8000;// fixed sample rate 8 kHz freq = atof(argv[1]);// tone freq - 1. argument in Hz ampl = atof(argv[2]);// tone amplitude - 2. argument tdur = atof(argv[3]);// tone duration - 3. argument in s numsa = tdur*srate;// overall number of samples ph =0;// initial phase 0 rad deltaph = TPI * freq /srate;// delta phase ptrf = fopen(argv[4],"wb"); fwrite("RIFF",4,1, ptrf);// chunk_id RIFF fwrite_int(36+ numsa,4, ptrf);// chunk_size fwrite("WAVE",4,1, ptrf);// spec. RIFF form for WAV fwrite("fmt",4,1, ptrf);// subchunk1id - format Souborový vstup a výstup (5/2)

  28. fwrite_int(16,4, ptrf);// subchunk1size 16 for PCM fwrite_int(1,2, ptrf);// audio_format, 1 = PCM fwrite_int(1,2, ptrf);// channels, 1=mono fwrite_int(srate,4, ptrf);// sample rate fwrite_int(srate *1*8/8,4, ptrf);// byte rate fwrite_int(1*8/8, 2, ptrf);// block align fwrite_int(8,2, ptrf);// bits per sample, 8 bits fwrite("data",4,1, ptrf);// subchunk2id - data fwrite_int(numsa *1*8/8,4, ptrf);// subchunk2 size while(numsa-->0) { sig =128*(ampl*sin(ph)+1); fwrite(&sig,1,1, ptrf); ph += deltaph; } fclose(ptrf); } else printf("Wrong number of arguments!!!!\n"); return0; } Souborový vstup a výstup (6/2) Příklad: Ex84.c

  29. Příklad: Vygenerujte soubor typu WAV, který bude měnit tón od zadané frekvence do zadané frekvence, s danou amplitudou, dobou trvání a jménem cílového WAV souboru (argumenty při spouštění programu) Souborový vstup a výstup (7/2) Příklad: Ex85.c - bude zveřejněn 17.2.2014

  30. Příklad – domácí úloha: Sestavte program, který vygeneruje soubor typu WAV, který bude obsahovat DTMF signální volbu podle zadaného kódu. Kód a cílový soubor jsou argumenty při spouštění programu. V programu proveďte rovněž korekci možných znaků DTMF kód, nepovolené znaky vylučte. Jeden dvojtón trvá 50 ms následuje mezera 50 ms. Souborový vstup a výstup (8/2) Příklad: Ex86.c– bude zveřejněn 24.2.2014

  31. TÉMA NÁSLEDUJÍCÍHOTUTORIÁLU Úvod do objektově orientovaného DĚKUJI ZA POZORNOST

More Related