Priorytety operatorów Łączność operatorów Operatory

Transkrypt

Priorytety operatorów Łączność operatorów Operatory
Priorytety operatorów
●
Łączność operatorów
Mówią o tym, jaka jest kolejność aplikowania
operatorów w wyrażeniu/przypisaniu
–
●
wiemy np. z matematyki, że mnożenie jest
„silniejsze” (ma wyższy priorytet) od dodawania:
●
1+2*3 = 7 a nie 9
●
ANSI C stosuje operatory arytmetyczne zgodnie
z intuicją:
–
najpierw operatory unarne, potem binarne – wpierw
multiplikatywne, a następnie addytywne
–
najniższy priorytet mają operatory przypisania
(pomijając operator „przecinka”, ale o nim potem)
–
●
●
Mówi o porządku, w jakim stosowane są operatory
o takim samym priorytecie, sąsiadujące ze sobą
w wyrażeniu/przypisaniu
Od prawej do lewej
–
operatory unarne (jednoargumentowe)
–
operator wyrażenia warunkowego ... ? ... : ...
–
przypisanie oraz jego warianty operatorowe
i = j = k ≡ i = (j = k)
Od lewej do prawej
–
kolejność możemy wymuszać nawiasowaniem
wszystkie pozostałe
i + j + k ≡
(i + j) + k
Szczegóły: Kerninghan i Ritchie „Język ANSI C”
115
116
Operatory - podsumowanie
●
●
●
●
●
●
Sterowanie wykonaniem programu
Operator „modulo” % zwraca resztę z dzielenia
całkowitego
●
Równość w ANSI C oznaczamy przez ==
W kontekście wyrażeń logicznych wartość 0
reprezentuje „fałsz”, a dowolna inna - „prawdę”
Wprowadzenie:
–
programowanie strukturalne
–
podejmowanie decyzji
–
„pętle”
–
rozgałęzienia – instrukcja „goto”
Na sposób obliczania wartości wyrażeń mają wpływ
priorytety operatorów
Operatory unarne, przypisania i warynkowy łączą się
od prawej do lewej; wszystkie pozostałe – od lewej
do prawej
Uwaga na priorytety operatorów bitowych –
najlepiej stosować nawiasowanie!
117
118
Programowanie strukturalne
●
Programy składane z „klocków”
Już w latach 60-tych XX wieku pokazano, że
dowolny algorytm da się zaimplementować stosując
jedynie trzy proste konstrukcje:
–
wykonanie ciągu akcji
podejmowanie decyzji
●
–
Każda z wymienionych konstrukcji może być
przedstawiona w postaci „schematu blokowego”
złożenie sekwencyjne
●
–
●
wybór akcji (bądź jej zaniechania) w zależności od
spełnienia określonego warunku
ciąg akcji
pętle
●
powtarzanie akcji w zależności od spełnienia
określonego warunku
119
120
Programy składane z „klocków”
●
Programy składane z „klocków”
Każda z wymienionych konstrukcji może być
przedstawiona w postaci „schematu blokowego”
●
Każda z wymienionych konstrukcji może być
przedstawiona w postaci „schematu blokowego”
warunek
warunek
niespełniony
●
spełniony
spełniony
niespełniony
podejmowanie decyzji
●
121
ciąg akcji
pętla typu „while-do”
122
Programy składane z „klocków”
●
Podstawowe elementy schematów
Każda z wymienionych konstrukcji może być
przedstawiona w postaci „schematu blokowego”
Terminator. Wskazuje punkt startu oraz punkty zakończenia działania
algorytmu. Terminator ma zawsze tylko jedną krawędź, która łączy go
z resztą diagramu.
Operacja wej.-wyj. - np. wprowadzanie danych lub drukowanie
wyników.
ciąg akcji
Przetwarzanie. Operacja bądź ciąg operacji wykonywanych przez
komputer, takich, jak przypisania, operacje arytmetyczne itp.
Decyzja. Oznacza punkt podejmowania decyzji. „Diament” ma zawsze
dwie krawędzie wychodzące – jedna odpowiada sytuacji, gdy warunek
jest spełniony, a druga – gdy nie jest spełniony.
spełniony
niespełniony
Akcja predefiniowana. Jedno polecenie oznaczające grupę wcześniej
zdefiniowanych instrukcji. Na przykład, „Oblicz n!” oznacza, że komputer
ma obliczyć wartość funkcji silnia dla argumentu n.
warunek
●
Krawędź przepływu. Łączy elementy schematu blokowego i obrazuje
następstwo w ciągu operacji wykonywanych przez algorytm.
pętla typu „do-while”
123
124
Przykład 1: obliczanie silni
Przykład 2: kasa
start
start
suma=0
założenie: n≥0
wczytaj n
wprowadź(cena)
silnia=1
suma=suma+cena
NIE
stop
n > 0
vat=suma * 0.22
kwota=suma+vat
TAK
TAK
Więcej
towarów?
NIE
Dukuj(suma, vat, total)
silnia*=n
n=n­1
stop
125
126
Instrukcja „złożona”
●
Podejmowanie decyzji
ANSI C pozwala łączyć ciągi instrukcji w całość,
tworząc tzw. instrukcje złożone
●
{
instr_1;
instr_2;
...
instr_n;
}
instr_1;
instr_2;
...
instr_n;
Język ANSI C oferuje dwa rodzaje instrukcji
wyboru:
–
if­else
–
switch
●
●
szczególny przypadek instrukcji if­else
pozwala dokonywać wyboru na podstawie wartości
parametru będącego liczbą całkowitą
127
Instrukcja if­else
Instrukcja if­else – przykład
if (wyrażenie)
instrukcja_1
else
instrukcja_2
TAK
instrukcja_1
wyrażenie != 0
128
NIE
instrukcja_2
129
#include <stdio.h>
int main() {
int wiek;
printf("Twój wiek: "); scanf("%d",&wiek);
if (wiek<20)
puts("Dziecko.");
else if (wiek<40) puts("Młodziak!");
else if (wiek<80)
puts("W sile wieku.");
else {
char odp;
printf("Naprawdę? "); scanf("%c",&odp);
if (odp=='T' || odp=='t')
puts("Gratulacje!");
else
puts("Tak myślałem");
}
return 0;
}
130
Instrukcja switch
●
●
Pozwala podejmować decyzje „wielowariantowe”,
w których sprawdzamy, czy wartość pewnego
wyrażenia pasuje do jednej z kilku stałych
całkowitych
„Obsługa” każdego z przypadków może być
zakończona instrukcją break;
–
●
Instrukcja switch – przykład
w przeciwnym wypadku sterowanie przejdzie do
rozważania kolejnego przypadku
Opcjonalny przypadek default pozwala obsłużyć
sytuację, gdy wartość wyrażenia nie pasuje do żadnej
z wymienionych stałych
131
#include <stdio.h>
int main() {
int wiek; char odp;
printf("Twój wiek: "); scanf("%d",&wiek);
switch (wiek/20) {
case 0:
puts("Dziecko."); break;
case 1:
puts("Młodziak!"); break;
case 2:
puts("W sile wieku."); break;
default :
printf("Naprawdę? "); scanf("%c",&odp);
if (odp=='T' || odp=='t')
puts("Gratulacje!");
else
puts("Tak myślałem");
}
return 0;
}
132
Pętle w ANSI C
●
Pętle w ANSI C c.d.
Dostępne są trzy rodzaje pętli
–
typu while-do:
–
while (wyrażenie)
instrukcja
–
pętla for
for (ini; war; iter)
instrukcja
typu do-while
–
do
instrukcja
while (wyrażenie)
równoważna pętli:
ini;
while (war) {
instrukcja
iter;
}
133
134
Pętla while – przykład
Pętla for – przykład
/* Liczymy od 1 do n */
int i=1;
while (i<=n) {
printf("%d ",i);
i += 1;
}
/* Liczymy od 1 do n */
int i;
for (i=1; i<=n; i++) printf("%d ",i);
/* Krótsza wersja */
int i=1;
while (i<=n)
printf("%d ",i++);
135
136
Pętla for – „ciekawsze” przykłady
Rozgałęzienia
int i=255;
for (;;) printf("%d ",i);
●
break
–
i=255;
for (;i;printf("%d ",i=i>>1));
●
i=255;
for (;i>>1;) printf("%d ",i);
continue
–
i=255;
for (;printf("%d ",i=i>>1)­2;);
●
i=255;
for (;(i=i>>1);) printf("%d ",i);
137
powoduje natychmiastowe opuszczenie najbardziej
zagnieżdżonej pętli bądź instrukcji switch, w której
występuje
przechodzi do następnego „obrotu pętli” - np.
w przypadku pętli „while­do” przeskakuje do
testowania warunku
goto
–
pozwala na „skok” do miejsca oznaczonego etykietą
–
umożliwia „wyskakiwanie” z wnętrza nawet
zagnieżdżonych (wielopoziomowych) pętli
138
break i continue – przykład
goto – przykład
/* W tablicy tab szukamy nieparzystej liczby
dwucyfrowej, której suma cyfr wynosi 7
*/
#include <stdio.h>
#define SIZE 5
int main() {
int i,c1,c2, tab[SIZE]={15,37,61,12,99};
/* Zał.: tab zawiera liczby dwucyfrowe
*/
for (i=0; i<SIZE; i++) {
if (tab[i]%2==0)
continue; /* pomijamy liczby parzyste */
c1=tab[i]/10; /* pierwsza cyfra */
c2=tab[i]%10; /* druga cyfra
*/
if (c1+c2 == 7) {
printf("znaleziona: %d ",tab[i]);
break;
}
}
return 0;
}
int i,j, a[MAX1], b[MAX2];
for (i=0; i<MAX1; i++)
for (j=0; j<MAX2; j++)
if (a[i]==b[j])
goto jest;
/* nie znaleziono */
...
return 1;
jest: /* znaleziono a[i]==b[j] */
...
139
goto – cała prawda
●
140
Instrukcje sterujące – podsumowanie
Każdy program wykorzystujący instrukcję goto
można napisać bez niej (na ogół kosztem pewnych
dodatkowych sprawdzeń oraz dodania zmiennych
pomocniczych)
●
●
int i,j, a[MAX1], b[MAX2], jest=0;
for (i=0; i<MAX1 && !jest; i++)
for (j=0; j<MAX2 && !jest; j++)
if (a[i]==b[j])
jest=1;
if (!jest) {
...; return 1;
} else {
...
}
141
●
●
Wszystkie algorytmy można wyrazić stosując: ciągi
prostych instrukcji, instrukcje warunkowe i pętle
Najczęściej stosowanymi w praktyce pętlami są for
oraz while­do
Instrukcje rozgałęziania continue i break
pozwalają „w kontrolowany sposób” opuszczać pętle
Instrukcja goto nie będziemy używać
–
jest „nadmiarowa”
–
jej zastosowanie może znacząco skomplikować
logiczną strukturę kodu
142
Przykład – wersja 1
Przykład – wersja 2
/* sumuj1.c ­­ sumowanie liczb całkowitych */
#include <stdio.h>
/* sumuj2.c ­­ sumowanie liczb całkowitych */
#include <stdio.h>
int main() {
long liczba;
long suma = 0L; // inicjalizacja
int status;
printf("Podaj pierwszą liczbę ");
printf("(q - zakończ): ");
status = scanf("%ld", &liczba);
while (status==1) { suma = suma + liczba;
printf("Podaj kolejną liczbę ");
printf("(q - zakończ): ");
status = scanf("%ld", &liczba);
}
printf("Suma wynosi %ld.\n", suma);
return 0;
}
int main() {
long liczba;
long suma = 0L; // inicjalizacja
printf("Podaj pierwszą liczbę ");
printf("(q - zakończ): ");
while (scanf("%ld",&liczba)) { suma = suma + liczba;
printf("Podaj kolejną liczbę ");
printf("(q - zakończ): ");
}
printf("Suma wynosi %ld.\n", suma);
return 0;
}
143
Przykład – wersja 3
144
Przykład – wersja 4
/* sumuj3.c ­­ sumowanie liczb całkowitych */
#include <stdio.h>
/* sumuj4.c ­­ sumowanie liczb całkowitych */
#include <stdio.h>
int main() {
long n;
long suma = 0L; // inicjalizacja
int status;
do {
printf("Podaj liczbę (q - zakończ): ");
status = scanf("%ld",&n);
suma += (status ? n : 0);
} while (status);
printf("Suma wynosi %ld.\n", suma);
return 0;
}
int main() {
long n;
long suma = 0L; // inicjalizacja
int nxt = 1;
do {
printf("Podaj liczbę (q - zakończ): ");
suma += (scanf("%ld",&n) ? n : (nxt=0));
} while (nxt);
printf("Suma wynosi %ld.\n", suma);
return 0;
}
145
146
Przykład – wersja 5
Operator przecinkowy
●
/* sumuj5.c ­­ sumowanie liczb całkowitych */
#include <stdio.h>
Wartość pary wyrażeń oddzielonych przecinkiem
–
int main() {
long n;
long suma = 0L; // inicjalizacja
do {
printf("Podaj liczbę (q - zakończ): ");
} while (scanf("%ld",&n) ? suma+=n : 0);
printf("Suma wynosi %ld.\n", suma);
return 0;
}
oblicza się od lewej do prawej
–
wartość lewego wyrażenia jest zaniedbywana
–
typem i wartością wyniku jest typ i wartość prawego
wyrażenia
/* uncje.c – taryfa pocztowa */
#include <stdio.h> int main() { const int F_OZ = 37; const int N_OZ = 23; int w, c; printf(" uncje cena\n"); for (w=1, c=F_OZ; w <= 16; w++, c+=N_OZ) printf("%5d $%4.2f\n", w, c/100.0); return 0; } błąd!
147
uncje.c – wynik działania
148
Przykład – wersja 6
uncje cena
1 $0.37
2 $0.60
3 $0.83
4 $1.06
5 $1.29
6 $1.52
7 $1.75
8 $1.98
9 $2.21
10 $2.44
11 $2.67
12 $2.90
13 $3.13
14 $3.36
15 $3.59
16 $3.82 /* sumuj6.c ­­ sumowanie liczb całkowitych */
#include <stdio.h>
int main() {
long n;
long suma = 0L; // inicjalizacja
do {
printf("Podaj liczbę (q - zakończ): ");
} while (scanf("%ld",&n) ? (suma+=n), 1 : 0);
printf("Suma wynosi %ld.\n", suma);
return 0;
}
Operator przecinkowy nie jest dostępny w języku Java!
149
150
C daje wiele możliwości... :)
Złożone typy danych w ANSI C
/* HelloWorld – wersja “profesjonalna” */
#include "stdio.h"
#define e 3
#define g (e/e)
#define h ((g+e)/2)
#define f (e­g­h)
#define j (e*e­g)
#define k (j­h)
#define l(x) tab2[x]/h
#define m(n,a) ((n&(a))==(a))
●
long tab1[]={ 989L,5L,26L,0L,88319L,123L,0L,9367L };
int tab2[]={ 4,6,10,14,22,26,34,38,46,58,62,74,82,86 };
main(m1,s) char *s; {
int a,b,c,d,o[k],n=(int)s;
if(m1==1){ char b[2*j+f­g]; main(l(h+e)+h+e,b); printf(b); }
else switch(m1­=h){
case f:
a=(b=(c=(d=g)<<g)<<g)<<g;
return(m(n,a|c)|m(n,b)|m(n,a|d)|m(n,c|d));
case h:
for(a=f;a<j;++a)if(tab1[a]&&!(tab1[a]%((long)l(n))))return(a);
case g:
if(n<h)return(g);
if(n<j){n­=g;c='D';o[f]=h;o[g]=f;}
else{c='\r'­'\b';n­=j­g;o[f]=o[g]=g;}
if((b=n)>=e)for(b=g<<g;b<n;++b)o[b]=o[b­h]+o[b­g]+c;
return(o[b­g]%n+k­h);
default:
if(m1­=e) main(m1­g+e+h,s+g); else *(s+g)=f;
for(*s=a=f;a<e;) *s=(*s<<e)|main(h+a++,(char *)m1);
} return(0);
}
●
●
●
●
●
Przechowuje ciąg elementów tego samego typu
Rozmiar tablicy jest stały – określany w momencie
deklaracji
do określania rozmiaru nie można stosować stałych
(zadeklarowanych z użyciem const)
–
na ogół stosuje się „stałe” zdefiniowane za pomocą
preprocesora (np. #define stala 20)
przechowują ciągi elementów danego typu
–
łańcuchy znaków (napisy), to szczególny przypadek
typu tablicowego – tablica znaków
Struktury
–
pozwalają grupować wartości różnych typów
–
taka „grupa wartości” stanowi jedną całość i może
być np. wykorzystana w instrukcji przypisania
152
Przykład
Jeden z podstawowych typów danych, spotykany
w większości języków programowania
–
–
151
Tablice w ANSI C
●
Tablice
Bezpośredni dostęp do elementów tablicy za pomocą
operatora indeksowania ([])
Indeksowanie za pomocą liczb naturalnych – od 0 do
n­1, gdzie „n” to zadeklarowany rozmiar tablicy
153
/* wczytuje liczby do tablicy (do napotkania 0)
i drukuje je w odwrotnej kolejności */
#include <stdio.h>
#define SIZE 50
int main() {
int i, n, liczba;
int liczby[SIZE];
for (n = 0; n < SIZE; ++n) {
printf("Podaj liczbę (0 - zakończ): ");
scanf("%d", &liczba);
if (liczba==0) break;
liczby[n] = liczba;
}
for (i = n­1; i >= 0; ­­i) printf("%d ", liczby[i]);
return 0;
}
154
Inicjalizacja tablicy
●
Inicjalizacja listą wartości
int a[] = {10,20,30,40,50};
●
Deklaracja rozmiaru jest opcjonalna
–
zadeklarowany rozmiar musi być nie mniejszy niż
długość podanej listy wartości
●
●
–
niepodane wartości są inicjalizowane zerami
jeśli lista wartości jest dłuższa niż rozmiar, wówczas
kompilator zasygnalizuje błąd
jeśli rozmiar nie został zadeklarowany, to tablica
otrzymuje rozmiar równy długości podanej
w inicjalizacji listy wartości
155

Podobne dokumenty