Wyklad 03


KURS C/C++
WYKAAD 3
Instrukcja break
Do tej grupy instrukcji należą:
break;
continue;
return wyrażenie;
goto etykieta;
Instrukcja break
Służy do przerwania działania pętli for, while, do...while oraz instrukcji switch. Instrukcja ta,
przenosi sterowanie do instrukcji bezpośrednio występującej po pętli lub po instrukcji switch. Jeśli
mamy do czynienia z pętlami zagnieżdżonymi break przerywa tylko tą petlę lub instrukcję switch w
której zostało użyte. Instrukcja break przerywa pętlę zanim wyrażenie testujące pętlę osiągnie
wartość 0.
Program 1 Program 2
#include #include
#include //random(), #include
#include #include
void main (){ void main(){
int licz, i, los;
int licz, i, los;
randomize();
los = 7;
for (i=1; i<10; i++) {
randomize();
licz=0;
licz=0;
do {
do {
licz++;
licz++;
if (random (30) = = i) break;
if (random (30) = = los) break;
} while (1);
} while (1);
cout<printf ("%d wylosowano za %d \
<<" razem";
//kontynu
razem3 ,los, licz);
}
}
}
Instrukcja continue
Instrukcja ta może być używana tylko w pętli for, while, do...while. Powoduje przeniesienie
sterowania na koniec pętli.
Program 1.
#include
#include
void main (){
int i;
float iloczyn;
clrscr ();
iloczyn =1;
for (i=1; i<30; i++ {
if ( (i % 3) = = 1) continue; //skok na koniec pętli,
iloczyn = iloczyn * i;
//koniec pętli: continue przenosi sterowanie w to miejsce.
}
}
Instrukcja return
Return pozwala funkcji na natychmiastowe przeniesienie sterowania do miejsca wywołania
funkcji i przekazania wartości stojącej po słowie return (w przypadku funkcji main do systemu
operacyjnego).
int main (){
..............
return 1;
}
Instrukcja goto
Instrukcja ta, wykonuje bezwarunkowe przeniesienie sterowania do miejsca gdzie występuje
dana etykieta. Etykieta musi być umieszczona w tej samej funkcji. Poniższy program ilustruje
użycie goto do przerwania zagnieżdżonej pętli:
Program 4.
#include
#include
void main (){
float w, i;
clrscr(); i=0;
i=0; do {
while (1) { i++;
i++; w=1/(i+1);
w=1/(i+1); } while (w>0.001);
if (w<0.001) goto wyraz; wyraz: printf (3 w=%f3 , w);
}
printf (3 \nkoniec petli\n3 );
wyraz: printf (3 w=%f3 , w);
getch();
}
Modyfikator const (stałe nazwane)
Obiekt, którego wartość nie ulega zmianie, nazywa się obiektem stałym. float pi = 3.14;
Jeżeli chcemy mieć pewność, że wartość zmiennej pi nie zostanie przypadkowo zmieniona,
poprzedzamy deklarację modyfikatorem const. Jest to deklaracja obiektu stałego.
const float pi = 3.14;
Inicjacjalizacja obiektu wartością musi sie odbyć w miejscu jego deklaracji. Potem nie jest to
możliwe.
Deklaracja
const float pi;
jest błędna, ponieważ deklarujemy obiekt stały więc jego wartość musi być inicjalizowana.
Poprawna:
const float pi = 3.14;
Grupa poniższych linii jest błędna, ponieważ s tała nie może uzyskać wartości w instrukcji
przypisania.
pi = 2.00; //błąd
pi = 3.14; //mimo, że próbujemy przypisać obiektowi const taką samą wartość będzie
sygnalizowany błąd.
Dyrektywa preprocesora.
#define pi 3.14
#define ESC 27
if (znak = = ESC) {...};
do {
.....
}
while (znak != ESC);
Operatory języka C/C++
a = i++ + j;
x*=(a!=0)?a:b++;
Operatory należą do jednej z dwu grup:
- operatory jednoargumentowe (unarne) wiÄ…zane z jednym argumentem.
- operatory dwuargumentowe (binarne) wiÄ…zane z dwoma argumentami.
Operatory arytmetyczne
- operatory : + - * /
Należą do grupy operatorów binarnych (ponieważ operujÄ… na dwóch obiektach żÿ argumentach).
- operator % czyli modulo
Jest operatorem binarnym. W wyniki działania tego operatora otrzymujemy resztę z dzielenia
argumentów stojących po obu stronach operatora:
45 % 6 -> 3
Argumenty tego operatora muszą być typu całkowitego. Argumenty tego operatora muszą być
typu całkowitego. Jeśli argumenty operatora są nieujemne to , to reszta z dzielenia jest nieujemna w
przeciwnym razie znak reszty zależy od implementacji.
Dla Borland 3.1, znak wyniku op1 % op2 jest zgodny ze znakiem oprandu op1.
z = - 45 % 6; z = - 45 % -6; z = 45 % -6;
z = -3 z = -3 z = 3
Priorytet operatorów *, /, % jest wyższy niż operatorów +, -.
- operatory jednoargumentowe + , -
Operator - zmienia wartość danego wyrażenia na przeciwną :
-a - (2*a + b)
- operatory inkrementacji i dekrementacji
++; --;
Realizują operacje zwiększania i zmniejszania o jeden.
Operatory dekrementacji i inkrementacji mogą mieć dwie formy:
- przedrostkowÄ… ( prefix): ++i; --i;
- przyrostkowÄ… (postfix): i++; i--;
W obu przypadkach wynikiem jest zmiana wartości i, ale wyrażenie ++i zwiększa i przed
użyciem jej wartości, natomiast wyrażenie i++ zwiększa zmienną i dopiero po użyciu jej
poprzedniej wartości. Jest to istotne w kontekście, w którym ważna jest wartość zmiennej i, a nie
tylko jej zmiana np:
i = 10;
x = i++;
cout<<" x = "<daje w rezultacie x = 10, ale
i = 10;
x = ++i;
cout<<" x = "<daje w rezultacie x = 11.
int m=3, n=2, r;
r = (m++) + (--n); //r=3+1=5
m = 4 n = 1
Ponieważ są to operatory unarne (jednoargumentowe) to wyrażenie :
(i + j)++ jest błędne;
W przypadku, gdy chodzi tylko o sam efekt zwiększania o jeden, operatory post i prefiks-owe są
równoważne.
for (i=11; i<34; i++) {...}
for (i=11; i<34; ++i) {...}
int i=1;
s[i] = i++; porządek wartościowania jest niezdefiniowany, może być wartościowane jako
s[1] = 1 lub jako s[2] = 1.
Operatory przypisania
operatory: = += -= *= /= %=
float b = 15; float w,a = 5.2;
w=a+b;
Jeżeli, argumenty nie mają takiego samego typu, to o ile jest to możliwe wykonana zostaje
niejawna konwersja typów.
int i=1.2; float b= 5/2; float b= 5.0/2;
Jeśli oba argumenty sa typu arytmetycznego to przed wykonaniem przypisania prawy argument
jest przekształcany do typu lewego argumentu.
i = i + 2; bardziej zwięzły zapis: i += 2;
Uwaga!!!
x*= y + 1;
jest odpowiednikiem wyrażenia:
x = x * (y+1); NIE : x = x * y + 1;
Działa tu bowiem zasada:
wyr1 operator= wyr2 to samo co wyr1 = (wyr1) operator (wyr2)
Operatory logiczne
- operatory relacji
SÄ… to operatory: > >= < <=
W wyniku działania tych operatorów otrzymujemy odpowiedz: prawda (true 1) lub fałsz (false
0) Priorytet tych operatorów jest taki sam .
- operatory przyrównania
SÄ… to operatory = = !=.
Ich priorytet jest niższy niż priorytet operatorów relacji
Program 1
#include
void main() {
int x = 10, x1 = 10;
if (x = 3) //bÅ‚Ä…d żÿ przypisanie, zamiast porównanie. Kompilator generuje ostrzeżenie
x= 2*x1;
else
x= 2 żÿ x1;
cout<<"x="<}
- operatory sumy i iloczynu logicznego
SÄ… to operatory:
| | - realizujÄ…cy sumÄ™ logicznÄ… (LUB - alternatywa)
&& - realizujÄ…cy iloczyn logiczny (I - koniunkcja)
Argumenty mogą być typu arytmetycznego lub wskaznikowego. Wynik jest typu int.
Przykład 1
#include
void main(){
int ch;
ch = getche();
if (((ch >= 'a') && (ch <= 'z')) | | ((ch >= 'A') && (ch <= 'Z')))
cout<<"wprowadzony znak jest literÄ…";
else if((ch >= '0') && (ch <= '9'))
cout<<"wprowadzony znak jest cyfrÄ…";
else
cout<<"Wprowadzony znak nie jest cyfrÄ… i nie jest literÄ…";
}
Wezmy np. fragment kodu:
if ((x1 = = 0) && (x1 = = 15) && (z>10))
Operatory && i | | gwarantują wartościowanie argumentów od lewej do prawej.
Dla operatora && drugi argument nie będzie obliczony, jeśli pierwszy ma wartość zero.
Dla operatora | | drugi argument nie będzie obliczony, jeśli pierwszy ma wartość niezerową.
int i = -6, d = 4;
if ((i>0) && (d++)) {
...............
}
W instrukcji tej nie tylko wykonywana jest operacja logiczna , ale także chcemy zwiększyć
wartość zmiennej d. Jeżeli, wyrażenie i>0 nie będzie prawdziwe to nie dojdzie do zwiększenia d,
musimy to rozważyć taką możliwość konstruując takie wyrażenia.
Priorytet operatora && jest większy niż operatora ||, ale oba są niższe niż operatorów
przyrównania i relacji, więc w wyrażeniu:
i < gr - 1 && (c = getchar()) != '\n' | | c!= EOF
nie potrzeba dodatkowych nawiasów.
Ponieważ jednak priorytet operatora != jest wyższy niż przypisania, więc w zwrocie (c=getchar()) !
= '\n' potrzebne są nawiasy. Najpierw bowiem ma zostać przypisana wartość zmiennej c, a potem
dopiero przyrównana do '\n'.
(i < (gr żÿ 1)) && ((c = getchar()) != '\n' ) | | (c!= EOF)
- operator negacji !
Operator jest jednoargumentowy i stoi zawsze po lewej stronie operandu:
!n
Jeśli n = 0, to wartością wyrażenia jest PRAWDA.
Jeśli n różne od 0, to wartością wyrażenia jest FAASZ.
Instrukcja: if (!n) jest równoważna instrukcji: if (n = = 0)
Przykład 1
int x;
x= !(-12); -> x=0
x= !(120); -> x=0
x= !(0); -> x=1
int i = 0;
if (!i) cout<<"Wartość i jest zerowa";
while (i-2)
while ((2*x) && y)
while ((2*x) && (!y))
Operator sizeof ()
Operator: sizeof(), podaje rozmiary:
a) typów zmiennych sizeof (nazwa_typu)
b) obiektów sizeof(nazwa_obiektu)
Przykład 9
#include
void main(){
int i;
cout <<"rozmiar typu integer w bajtach " << sizeof(int);
cout<<" \n rozmiar zmiennej i w bajtach " << sizeof(i);
}
Operator przecinkowy
Kilka wyrażeń oddzielonych przecinkiem wartościuje się od lewej do prawej, przy czym wartość
lewego wyrażenia przepada.
i = 5;
b = (a = i, a=a+1);
Jeśli kilka wyrażeń stoi obok siebie i są oddzielone przecinkami, to wartością zmiennej b jest
wartość prawego argumentu, czyli
b = 6 a = 6
Operator przecinkowy może wystąpić wyłącznie w nawiasie.
Jeżeli pominiemy nawiasy to:
b = a = i, a=a+1;
b = 5; a=6;
int x, a, c;
a=5; c=7;
c=(x=a, a=c, x);
czyli: x=5, a=7, c=5
Wyrażenie jest wartościowane od lewej do prawej.
Operatory bitowe
Operatory bitowe:
<< - przesunięcie w lewo
>> - przesunięcie w prawo
& - bitowy iloczyn logiczny
| - bitowa suma logiczna
^ - bitowa różnica symetryczna (bitowe exclusive OR)
~ - bitowa negacja
- operator przesunięcia w lewo <<
Jest to operator unarny, operujący na argumentach całkowitych: zmienna << ile miejsc
Służy do przesuwania bitów argumentu stojącego po lewej stronie operatora o liczbę pozycji
określoną przez drugi argument (jego wartość musi być dodatnia). Zwolnione bity zostają
uzupełnione zerami:
int x = 0x0010;
int wynik;
wynik = x << 2;
Powyższy fragment programu przesunie bity liczby x o 2 miejsca w lewo:
x = 0000 0000 0001 0000 //16 0x0010
wynik = 0000 0000 0100 0000 //64 0x0040
można:
x = x << 2.
Operacja ta ( x<<2) jest równoważna pomnożeniu zmiennej przez cztery:
x 0x0001 = 1
x<<2 0x0100 = 4
- operator przesunięcia w prawo >>
zmienna >> ile miejsc
Działa na operandach całkowitych. Przesuwa bity operandu stojącego polewej stronie operatora
o ilość bitów wskazaną przez operand prawy.
Bity z prawej strony sÄ… gubione.
Jeśli operator pracuje na danej unsigned czyli bez znaku, to bity z lewego brzegu są
uzupełnione zerami , jeśli jest to liczba ze znakiem, to bity z lewego brzegu są uzupełnione zerami
lub jedynkami zależnie od implementacji, w pakiecie Borland 3.3 najbardziej znaczące bity
uzupełniane są bitem znaku.
unsigned int x = 0x0ff0;
unsigned int wynik;
wynik = x >>2;
x 0000 1111 1111 0000
wynik 0000 0011 1111 1100
signed int f = 0xff00; //-256
signed int wynik;
wynik = x>>2; //-64
x 1111 1111 0000 0000
wynik 0011 1111 1100 0000 //uzupełnienie zerami
wynik1 1111 1111 1100 0000 //uzupełnienie bitem znaku
Implementacja Borland C++ daje wynik1.
- operatory negacji , iloczynu, sumy, różnicy symetrycznej
Operatory te działają na operandach całkowitych.
b1 b2 ~ b1 (not) b1 & b2 (and) b1 | b2 (or) b1 ^ b2 (xor)
0 0 1 0 0 0
0 1 1 0 1 1
1 0 0 0 1 1
1 1 0 1 1 0
int x1 = 0x0f0f;
int x2 = 0x0ff0;
x1 0000 1111 0000 1111
x2 0000 1111 1111 0000
x1 & x2 0000 1111 0000 0000 zasłania pewną grupę bitów
x1 | x2 0000 1111 1111 1111 służy do ustawiania bitów
x1 ^ x2 0000 0000 1111 1111 tam gdzie bity operandów są
takie same ustawia 0, a gdzie różne 1
~ x1 1111 0000 1111 0000 zamienia bit 1 na 0 i odwrotnie.
Priorytet i łączność operatorów
Priorytety operatorów (od najwyższego) podaje zestawienie:
15. () [] -> L
14. ! ~ ++ -- + - * & sizeof P // adres i wskaznik
13. * / % L
12. + - L
11. << >> L
10. < <= > >= L
9. == != L
8. & L
7. ^ L
6. | L
5. && L
4. || L
3. ? : P
2. = += -= *= /= %= ^= |= <<= >>= P
1. , L
Litery L i P określają w jaki sposób grupowane jest wykonywanie wyrażenia i tak np:
dla wyrażenia z operatorem + (L)
a + b + c + d + e
lewostronna łączność oznacza:
((((a + b) + c) + d) + e)
natomiast dla wyrażenia z operatorem = (P)
a = b = c = d = e
oznacza:
(a = ( b = (c = (d = e))))
Arytmetyczne wyrażenie warunkowe
Instrukcja :
if( a > b) m = 10;
else m = -1;
może być zastąpiona trzyargumentowym operatorem " ? : " :
max = (a>b) ? 10 : -1;
Nawiasy w wyrażeniu warunkowym nie są konieczne, ze względu na bardzo niski priorytet
operatora ?
Ogólnie mozna wyrażenie warunkowe zapisać:
wyr1 ? wyr2 : wyr3;
wyr2 i wyr3 powinny mieć taki sam typ, jesli nie to wykonywane jest przekształcenie typów.
max = a > b ? a : b;
Wyrażenia warunkowe często wpływaja na zwięzłość programu np.:
printf("Masz %d częś%s.\n", n, n = =1 ? "ć" : "ci");
lub:
for(i = 0; i < n; i++)
printf("%6d%c", i, ((i%10 = = 0) | | (i = = n)) ? '\n' : ' ');
Znak nowego wiersza w powyższym przykładzie wypisywany jest po każdym dziesiątym
elemencie tablicy, natomiast po innych wstawiany jest znak spacji.
Przekształcanie typów
Jeżeli argumentami operatora są obiekty różnych typów, to są one przekształcane do jednego
wspólnego typu według kilku reguł. Ogólna zasada mówi że: automatycznie wykonuje się tylko
takie przekształcenia, w których argument "ciasniejszy jest zamieniany na obszerniejszy bez utraty
informacji: np zamiana całkowitej na zmiennopozycyjną.
Niedozwolone jest indeksowanie tablic zmiennymi float ( nie odbywa siÄ™ konwersja).
Wyrażenia w których może wystąpić utrata informacji, jak np. przypisanie wartości o dłuższym
typie całkowitym zmiennej krótszego typu, czy po zmianie zmiennopozycyjnej na całkowitą, mogą
powodowac wypisanie ostrzeżenia, ale nie jest niedozwolone.
Obiekty char są krótkimi liczbami całkowitymi, zapewniającymi znaczną elastyczność przy
różnego rodzaju przekształceniach.
Ogólnie konwersja wykonywana jest w następujący sposób (zasady powinny być stosowane wg
kolejności wymieniania):
- jeśli jeden argument jest long double drugi przekształcany jest do long double.
- jeśli nie to jeśli jeden argument jest double drugi przekształcany jest do double.
- jeśli nie to jeśli jeden argument jest float drugi przekształcany jest do float.
- jeśli nie to jeśli jeden argument jest unsigned long drugi przekształcany jest do unsigned long
- jeśli nie to jeśli jeden argument jest signed long drugi przekształcany jest do signed long
- jeśli nie to jeśli jeden argument jest unsigned int drugi przekształcany jest do unsigned int
- w przeciwnym przypadku oba operandy sÄ… typu int
Sposoby wykonywania konwersji
- char na int
powielanie bitu znaku dla signed char lub wypełnienie zerami dla unsigned char
-short na int
ta sama wartość
- unsigned short na unsigned int
ta sama wartość
-konwersja dłuższego typu całkowitego do mniejszego
Odrzucenie bardziej znaczących bitów i w razie ich ustawienia utrata informacji
- konwersja między typami calkowitymi o tych samych dlugościach
bezpośrednie skopiowanie wartości jednej zmiennej do drugiej. Warto wiedzieć, że można
uzyskać ciekawe wyniki np.:
int -1000 po konwersji do unsigned int 64536
( bit znaku traktowany jako bit o wadze 2 do 15)
- konwersja rzeczywiste na całkowite
odrzucenie części ułamkowej liczby rzeczywistej
- konwersja całkowite na rzeczywiste
nadanie odpowiedniej liczbie rzeczywistej wartości liczby całkowitej
- konwersje między typami rzeczywistymi o różnych rozmiarach
zaokrąglenie do najbliższej wartości docelowego typu.
Oprócz automatycznego przekształcania typów, w dowolnym wyrażeniu można jawnie wymusić
przekształcenie typów za pomocą:
- jednoargumentowego operatora rzutowania (casting)
Operator ten może mieć dwie formy:
(nazwa_typu) zmienna //forma języka C/C++ - notacja rzutowa
nazwa_typu (zmienna) //forma C++ - notacja funkcyjna
Notacja funkcyjna stosowana tylko do typów które mają prostą nazwę.
int i; float f;
i = (int) f; f = (float) i;
i = int (f); f = float (i);


Wyszukiwarka

Podobne podstrony:
wyklad 03
Lipidy cz I Wykład z 7 03 2007
Wykład 3 5 03 2013
Drogi i ulice wyklad 03
Wykład 03 The?st SDH Project
TI Wykład 03
2 wyklad 03 04 2008
wyklad 03 (2)
fizjologia zwierzat wyklad 03
Wykład 03 Modele wiązek
Wykład 03 (część 08) twierdzenie o wzajemności prac i z niego wynikające
wyklad 03
1 Wyklad 6 03 2008
Wykład 03 Przepływy płynów cd
Wykład 03 Metoda Różnic Skończonych 1

więcej podobnych podstron