Programowanie Proceduralne

Transkrypt

Programowanie Proceduralne
Programowanie Proceduralne
Programowanie Proceduralne
Bożena Woźna-Szcześniak
[email protected]
Jan Długosz University, Poland
Wykład 3
Programowanie Proceduralne
Typ zmiennoprzecinkowy
Typy zmiennoprzecinkowy
float Najmniejszy typ rzeczywisty w C. Dobry do
obliczeń z dokładnościa˛ do 6 miejsc po przecinku.
Obliczenia przy użyciu tego typu sa˛ szybkie, ale
łatwo można uzyskać przepełnienie. Typowa
wartość minimalna to 10−38 . Typowa wartość
maksymalna to 1038 .
double “Średni” typ rzeczywisty w C. Dobry do obliczeń z
dokładnościa˛ do 12 miejsc po przecinku. Typowa
wartość minimalna to 10−308 . Typowa wartość
maksymalna to 10308 . Znacznie wolniejszy w
obliczeniach od float, ale za to bardziej
precyzyjny.
Programowanie Proceduralne
Typ zmiennoprzecinkowy
Typy zmiennoprzecinkowy
long double Najwiekszy
˛
typ rzeczywisty w C. Dobry do
obliczeń z dokładnościa˛ do 18 miejsc po
przecinku. Typowa wartość minimalna to 10−4000 .
Typowa wartość maksymalna to 104000 . Obliczenia
sa˛ najwolniejsze, ale najbardziej dokładne.
float.h Zbiór nagłówkowy zawierajacy
˛ stałe zwiazane
˛
z
typem zmiennoprzecinkowym.
Programowanie Proceduralne
Typ zmiennoprzecinkowy
Typ zmiennoprzecinkowy - float.h
1
2
3
4
5
6
7
8
9
# include < s t d i o . h>
# include < f l o a t . h>
i n t main ( void )
{
p r i n t f ( " f l o a t min=%g , max=%g \ n " , FLT_MIN ,FLT_MAX ) ;
p r i n t f ( " double min=%l g , max=%l g \ n " , DBL_MIN ,DBL_MAX ) ;
p r i n t f ( " l o n g double min=%Lg , max=%Lg \ n " , LDBL_MIN ,LDBL_MAX ) ;
return 0;
}
float min=1.17549e-38, max=3.40282e+38
double min=2.22507e-308, max=1.79769e+308
long double min=3.3621e-4932, max=1.18973e+4932
Programowanie Proceduralne
Typ zmiennoprzecinkowy
double
Typ zmiennoprzecinkowy - double
%lf printf wyświetla liczbe˛ rzeczywista˛ z dokładnościa˛
do 6 miejsc po przecinku.
%le printf wyświetla liczbe˛ rzeczywista˛ z dokładnościa˛
do 6 miejsc po przecinku, ale w notacji wykładniczej.
Np., 1.200000e − 05 znaczy 1.2 · 10−5 .
%lg printf wyświetla liczbe˛ rzeczywista˛ z pominieciem
˛
“zbednych”
˛
zer i w najkrótszej możliwej postaci. Np.
Zamiast 0.000012 dostajemy 1.2e-05.
%a.blf a (np., a=7) wskazuje szerokość liczby, b (np. b=2)
wskazuje precyzje˛ (dokładność po przecinku).
%.2le Dokładność do 2 miejsc po przecinku w formacie
wykładniczym.
%.4lg Dokładność do 4 miejsc po przecinku w “zwiezłym”
˛
formacie.
Programowanie Proceduralne
Typ zmiennoprzecinkowy
double
Typ zmiennoprzecinkowy - double - przykład 1
1
2
3
4
5
6
7
8
9
10
11
# include < s t d i o . h>
# include < f l o a t . h>
i n t main ( void )
{
double f = 3.1416 , g = 1 .2 e−5, h = 5000000000.0;
p r i n t f ( " f=% l f \ t g=% l f \ t h=% l f \ n " , f , g , h ) ;
p r i n t f ( " f=%l e \ t g=%l e \ t h=%l e \ n " , f , g , h ) ;
p r i n t f ( " f=%l g \ t g=%l g \ t h=%l g \ n " , f , g , h ) ;
p r i n t f ( " f =%7.2 l f \ t g =%.2 l e \ t h =%.4 l g \ n " , f , g , h ) ;
return 0;
}
Programowanie Proceduralne
Typ zmiennoprzecinkowy
double
Typ zmiennoprzecinkowy - double - przykład 1,
wykonanie
1
2
3
4
5
6
7
8
9
10
11
# include < s t d i o . h>
# include < f l o a t . h>
i n t main ( void )
{
double f = 3.1416 , g = 1 .2 e−5, h = 5000000000.0;
p r i n t f ( " f=% l f \ t g=% l f \ t h=% l f \ n " , f , g , h ) ;
p r i n t f ( " f=%l e \ t g=%l e \ t h=%l e \ n " , f , g , h ) ;
p r i n t f ( " f=%l g \ t g=%l g \ t h=%l g \ n " , f , g , h ) ;
p r i n t f ( " f =%7.2 l f \ t g =%.2 l e \ t h =%.4 l g \ n " , f , g , h ) ;
return 0;
}
f=3.141600
f=3.141600e+00
f=3.1416
f=
3.14
g=0.000012
g=1.200000e-05
g=1.2e-05
g=1.20e-05
h=5000000000.000000
h=5.000000e+09
h=5e+09
h=5e+09
Programowanie Proceduralne
Typ zmiennoprzecinkowy
float
Typ zmiennoprzecinkowy - float - przykład 2
1
2
3
4
5
6
7
8
9
10
11
# include < s t d i o . h>
# include < f l o a t . h>
i n t main ( void )
{
f l o a t f = 3.1416 f , g = 1 .2 e−5f , h = 5000000000.0 f ;
p r i n t f ( " f=%f \ t g=%f \ t h=%f \ n " , f , g , h ) ;
p r i n t f ( " f=%e \ t g=%e \ t h=%e \ n " , f , g , h ) ;
p r i n t f ( " f=%g \ t g=%g \ t h=%g \ n " , f , g , h ) ;
p r i n t f ( " f =%7.2 f \ t g =%.2e \ t h =%.4g \ n " , f , g , h ) ;
return 0;
}
Programowanie Proceduralne
Typ zmiennoprzecinkowy
float
Typ zmiennoprzecinkowy - float - przykład 2,
wykonanie
1
2
3
4
5
6
7
8
9
10
11
# include < s t d i o . h>
# include < f l o a t . h>
i n t main ( void )
{
f l o a t f = 3.1416 f , g = 1 .2 e−5f , h = 5000000000.0 f ;
p r i n t f ( " f=%f \ t g=%f \ t h=%f \ n " , f , g , h ) ;
p r i n t f ( " f=%e \ t g=%e \ t h=%e \ n " , f , g , h ) ;
p r i n t f ( " f=%g \ t g=%g \ t h=%g \ n " , f , g , h ) ;
p r i n t f ( " f =%7.2 f \ t g =%.2e \ t h =%.4g \ n " , f , g , h ) ;
return 0;
}
f=3.141600
f=3.141600e+00
f=3.1416
f=
3.14
g=0.000012
g=1.200000e-05
g=1.2e-05
g=1.20e-05
h=5000000000.000000
h=5.000000e+09
h=5e+09
h=5e+09
Programowanie Proceduralne
Typ zmiennoprzecinkowy
float
Typ zmiennoprzecinkowy - long double - przykład 3,
wykonanie
1
2
3
4
5
6
7
8
9
10
11
# include < s t d i o . h>
# include < f l o a t . h>
i n t main ( void )
{
long double f = 3.1416 L , g = 1 .2 e−5L ,
p r i n t f ( " f=%L f \ t g=%L f \ t h=%L f \ n " , f , g ,
p r i n t f ( " f=%Le \ t g=%Le \ t h=%Le \ n " , f , g ,
p r i n t f ( " f=%Lg \ t g=%Lg \ t h=%Lg \ n " , f , g ,
p r i n t f ( " f =%7.2 L f \ t g =%.2Le \ t h =%.4Lg \ n "
return 0;
}
f=3.141600
f=3.141600e+00
f=3.1416
f=
3.14
h = 5000000000.0L ;
h);
h);
h);
, f , g, h);
g=0.000012
g=1.200000e-05
g=1.2e-05
g=1.20e-05
h=5000000000.000000
h=5.000000e+09
h=5e+09
h=5e+09
Programowanie Proceduralne
Typ wyliczeniowy
Typ wiliczeniowy
◮
Typ wyliczeniowy to automatyczny mechnizm służacy
˛ do
generowania stałych o konkretnych nazwach.
◮
Przykład:
enum dzien { poniedzialek, wtorek, sroda,
czwartek, piatek, sobota, niedziela }
◮
W typie wyliczeniowym pierwsza wartość domyślnie jest
równa zero (patrz przykład 1).
◮
Każda nastepna
˛
ma wartość wieksz
˛
a˛ o jeden - chyba że
zostanie zdefiniowana inaczej (patrz przykłady 2 i 3).
◮
Stałe definiowane przy pomocy enums sa˛
implementowane przez kompilator jako “typy calkowite”.
Konkretny typ – int, long, long long – jest
dobierany na podstawie wartości stałej.
Programowanie Proceduralne
Typ wyliczeniowy
Typ wiliczeniowy
◮
Typ wyliczeniowy to automatyczny mechnizm służacy
˛ do
generowania stałych o konkretnych nazwach.
◮
Przykład:
enum dzien { poniedzialek, wtorek, sroda,
czwartek, piatek, sobota, niedziela }
◮
W typie wyliczeniowym pierwsza wartość domyślnie jest
równa zero (patrz przykład 1).
◮
Każda nastepna
˛
ma wartość wieksz
˛
a˛ o jeden - chyba że
zostanie zdefiniowana inaczej (patrz przykłady 2 i 3).
◮
Stałe definiowane przy pomocy enums sa˛
implementowane przez kompilator jako “typy calkowite”.
Konkretny typ – int, long, long long – jest
dobierany na podstawie wartości stałej.
Programowanie Proceduralne
Typ wyliczeniowy
Typ wiliczeniowy
◮
Typ wyliczeniowy to automatyczny mechnizm służacy
˛ do
generowania stałych o konkretnych nazwach.
◮
Przykład:
enum dzien { poniedzialek, wtorek, sroda,
czwartek, piatek, sobota, niedziela }
◮
W typie wyliczeniowym pierwsza wartość domyślnie jest
równa zero (patrz przykład 1).
◮
Każda nastepna
˛
ma wartość wieksz
˛
a˛ o jeden - chyba że
zostanie zdefiniowana inaczej (patrz przykłady 2 i 3).
◮
Stałe definiowane przy pomocy enums sa˛
implementowane przez kompilator jako “typy calkowite”.
Konkretny typ – int, long, long long – jest
dobierany na podstawie wartości stałej.
Programowanie Proceduralne
Typ wyliczeniowy
Typ wiliczeniowy
◮
Typ wyliczeniowy to automatyczny mechnizm służacy
˛ do
generowania stałych o konkretnych nazwach.
◮
Przykład:
enum dzien { poniedzialek, wtorek, sroda,
czwartek, piatek, sobota, niedziela }
◮
W typie wyliczeniowym pierwsza wartość domyślnie jest
równa zero (patrz przykład 1).
◮
Każda nastepna
˛
ma wartość wieksz
˛
a˛ o jeden - chyba że
zostanie zdefiniowana inaczej (patrz przykłady 2 i 3).
◮
Stałe definiowane przy pomocy enums sa˛
implementowane przez kompilator jako “typy calkowite”.
Konkretny typ – int, long, long long – jest
dobierany na podstawie wartości stałej.
Programowanie Proceduralne
Typ wyliczeniowy
Typ wiliczeniowy
◮
Typ wyliczeniowy to automatyczny mechnizm służacy
˛ do
generowania stałych o konkretnych nazwach.
◮
Przykład:
enum dzien { poniedzialek, wtorek, sroda,
czwartek, piatek, sobota, niedziela }
◮
W typie wyliczeniowym pierwsza wartość domyślnie jest
równa zero (patrz przykład 1).
◮
Każda nastepna
˛
ma wartość wieksz
˛
a˛ o jeden - chyba że
zostanie zdefiniowana inaczej (patrz przykłady 2 i 3).
◮
Stałe definiowane przy pomocy enums sa˛
implementowane przez kompilator jako “typy calkowite”.
Konkretny typ – int, long, long long – jest
dobierany na podstawie wartości stałej.
Programowanie Proceduralne
Typ wyliczeniowy
enum - przykład 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# include < s t d i o . h>
enum m i e s i a c { p o n i e d z i a l e k , wtorek , sroda , czwartek , p i a t e k , / /
sobota , n i e d z i e l a } ;
i n t main ( void )
{
enum m i e s i a c d z i s = wtorek ;
while ( d z i s != sobota ) {
p r i n t f ( " Dzi ś j e s t %d d z i e n t y g o d n i a wiec s i e˛ ucze ! \ n " , d z i s + 1 ) ;
d z i s ++;
}
p r i n t f ( " Dzi ś j e s t %d d z i e n ty g o d n i a , c z y l i sobota " ,++ d z i s ) ;
p r i n t f ( " wi ec
˛ mam wolne : ) ! \ n " ) ;
p r i n t f ( " J u t r o j e s t %d d z i e n ty g o d n i a , c z y l i n i e d z i e l a " ,++ d z i s ) ;
p r i n t f ( " wi ec
˛ mam t e ż wolne : ) ! \ n " ) ;
return 0;
}
Programowanie Proceduralne
Typ wyliczeniowy
enum - przykład, wykonanie
e ucze !
Dziś jest 2 dzien tygodnia wiec si˛
Dziś jest 3 dzien tygodnia wiec si˛
e ucze !
Dziś jest 4 dzien tygodnia wiec si˛
e ucze !
Dziś jest 5 dzien tygodnia wiec si˛
e ucze !
Dziś jest 6 dzien tygodnia czyli sobota wi˛
ec
mam wolne :)!
Jutro jest 7 dzien tygodnia czyli niedziela
wi˛
ec mam też wolne :)!
Programowanie Proceduralne
Typ wyliczeniowy
enum - przykład 2
1
2
3
4
5
6
7
8
9
10
# include < s t d i o . h>
enum m i e s i a c { s ty c z e n =1 , l u t y , marzec , kwiecien , maj , czerwiec , l i p i e c , / /
s i e r p i e n , wrzesien , p a z d z i e r n i k , l i s t o p a d , g r u d z i e n } ;
i n t main ( void ) {
p r i n t f ( "%d , %d , %d , " , styczen , l u t y , marzec ) ;
p r i n t f ( "%d , %d , %d , " , kwiecien , maj , c z e r w i e c ) ;
p r i n t f ( " . . . , %d . \ n " , g r u d z i e n ) ;
return 0;
}
1, 2, 3, 4, 5, 6,..., 12.
Programowanie Proceduralne
Typ wyliczeniowy
enum - przykład 2
1
2
3
4
5
6
7
8
9
10
# include < s t d i o . h>
enum m i e s i a c { s ty c z e n =1 , l u t y , marzec , kwiecien , maj , czerwiec , l i p i e c , / /
s i e r p i e n , wrzesien , p a z d z i e r n i k , l i s t o p a d , g r u d z i e n } ;
i n t main ( void ) {
p r i n t f ( "%d , %d , %d , " , styczen , l u t y , marzec ) ;
p r i n t f ( "%d , %d , %d , " , kwiecien , maj , c z e r w i e c ) ;
p r i n t f ( " . . . , %d . \ n " , g r u d z i e n ) ;
return 0;
}
1, 2, 3, 4, 5, 6,..., 12.
Programowanie Proceduralne
Typ wyliczeniowy
enum - przykład 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# include < s t d i o . h>
enum d i r e c t i o n { n o r t h = 0 , e a s t = 90 , south = 180 , west = 270 } ;
i n t main ( void ) {
int n;
do {
p r i n t f ( " Podaj co pokazuje kompas : " ) ;
s c a n f ( "%d " ,&n ) ;
switch ( n ) {
case n o r t h : p r i n t f ( " I d z na Polnoc ! \ n " ) ; break ;
case e a s t : p r i n t f ( " I d z na Wschod ! \ n " ) ; break ;
case south : p r i n t f ( " I d z na P o l u d n i e ! \ n " ) ; break ;
case west : p r i n t f ( " I d z na Zachod ! \ n " ) ; break ;
d e f a u l t : p r i n t f ( " Kierunek n i e p r a w i d ł o w y ! ! ! \ n " ) ; break ;
}
} while ( ! ( ( n== n o r t h ) | | ( n== e a s t ) | | ( n==south ) | | ( n==west ) ) ) ;
return 0;
}
Programowanie Proceduralne
Typ wyliczeniowy
enum - przykład 3, przykładowe wykonanie
Podaj co pokazuje kompas: 2
Kierunek nieprawidłowy !!!
Podaj co pokazuje kompas: 4
Kierunek nieprawidłowy !!!
Podaj co pokazuje kompas: 90
Idz na Wschod .
Programowanie Proceduralne
Typ wyliczeniowy
typdef i enum
◮
Standardowa definicja typu wyliczeniowego, wymaga
użycia słowa kluczowego enum przy definiowaniu
zmiennych tego typu, przy przekazywaniu argumentów do
funkcji, itd. (patrz przykład 1).
◮
Aby uniknać
˛ tak uciażliwego
˛
stosowania nowo
zdefiniowanego typu, można wykorzystać instrukcje˛ typdef
◮
Przykład:
typedef enum {poniedzialek, wtorek, sroda,
czwartek, piatek, sobota, niedziela}
miesiac;
miesiac dzis = wtorek;
Programowanie Proceduralne
Typ wyliczeniowy
typdef i enum
◮
Standardowa definicja typu wyliczeniowego, wymaga
użycia słowa kluczowego enum przy definiowaniu
zmiennych tego typu, przy przekazywaniu argumentów do
funkcji, itd. (patrz przykład 1).
◮
Aby uniknać
˛ tak uciażliwego
˛
stosowania nowo
zdefiniowanego typu, można wykorzystać instrukcje˛ typdef
◮
Przykład:
typedef enum {poniedzialek, wtorek, sroda,
czwartek, piatek, sobota, niedziela}
miesiac;
miesiac dzis = wtorek;
Programowanie Proceduralne
Typ wyliczeniowy
typdef i enum
◮
Standardowa definicja typu wyliczeniowego, wymaga
użycia słowa kluczowego enum przy definiowaniu
zmiennych tego typu, przy przekazywaniu argumentów do
funkcji, itd. (patrz przykład 1).
◮
Aby uniknać
˛ tak uciażliwego
˛
stosowania nowo
zdefiniowanego typu, można wykorzystać instrukcje˛ typdef
◮
Przykład:
typedef enum {poniedzialek, wtorek, sroda,
czwartek, piatek, sobota, niedziela}
miesiac;
miesiac dzis = wtorek;
Programowanie Proceduralne
Typ wyliczeniowy
typdef i enum - przykład 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# include < s t d i o . h>
typedef enum { p o n i e d z i a l e k , wtorek , sroda , czwartek , p i a t e k , / /
sobota , n i e d z i e l a } m i e s i a c ;
i n t main ( void )
{
m i e s i a c d z i s = wtorek ;
while ( d z i s != sobota ) {
p r i n t f ( " Dzi ś j e s t %d d z i e n t y g o d n i a wiec s i e˛ ucze ! \ n " , d z i s + 1 ) ;
d z i s ++;
}
p r i n t f ( " Dzi ś j e s t %d d z i e n ty g o d n i a , c z y l i sobota " ,++ d z i s ) ;
p r i n t f ( " wi ec
˛ mam wolne : ) ! \ n " ) ;
p r i n t f ( " J u t r o j e s t %d d z i e n ty g o d n i a , c z y l i n i e d z i e l a " ,++ d z i s ) ;
p r i n t f ( " wi ec
˛ mam t e ż wolne : ) ! \ n " ) ;
return 0;
}
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
Preprocessor jest rodzajem nie-interaktywnego edytora,
który jest “umieszczony na samym poczatku”
˛
kompilatora.
◮
Dzieki
˛ niemu kompilator nigdy nie widzi kodu napisanego
przez programiste, ale kod, który wygenerował
preprocessor.
◮
Dyrektywy preprocesora sa˛ zatem instrukcjami dla
kompilatora.
◮
Dyrektywy nie sa˛ jednak poleceniami jezyka
˛
C.
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
Preprocessor jest rodzajem nie-interaktywnego edytora,
który jest “umieszczony na samym poczatku”
˛
kompilatora.
◮
Dzieki
˛ niemu kompilator nigdy nie widzi kodu napisanego
przez programiste, ale kod, który wygenerował
preprocessor.
◮
Dyrektywy preprocesora sa˛ zatem instrukcjami dla
kompilatora.
◮
Dyrektywy nie sa˛ jednak poleceniami jezyka
˛
C.
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
Preprocessor jest rodzajem nie-interaktywnego edytora,
który jest “umieszczony na samym poczatku”
˛
kompilatora.
◮
Dzieki
˛ niemu kompilator nigdy nie widzi kodu napisanego
przez programiste, ale kod, który wygenerował
preprocessor.
◮
Dyrektywy preprocesora sa˛ zatem instrukcjami dla
kompilatora.
◮
Dyrektywy nie sa˛ jednak poleceniami jezyka
˛
C.
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
Preprocessor jest rodzajem nie-interaktywnego edytora,
który jest “umieszczony na samym poczatku”
˛
kompilatora.
◮
Dzieki
˛ niemu kompilator nigdy nie widzi kodu napisanego
przez programiste, ale kod, który wygenerował
preprocessor.
◮
Dyrektywy preprocesora sa˛ zatem instrukcjami dla
kompilatora.
◮
Dyrektywy nie sa˛ jednak poleceniami jezyka
˛
C.
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
Dyrektywy rozpoczynaja˛ sie˛ od znaku #
◮
Każda dyrektywa musi znajdować sie˛ w oddzielnym
wierszu.
Dyrektywa #include fizycznie wstawia w miejscu jej
wystapienia
˛
kod załaczonego
˛
pliku - kompilator zatem
widzi zawartość wymienionego w dyrektywie #include
pliku:
◮
◮
◮
#include <stdio.h>
#include “mybib.c”
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
Dyrektywy rozpoczynaja˛ sie˛ od znaku #
◮
Każda dyrektywa musi znajdować sie˛ w oddzielnym
wierszu.
Dyrektywa #include fizycznie wstawia w miejscu jej
wystapienia
˛
kod załaczonego
˛
pliku - kompilator zatem
widzi zawartość wymienionego w dyrektywie #include
pliku:
◮
◮
◮
#include <stdio.h>
#include “mybib.c”
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
Dyrektywy rozpoczynaja˛ sie˛ od znaku #
◮
Każda dyrektywa musi znajdować sie˛ w oddzielnym
wierszu.
Dyrektywa #include fizycznie wstawia w miejscu jej
wystapienia
˛
kod załaczonego
˛
pliku - kompilator zatem
widzi zawartość wymienionego w dyrektywie #include
pliku:
◮
◮
◮
#include <stdio.h>
#include “mybib.c”
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
◮
#define nazwa_makra ciag_znaków
˛
- służy do
definiowania tzw. makr (w tym makr funkcyjnych albo
funkcjo-podobnych).
Dyrektywa definiuje identyfikator oraz ciag
˛ znaków, który
bedzie
˛
zamiast niego wstawiany we wszystkich jego
wystapieniach
˛
w programie. Ciagiem
˛
znaków może być
np. stała (liczba, łańcuch) lub instrukcja.
Przykład:
◮
◮
◮
◮
#define ROZMIAR 150
#define EPS 3.5E-8
#define KOMUNIKAT “Wystapił
˛
niezidentyfikowany bład”
˛
#undef nazwa_makra - anuluje definicje˛ makra
◮
◮
◮
#undef ROZMIAR
#undef EPS
#undef KOMUNIKAT
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
◮
#define nazwa_makra ciag_znaków
˛
- służy do
definiowania tzw. makr (w tym makr funkcyjnych albo
funkcjo-podobnych).
Dyrektywa definiuje identyfikator oraz ciag
˛ znaków, który
bedzie
˛
zamiast niego wstawiany we wszystkich jego
wystapieniach
˛
w programie. Ciagiem
˛
znaków może być
np. stała (liczba, łańcuch) lub instrukcja.
Przykład:
◮
◮
◮
◮
#define ROZMIAR 150
#define EPS 3.5E-8
#define KOMUNIKAT “Wystapił
˛
niezidentyfikowany bład”
˛
#undef nazwa_makra - anuluje definicje˛ makra
◮
◮
◮
#undef ROZMIAR
#undef EPS
#undef KOMUNIKAT
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Dyrektywy preprocesora
◮
◮
#define nazwa_makra ciag_znaków
˛
- służy do
definiowania tzw. makr (w tym makr funkcyjnych albo
funkcjo-podobnych).
Dyrektywa definiuje identyfikator oraz ciag
˛ znaków, który
bedzie
˛
zamiast niego wstawiany we wszystkich jego
wystapieniach
˛
w programie. Ciagiem
˛
znaków może być
np. stała (liczba, łańcuch) lub instrukcja.
Przykład:
◮
◮
◮
◮
#define ROZMIAR 150
#define EPS 3.5E-8
#define KOMUNIKAT “Wystapił
˛
niezidentyfikowany bład”
˛
#undef nazwa_makra - anuluje definicje˛ makra
◮
◮
◮
#undef ROZMIAR
#undef EPS
#undef KOMUNIKAT
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# include < s t d i o . h>
i n t main ( void )
{
# d e f i n e EPS 3 .5E−8
double d = EPS ;
p r i n t f ( " Wprowadziles l i c z b e : %g <−> %.10 l f \ n " , d , d ) ;
# d e f i n e ROZMIAR 150
p r i n t f ( " Rozmiar = %d \ n " , ROZMIAR ) ;
# undef ROZMIAR
# d e f i n e ROZMIAR 15
p r i n t f ( "Nowy Rozmiar = %d \ n " , ROZMIAR ) ;
return 0;
}
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
Wprowadziles liczbe: 3.5e-08 <-> 0.0000000350
Rozmiar = 150
Nowy Rozmiar = 15
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
#define ABS(a) ((a)>=0 ? (a) : (-a))
◮
Powyższe makro oblicza wartość bezwzgledn
˛ a˛ z liczby
przekazanej argumentem a.
◮
W przeciwieństwie do funkcji, np. int abs(int,int);,
która mogłaby realizować podobne zadanie, makro ABS
akceptuje argumenty dowolnego typu arytmetycznego lub
nawet wskaźnikowego.
◮
Wada: może obliczać wartość argumentu a wielokrotnie co
powoduje generowanie wiekszego kodu.
◮
Uwaga ! Nawiasy sa˛ niezbedne
˛
do poprawnego obliczania
wyrażeń.
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# include < s t d i o . h>
# define ABS( a ) ( ( a) >=0 ? ( a ) : (−a ) )
i n t main ( void )
{
int a;
p r i n t f ( " Podaj l i c z b e˛ c a ł k o w i t a˛ : " ) ;
p r i n t f ( "ABS(%d ) = %d \ n " , a , ABS( a ) ) ;
s c a n f ( "%d " ,& a ) ;
double b ;
p r i n t f ( " Podaj l i c z b e˛ r z e c z y w i s t a˛ : " ) ; s c a n f ( "%l f " ,& b ) ;
p r i n t f ( "ABS(% l f ) = %l f \ n " , b ,ABS( b ) ) ;
p r i n t f ( "ABS(% l f ) = %l f \ n " , a−b , ABS( a−b ) ) ;
i n t ∗p=&a ; / / w y j a ś n i e n i e na nastenych wykładach
p r i n t f ( "ABS(%d ) = %d \ n " ,∗ p , ABS( ∗ p ) ) ;
return 0;
}
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
Podaj liczb˛
e całkowita:
˛ -3
ABS(-3) = 3
Podaj liczb˛
e rzeczywista:
˛ 78.2
ABS(78.200000) = 78.200000
ABS(-81.200000) = -75.200000
ABS(-3) = 3
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# include < s t d i o . h>
i n t main ( void )
{
# d e f i n e even ( x ) ( x ) % 2 ? 0 : 1
int a;
p r i n t f ( " Podaj l i c z b e : " ) ;
s c a n f ( "%d " ,& a ) ;
i f ( even ( a ) ) p r i n t f ( "%d j e s t p a r z y s t e \ n " , a ) ;
else p r i n t f ( "%d j e s t n i e p a r z y s t e \ n " , a ) ;
p r i n t f ( " Rozważmy 2∗a = %d \ n " ,2∗ a ) ;
i f ( even (2∗ a ) ) p r i n t f ( "%d j e s t p a r z y s t e \ n " ,2∗ a ) ;
else p r i n t f ( "%d j e s t n i e p a r z y s t e \ n " ,2∗ a ) ;
p r i n t f ( " Rozważmy 2+a = %d \ n " ,2+ a ) ;
i f ( even (2+ a ) ) p r i n t f ( "%d j e s t p a r z y s t e \ n " ,2+ a ) ;
else p r i n t f ( "%d j e s t n i e p a r z y s t e \ n " ,2+ a ) ;
return 0;
}
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
Podaj liczbe: 3
3 jest nieparzyste
Rozważmy 2*a = 6
6 jest parzyste
Rozważmy 2+a = 5
5 jest nieparzyste
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład źle zdefiniowanego makra
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# include < s t d i o . h>
i n t main ( void )
{
# d e f i n e even ( x ) x % 2 ? 0 : 1
int a;
p r i n t f ( " Podaj l i c z b e : " ) ;
s c a n f ( "%d " ,& a ) ;
i f ( even ( a ) ) p r i n t f ( "%d j e s t p a r z y s t e \ n " , a ) ;
else p r i n t f ( "%d j e s t n i e p a r z y s t e \ n " , a ) ;
p r i n t f ( " Rozważmy 2∗a = %d \ n " ,2∗ a ) ;
i f ( even (2∗ a ) ) p r i n t f ( "%d j e s t p a r z y s t e \ n " ,2∗ a ) ;
else p r i n t f ( "%d j e s t n i e p a r z y s t e \ n " ,2∗ a ) ;
p r i n t f ( " Rozważmy 2+a = %d \ n " ,2+ a ) ;
i f ( even (2+ a ) ) p r i n t f ( "%d j e s t p a r z y s t e \ n " ,2+ a ) ;
else p r i n t f ( "%d j e s t n i e p a r z y s t e \ n " ,2+ a ) ;
return 0;
}
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
Podaj liczbe: 3
3 jest nieparzyste
Rozważmy 2*a = 6
6 jest parzyste
Rozważmy 2+a = 5
5 jest nieparzyste
-----------------------Podaj liczbe: 4
4 jest parzyste
Rozważmy 2*a = 8
8 jest parzyste
Rozważmy 2+a = 6
6 jest nieparzyste
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
1
2
3
4
5
6
7
8
9
10
11
12
13
# include < s t d i o . h>
i n t main ( void )
{
# d e f i n e ABSDIFF ( a , b ) ( ( a ) > ( b ) ? ( a) −(b ) : ( b) −(a ) )
int a ,b ;
p r i n t f ( " Podaj 1 l i c z b e : " ) ; s c a n f ( "%d " ,&a ) ;
p r i n t f ( " Podaj 2 l i c z b e : " ) ; s c a n f ( "%d " ,&b ) ;
p r i n t f ( " ABSDIFF(%d,%d ) = %d \ n " , a , b , ABSDIFF ( a , b ) ) ;
# undef ABSDIFF
# d e f i n e MAX( a , b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
p r i n t f ( "MAX(%d,%d ) = %d \ n " , a , b ,MAX( a , b ) ) ;
return 0;
}
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
Podaj 1 liczbe: 5
Podaj 2 liczbe: 6
ABSDIFF(5,6) = 1
MAX(5,6) = 6
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# include < s t d i o . h>
# define y 1
# define kwadrat ( a ) ( ( a ) ∗ ( a ) )
# define x 2
# define g kwadrat
# define t ( a ) ( a )
i n t main ( void )
{
i n t a=y ; / / a=1
i n t b=x ; / / b=2
p r i n t f ( " a=%d , b=%d \ n " , a , b ) ;
a = t (a ) ;
p r i n t f ( " a= t ( a)=%d , b=%d \ n " , a , b ) ;
a = kwadrat ( b ) ;
p r i n t f ( " a=kwadrat ( b)=%d , b=%d \ n " , a , b ) ;
a = g(b ) ;
p r i n t f ( " a=g ( b)=%d , b=%d \ n " , a , b ) ;
a = kwadrat ( y + 1 ) ; p r i n t f ( " a = kwadrat ( y+1)=%d , y=%d \ n " , a , y ) ;
b = kwadrat ( kwadrat ( x ) ) ;
p r i n t f ( " x = %d , b = kwadrat ( kwadrat ( x ))=%d \ n " , x , b ) ;
b = t ( t (g (0)) + t ( 1 ) ) ;
p r i n t f ( " b = t ( t ( g ( 0 ) ) + t ( 1 ) ) = %d \ n " , b ) ;
return 0;
}
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
a=1, b=2
a=t(a)=1, b=2
a=kwadrat(b)=4,b=2
a=g(b)=4, b=2
a = kwadrat(y+1)=4, y=1
x = 2, b = kwadrat(kwadrat(x))=16
b = t(t(g(0)) + t(1)) = 1
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include < s t d i o . h>
i n t main ( void ) {
# d e f i n e s t r ( x ) #x
char c1 [ ] = s t r ( h e l l o ) ;
/ / char c1 [ ] = " h e l l o " ;
p r i n t f ( "%s \ n " , c1 ) ;
# d e f i n e s t r s t r ( x ) #x#x
char c2 [ ] = s t r s t r ( h e l l o ) ;
p r i n t f ( "%s \ n " , c2 ) ;
# d e f i n e s t r s t r s t r ( x ) #x#x#x
char c3 [ ] = s t r s t r s t r ( h e l l o ) ;
p r i n t f ( "%s \ n " , c3 ) ;
return 0;
}
Jeśli parametr w definicji makra
jest bezpośrednio poprzedzony
przez znak #, to parametr ten
zostaje ujety
˛ w znaki
cudzysłowu. Tzn.,
#parameter zostaje
zastapione
˛
przez
“parameter”. Nastepnie
˛
każdy cudzysłów jest
poprzedzony znakiem \.
hello
hellohello
hellohellohello
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
1
2
3
4
5
6
7
8
9
10
11
12
# include < s t d i o . h>
i n t main ( void )
{
# d e f i n e t e m p f i l e ( d i r ) # d i r " ma k o ta "
p r i n t f ( "%s \ n " , t e m p f i l e ( " Ala " ) ) ;
# undef t e m p f i l e
# d e f i n e t e m p f i l e ( d i r ) # d i r "%s "
p r i n t f ( t e m p f i l e ( / user / i n c l u d e / ) , " s t d d e f . h " ) ;
pri ntf ( " \n" );
p r i n t f ( t e m p f i l e ( " / user / i n c l u d e / " ) , " s t d d e f . h " ) ;
return 0;
}
"Ala" ma kota
/user/include/stddef.h
"/user/include/"stddef.h
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Przykład
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include < s t d i o . h>
i n t main ( void )
{
# d e f i n e c a t ( x , y ) x##y
#define xcat ( x , y ) cat ( x , y )
in t c = cat ( 1 , 2 ) ;
p r i n t f ( " \ n%d \ n " , c ∗ 2 ) ;
i n t c a t ( B ,WS) = 2011;
p r i n t f ( "BWS = %d \ n " ,BWS) ;
/ / i n t d= c a t ( c a t ( 1 , 2 ) , 3 ) ; − ZLE
in t d = xcat ( xcat ( 1 , 2 ) , 3 ) ;
p r i n t f ( " d = %d \ n " , d ) ;
return 0;
}
Jeśli definicja makra zawiera
wystapienie
˛
operatora ##, to
parametry zostaja˛ połaczone
˛
w
jeden token, a operator ##
usuniety.
˛ Dodatkowo makro
przestaje być już rozwijane.
24
BWS = 2011
d = 123
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - przykład
#include<stdio.h>
#define scat(x,y) #x #y
#define typ(y) scat(%,y)
#define END 10
#define FOREACH(TAB,BEGIN, END,format) \
for ( int i = BEGIN; i < (END); ++i)\
{ \
if (i % 3==0 ) printf ("\n"); \
printf("[%d] = ",i); \
printf(typ(format),TAB[i]);\
printf(", ");\
} \
printf("\n");
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - przykład
#include<stdio.h>
#define scat(x,y) #x #y
#define typ(y) scat(%,y)
#define END 10
//Podajemy tylko koniec
#define PRINTTAB(TAB,END,format) \
for ( int BEGIN = 0; (BEGIN) < (END); ++BEGIN)\
{ \
if (BEGIN % 3==0 ) printf ("\n"); \
printf("[%d] = ",BEGIN); \
printf(typ(format),TAB[BEGIN]);\
printf(", ");\
} \
printf("\n");
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - przykład
int main(void) {
int a[]={1,2,3};
printf("Tablica a, zakres [0..2]:");
FOREACH(a,0,sizeof(a)/sizeof(a[0]),d);
printf("Tablica a, zakres [0..9]:");
PRINTTAB(a,10,d);
double b[10]={1.0,22.0,3.3};
printf("Tablica a, zakres [0..9]:");
FOREACH(b,0,10,lf);
char c[]="ALA MA Kota";
printf("Tablica c:");
FOREACH(c,0,sizeof(c)/sizeof(c[0]),c);
PRINTTAB(c,sizeof(c)/sizeof(c[0]),c);
return 0;
}
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - przykład
Tablica a, zakres [0..2]:
[0] = 1, [1] = 2, [2] = 3,
Tablica a, zakres [0..9]:
[0] = 1, [1] = 2, [2] = 3,
[3] = 134513448, [4] = 10910560, [5] = 134520820,
[6] = 6, [7] = 3, [8] = 9913124,
[9] = 9912308,
Tablica a, zakres [0..9]:
[0] = 1.000000, [1] = 22.000000, [2] = 3.300000,
[3] = 0.000000, [4] = 0.000000, [5] = 0.000000,
[6] = 0.000000, [7] = 0.000000, [8] = 0.000000,
[9] = 0.000000,
Tablica c:
[0] = A, [1] = L, [2] = A,
[3] = , [4] = M, [5] = A,
[6] = , [7] = K, [8] = o,
[9] = t, [10] = a, [11] = ,
[0]
[3]
[6]
[9]
= A, [1] = L, [2] =
= , [4] = M, [5] =
= , [7] = K, [8] =
= t, [10] = a, [11]
A,
A,
o,
= ,
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - kompilacja warunkowa
◮
Dyrektywy kompilacji warunkowej: #if, #else,
#elif, #endif
◮
Dyrektywy kompilacji warunkowej pozwalaja˛ wybiórczo
kompilować fragmenty kodu źródłowego, pozwalaja˛ na
tworzenie różnych wersji programu.
◮
Z uwagi na to, że wartość wyrażenia obliczana jest na
etapie kompilacji to elementami wyrażenia w dyrektywie #if
moga˛ być jedynie wartości makr oraz stałe.
◮
Ogólna postać dyrektyw #if, #endif:
#if
wyrażenie_stałe
instrukcje
#endif
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - kompilacja warunkowa
◮
Ogólna postać dyrektywy #if z #else i #endif:
#if
wyrażenie_stałe
instrukcje1
#else
instrukcje2
#endif
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - kompilacja warunkowa
◮
Ogólna postać dyrektywy #if z #elif, #else i #endif:
#if
wyrażenie_stałe_1
instrukcje_1
#elif wyrażenie_stałe_2
instrukcje_2
........................
#else
instrukcje_n
#endif
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - kompilacja warunkowa, wordsize.h
/* Determine the wordsize from
the preprocessor defines. */
#if defined __x86_64__
# define __WORDSIZE 64
# define __WORDSIZE_COMPAT32 1
#else
# define __WORDSIZE 32
#endif
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - test zdefiniowania
◮
#defined identyfikator
// 1 : gdy identyfikator był już zdefiniowany
// 0 : gdy identyfikator jest nie zdefiniowany
#if defined identyfikator
/* równoważne */
#ifdef identyfikator
◮
#if ! defined identyfikator
/* równoważne */
#ifndef identyfikator
Programowanie Proceduralne
Dyrektywy preprocesora zdefiniowane w ANSI C
Preprocesor - Polecenia dla kompilatora
◮
◮
# error komunikat_o_błedzie
˛
zleca kompilatorowi
zakończenie kompilowania programu w miejscu jej
wystapienia
˛
(jest stosowana na etapie usuwania błedów).
˛
#pragma umożliwia przekazanie kompilatorowi
dodatkowych instrukcji (zależna od kompilatora):
◮
◮
◮
◮
Wiadomość podczas kompilacji: #pragma message
“WersjaProbna”.
#pragma exit funkcje - określa funkcje majace
˛ zostać
wywoływane tuż przed zakończeniem działania programu.
#pragma startup funkcje - określa funkcje majace
˛ zostać
wywoływane tuż po rozpoczeciu
˛
działania programu;
...