Wykład 2 Wejście i wyjście - funkcje scanf i printf Operator przypisania prostego Operatory arytmetyczne Kolejność wykonywania operacji Operatory przypisania arytmetycznego Operatory inkrementacji/dekrementacji Operatory relacji Operatory logiczne Operatory bitowe Podstawowe pojęcia związane z operatorami Operator warunkowy Priorytet operatorów 2017-02-03 W2 1
Funkcja standardowa printf - jej parametrami są: - łańcuch znaków zawierający między innymi kody formatujące, - wyrażenia, których wartości maja być wyprowadzone w sposób określony odpowiednimi kodami formatującymi. Zestawienie kodów formatujących funkcji printf: %c Pojedynczy znak %s Łańcuch znaków %d Dziesiętna liczba całkowita ze znakiem %f Liczba rzeczywista (notacja dziesiętna, tzw. stałoprzecinkowa)) %e Liczba rzeczywista (notacja wykładnicza) %g Liczba rzeczywista (krótszy z formatów %f lub %e) %u Liczba dziesiętna całkowita bez znaku %x Liczba całkowita szesnastkowa bez znaku %o Liczba całkowita ósemkowa bez znaku %p Wartość adresu (zmiennej wskaźnikowej) l (litera małe el) Przedrostek stosowany w kodach %d, %u, %x i %o dla oznaczenia długiej liczby całkowitej (n.p. %ld) 2017-02-03 W2 2
Następujący prosty program wyświetla wartości kilku stałych rzeczywistych: /* Przykład 2.1 */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { system("cls"); printf("\n"); printf("%f %f %f\n", 19.1, -2.501, 231.3); printf("%f %f %f\n", 1357.0, 712.565, -2285.3); system("pause"); system("cls"); return 0; } A to wyniki: 2017-02-03 W2 3
Wyniki maja postać "nieuporządkowaną", są mało czytelne. Wszystkie liczby zostały wyświetlone z 6 cyframi części ułamkowej, podczas gdy wyprowadzane wartości mają tylko co najwyżej 3 cyfry znaczące po kropce dziesiętnej. Dzieje się tak, ponieważ domyślnym formatem dziesiętnej liczby rzeczywistej wyprowadzanej wg kodów konwersji %f, %e, %g jest 6 cyfr po kropce dziesiętnej (w postaci wykładniczej 6 cyfr po kropce dziesiętnej mantysy). Zmianę tej domyślnej, nie zawsze pożądanej dokładności uzyskano w następującym programie: /* Przykład 2.2*/ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { system("cls"); printf("\n"); printf("%.1f %.1f %.1f\n", 19.1, -2.501, 231.3); printf("%.1f %.1f %.1f\n", 1357.0, 712.565, -2285.3); system("pause"); system("cls"); return 0; } 2017-02-03 W2 4
Wyniki mają teraz postać: Wszystkie liczby zostały wyprowadzone z 1 cyfrą w części ułamkowej. Liczby -2.501 oraz 712.565 zostały zaokrąglone. Taki sposób wyświetlenia wyników określa sekwencja.1 pomiędzy znakiem % a literą f w kodzie konwersji. Ogólnie, kombinacja %.nf w kodzie formatującym oznacza wypisanie liczby rzeczywistej z n cyframi po kropce dziesiętnej. 2017-02-03 W2 5
Jeszcze inny sposób wyprowadzenia wyników zastosowano w następującym programie: /* Przykład 2.3 */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { system("cls"); printf("\n"); printf("%8.1f %8.1f %8.1f\n", 19.1, -2.501, 231.3); printf("%8.1f %8.1f %8.1f\n", 1357.0, 712.565, -2285.3); system("pause"); system("cls"); return 0; } 2017-02-03 W2 6
I wyniki jakie wyświetla na ekranie: Kod formatujący: %m.nf oznacza polecenie wyświetlenia wartości odpowiedniego wyrażenia w postaci liczby rzeczywistej, w zapisie stałoprzecinkowym w polu o całkowitej szerokości m znaków, z n cyframi części ułamkowej. Do szerokości pola liczony jest znak minus oraz kropka dziesiętna. Jeżeli chcemy uzyskać na wyjściu wartości wyrażeń wyrównane do lewej krawędzi pola to powinniśmy w kodzie formatującym użyć znaku minus bezpośrednio po symbolu %. 2017-02-03 W2 7
/* Przykład 2.4 */ #include <cstdio> #include <ctdlib> using namespace std; // int main(void) { system("cls"); printf("\n"); printf("%-8.1f %-8.1f %-8.1f\n", 19.1, -2.501, 231.3); printf("%-8.1f %-8.1f %-8.1f\n", 1357.0, 712.565, -2285.3); system("pause"); system("cls"); return 0; } 2017-02-03 W2 8
W celu wprowadzenia do programu danych z zewnątrz (najczęściej z klawiatury) można użyć funkcji standardowej scanf. Podobnie jak funkcja printf obsługuje ona różne typy danych. Przykładem użycia funkcji scanf jest pokazany dalej program, który pyta o użytkownika o wiek w latach. Po wpisaniu tej wartości na klawiaturze, czyta ją (dokładniej odczytuje z bufora klawiatury kody kolejno naciskanych klawiszy), oblicza odpowiadającą wprowadzonym latom liczbę dni (dla uproszczenia nie uwzględnia lat przestępnych) i wyświetla wynik. 2017-02-03 W2 9
#include <cstdio> #include <cstdlib> using namespace std; // int main(void) { float lata, dni; system("cls"); printf("\npodaj swoj wiek w latach: "); scanf("%f", &lata); dni = 365 * lata; printf("masz %.1f dni.\n", dni); system("pause"); system("cls"); return 0; } 2017-02-03 W2 10
Prototyp funkcji scanf znajduje się w pliku nagłówkowym cstdio (można używać "starej" nazwy stdio.h). Funkcja scanf wymaga podania co najmniej dwóch argumentów. Pierwszym z nich jest zawsze kod formatujący, drugi parametr i następne to adresy zmiennych, których wartości zostaną odczytane z klawiatury, przekształcone do postaci określonej odpowiednimi kodami formatującymi i przypisane zmiennym. Funkcja wymaga podania adresów zmiennych, a nie ich nazw. Symbol & jest tzw. operatorem wyłuskania adresu lub krócej operatorem adresowania. Sekwencja &nazwa-zmiennej reprezentuje wartość adresu (lokalizacji w pamięci komputera) zmiennej o podanej nazwie. Drugi i następne parametry funkcji scanf muszą być adresami, a nie nazwami zmiennych. Po powrocie z funkcji scanf do funkcji wywołującej zmienne, których adresy wystąpiły w wywołaniu scanf mają wartości równe danym wprowadzonym przez użytkownika z klawiatury. W podanym wyżej przykładzie wprowadzamy wartość zmiennej lata. Zadeklarowano ją jako float. W wywołaniu funkcji scanf występuje łańcuch znaków - kod formatujący %f właściwy dla danych typu float oraz, jako drugi parametr - adres zmiennej lata (zapis &lata). 2017-02-03 W2 11
Kody formatujące w funkcji scanf %c pojedynczy znak %s łańcuch znaków %d liczba całkowita dziesiętna ze znakiem (dodatnia lub ujemna) %f lub %e liczba rzeczywista dziesiętna w notacji stało- lub zmiennoprzecinkowej %u liczba całkowita dziesiętna bez znaku %x liczba całkowita szesnastkowa bez znaku %o liczba całkowita ósemkowa bez znaku l L małe el - przedrostek przed d, o, u, x dla określenia formatu liczby całkowitej długiej (long int) Przedrostek przed f lub e dla oznaczenia formatu długiej liczby rzeczywistej o podwójnej precyzji (long double) 2017-02-03 W2 12
Różnicę pomiędzy wartością zmiennej a jej adresem można zobaczyć w następującym przykładzie programu: /* Przykład 2.6 */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { int n; float x; double y; n=2; x=-90.9910771; y=1.2345e-11; printf("\nwartosc n = %d, adres n = %p", n, &n); printf("\nwartosc x = %f, adres x = %p", x, &x); printf("\nwartosc y = %e, adres y = %p\n", y, &y); system("pause"); return 0; } 2017-02-03 W2 13
Operatory danych. są słowami kluczowymi lub symbolami, które powodują wykonanie operacji na Operator przypisania prostego (=): zmienna = wyrażenie oblicza wartość wyrażenia i przypisuje zmiennej. W języku C/C++ konstrukcja taka jest sama w sobie wyrażeniem. Ponieważ każde wyrażenie ma wartość to przypisanie proste jest wyrażeniem o określonej wartości. Po wykonaniu instrukcji x = y = z = 15.5; zmienne x, y, z będą mieć identyczną wartość 15.5 Po wykonaniu instrukcji t = (r = 12) -3; zmienna r ma wartość 12, a zmienna t ma wartość 12-3 czyli 9. Operator przypisania wiąże swoje argumenty (operandy) w kolejności od strony prawej do lewej. 2017-02-03 W2 14
Przykład programu ilustrującego działanie operatora przypisania prostego: /* Przykład 2.7 */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { float x, y, z; int t, r; x=y=z=15.5; t=(r=12)-3; printf("\nwyniki dzialan: x = %f y = %f z = %f\n", x, y, z); printf(" r = %d t = %d\n", r, t); system("pause"); return 0; } 2017-02-03 W2 15
Operatory arytmetyczne: unarne: +argument (jednoargumentowe) -argument zmiana znaku argumentu binarne: argument1 + argument2 dodawanie (dwuargumentowe) argument1 - argument2 odejmowanie argument1 * argument2 mnożenie argument1 / argument2 dzielenie argument1%argument2 reszta z dzielenia Przykład zastosowania niektórych operatorów arytmetycznych (program konwersji temperatury w stopniach Farenheit'a na temperaturę w stopniach Celsjusza: 2017-02-03 W2 16
/* Przykład 2.8 */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { float ftemp, ctemp; printf("\npodaj temperature w stopniach Farenheit\'a: "); scanf("%f", &ftemp); ctemp = (ftemp-32) * 5 / 9; printf("temperatura w stopniach Celsjusza %-6.1f\n", ctemp); system("pause"); return 0; } 2017-02-03 W2 17
Kolejność w jakiej wykonywane są operacje wpływa w istotny sposób na wartość wyrażenia. Dla operatorów arytmetycznych kolejność ta (priorytet) jest następująca: 1. Obliczenie czynników i składników ujętych w nawiasy 2. Wykonanie jednoargumentowych operacji + i 3. Wykonanie operacji mnożenia (*), dzielenia (/) i obliczania reszty z dzielenia (%) 4. Wykonanie dwuargumentowych operacji dodawania (+) i odejmowania (-). Przykład wyrażenia arytmetycznego jak zapisać w języku C/C++ wyrażenie:? a d f c e h g j 2017-02-03 W2 18
Chyba tak: a + c/(d + e/(f + g/(h +j))) /* Przyklad 2.10 - Ilustracja dzialania operatora reszty z dzielenia */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { int a=17; int b=-3; int c=-55; int d=6; printf("\nreszta z dzielenia %4d przez %4d jest rowna %4d", a, b, a % b); printf("\nreszta z dzielenia %4d przez %4d jest rowna %4d", c, d, c % d); printf("\nreszta z dzielenia %4d przez %4d jest rowna %4d", a, d, a % d); printf("\nreszta z dzielenia %4d przez %4d jest rowna %4d\n", c, b, c % b); system("pause"); return 0; } 2017-02-03 W2 19
Wyrażenia można użyć prawie wszędzie tam, gdzie dopuszczalne jest użycie zmiennej. /*Przyklad 2.9 Uzycie wyrazenia jako parametru funkcji standardowej printf*/ #include <cstdio> #include <cstdlib> using namespace std; int main(void) { int numer=3; printf("liczba zwiekszona o 9 jest rowna:%4d\n", numer+9); system("pause"); return0; } Liczba zwiekszona o 9 jest rowna: 12 2017-02-03 W2 20
/* Przyklad 2.10 - Ilustracja dzialania operatora reszty z dzielenia */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { int a=17; int b=-3; int c=-55; int d=6; printf("\nreszta z dzielenia %4d przez %4d jest rowna %4d", a, b, a % b); printf("\nreszta z dzielenia %4d przez %4d jest rowna %4d", c, d, c % d); printf("\nreszta z dzielenia %4d przez %4d jest rowna %4d", a, d, a % d); printf("\nreszta z dzielenia %4d przez %4d jest rowna %4d\n", c, b, c % b); system("pause"); return 0; } 2017-02-03 W2 21
Bardzo często w programach występują instrukcje, których zadaniem jest np. zwiększenie aktualnej wartości zmiennej o określoną liczbę i przypisanie tak obliczonej wartości tej samej zmiennej. Klasyczny sposób zapisu takiej instrukcji to: x = x + a; W języku C/C++ taką instrukcję można zapisać w zwięzłej postaci jako: x += a; Użyto tutaj symbolu += arytmetycznego operatora przypisania sumy. 2017-02-03 W2 22
W podobny sposób można uprościć zapis innych wyrażeń arytmetycznych obliczanych wg takiego samego schematu. Zestaw arytmetycznych operatorów przypisania to: += przypisanie sumy arg1+=arg2 arg1 = arg1 + arg2 -= przypisanie różnicy arg1-=arg2 arg1 = arg1 - arg2 *= przypisanie iloczynu arg1*=arg2 arg1 = arg1 * arg2 /= przypisanie ilorazu arg1 /=arg2 arg1 = arg1 / arg2 %= przypisanie reszty arg1 %=arg2 arg1 = arg1 % arg2 2017-02-03 W2 23
/* Przyklad 2.11 - arytmetyczny operator przypisania */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { int razem = 0; int ilosc = 10; printf("\nrazem=%d\n", razem); razem += ilosc; printf("razem=%d\n", razem); razem += ilosc; printf("razem=%d\n", razem); system("pause"); return 0; } 2017-02-03 W2 24
Innym operatorem upraszczającym zapis tekstu źródłowego jest operator inkrementacji/dekrementacji. W zależności od sposobu wykonania operacji zwiększenia/zmniejszenia wartości zmiennej o 1 mówimy o operatorze przedrostkowym lub o operatorze przyrostkowym inkrementacji/dekrementacji: ++arg arg = arg + 1 operator przedrostkowy inkrementacji --arg arg = arg - 1 operator przedrostkowy dekrementacji arg++ arg = arg + 1 operator przyrostkowy inkrementacji arg-- arg = arg - 1 operator przyrostkowy dekrementacji 2017-02-03 W2 25
/* Przyklad 2.12 dzialanie przyrostkowego operatora inkrementacji */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { int num=0; printf("\nliczba num = %d", num); printf("\nliczba num = %d", num++); printf("\nliczba num = %d\n", num); system("pause"); return 0; } 2017-02-03 W2 26
/* Przyklad 2.13 dzialanie przedrostkowego operatora inkrementacji */ #include <cstdio> #include <cstdlib> using namespace std; // int main(void) { int num=0; printf("\nliczba num = %d", num); printf("\nliczba num = %d", ++num); printf("\nliczba num = %d\n", num); system("pause"); return 0; } 2017-02-03 W2 27
Operatory relacji służą do sprawdzania w programach zależności pomiędzy wartościami zmiennych, wyrażeń. Relacja może być prawdziwa lub fałszywa. Mówimy, że relacje mają wartości logiczne prawdy lub fałszu. W języku C/C++ istnieje typ logiczny. Deklaruje się słowem kluczowym bool. Wartości logiczne (true albo false) są reprezentowane za pomocą wartości całkowitych: 1 dla prawdy true i 0 dla fałszu false. Zestaw operatorów relacji to: < mniejsze > większe <= mniejsze lub równe >= większe lub równe == równe!= różne Operator równości reprezentowany jest przez dwa znaki równości, a operator "różny" przez znak wykrzyknika i równości 2017-02-03 W2 28
Relacja to wyrażenie postaci : arg1 op arg2 gdzie: arg1, arg2 - argumenty relacji (wyrażenia typów prostych), op - operator relacji. Relacja może być prawdziwa lub fałszywa. W C/C++ relacja prawdziwa ma wartość true (1), fałszywa wartość false (0). Operatory logiczne: dwuargumentowe: sumy logicznej, && iloczynu logicznego Wyrażenie logiczne (funkcja zdaniowa): arg1 op arg2 gdzie: arg1, arg2 - wyrażenia o wartościach true (prawda) albo false (fałsz), op - operator logiczny 2017-02-03 W2 29
Działanie operatorów logicznych dwuargumentowych suma logiczna arg1 arg2 arg1 arg2 0 (fałsz) 1 (prawda) 0 (fałsz) 0 (fałsz) 1 (prawda) 1 (prawda) 1 (prawda) 1 (prawda) iloczyn logiczny arg1 && arg2 arg1 arg2 0 (fałsz) 1 (prawda) 0 (fałsz) 0 (fałsz) 0 (fałsz) 1 (prawda) 0 (fałsz) 1 (prawda) 2017-02-03 W2 30
Operator logiczny jednoargumentowy!arg - negacja arg!arg 0 (fałsz) 1 (prawda) 1 (prawda) 0 (fałsz) 2017-02-03 W2 31
Operatory bitowe - wykonywanie operacji na bitach argumentów ~op op1&op2 op1 op2 op1^op2 op1«op2 op1»op2 negacja bitowa iloczyn bitowy suma bitowa bitowa różnica symetryczna przesunięcie w lewo przesunięcie w prawo Przykłady: Dwie liczby całkowite dodatnie: 337 1109 337 101010001 ~337 1111111010101110 1109 10001010101 ~1110 1111101110101010 2017-02-03 W2 32
Argumenty 337 101010001 1109 10001010101 bitowy iloczyn logiczny 81 1010001 bitowa suma logiczna 1365 10101010101 bitowa różnica symetryczna 1284 10100000100 Przesunięcie: 337 101010001 337 << 3 = 101010001000 (2696) 337 >> 3 = 101010 (42) 2017-02-03 W2 33
// Przykłady kilku wyrażeń #include <iostream> #include <cstdlib> using namespace std; int main() { } int a = 10, b = 20, c; c = (a++) + b--; cout << "Wyniki 1: a = " << a << ", b = " << b << ", c = " << c << endl; a = 10; b = 20; c = (a, b + a, b*b) % (a >> 4, b << 2); cout << "Wyniki 2: a = " << a << ", b = " << b << ", c = " << c << endl; a = 10; b = 20; ++c *= (a!= 0)?a:b++; cout << "Wyniki 3: a = " << a << ", b = " << b << ", c = " << c << endl; ++c *= (a == 0)?a:b++; cout << "Wyniki 4: a = " << a << ", b = " << b << ", c = " << c << endl; system("pause"); return 0; 2017-02-03 W2 34
2017-02-03 W2 35
Podstawowe pojęcia związane z operatorami: Priorytet operatorów - kolejność wykonywania działań Wiązanie - sposób łączenia operatora z operandem (argumentem) Operator unarny - operator wiązany z jednym argumentem Operator binarny - operator wiązany z dwoma argumentami Opracowanie wyrażenia - obliczenia i operacje wykonywane podczas przetwarzania wyrażenia (obliczania jego wartości) 2017-02-03 W2 36
Operator warunkowy arg1?arg2:arg3 wymaga trzech argumentów: arg1 musi być typu prostego arg2 arg3 obydwa muszą być zgodnego typu Najpierw obliczana jest wartość wyrażenia arg1. Jeżeli jest niezerowa (co odpowiada logicznej wartości true), to następuje obliczanie wartości wyrażenia arg2 i tą wartość otrzymuje całe wyrażenie. W przeciwnym przypadku (arg1 równe 0 czyli false) obliczona zostanie wartość wyrażenia arg3 i taką wartość otrzyma całe wyrażenie. 2017-02-03 W2 37
/* Program wczytuje 3 liczby całkowite i wybiera największą z nich */ #include <iostream> using namespace std; int main(void) { int a, b, c; cout << "Podaj trzy liczby całkowite: "; cin >> a >> b >> c; cout << "Największa: " << ((a>b?a:b)>c?(a>b?a:b):c) << endl; return 0; } 2017-02-03 W2 38
Priorytet operatorów () [] { } -> :: wiązanie: od lewej do prawej! ~ + - ++ -- & * (typ) sizeof new delete od prawej do lewej ->* od lewej do prawej / % od lewej do prawej + - od lewej do prawej << >> od lewej do prawej < <= > >= od lewej do prawej ==!= od lewej do prawej & od lewej do prawej ^ od lewej do prawej od lewej do prawej && od lewej do prawej od lewej do prawej?: od lewej do prawej = *= /= %= += -= &= ^= = <<= >>= od prawej do lewej, (przecinek) od lewej do prawej 2017-02-03 W2 39