Typy danych - Politechnika Śląska
Transkrypt
Typy danych - Politechnika Śląska
Programowanie komputerów Jacek Lach Zakład Oprogramowania Instytut Informatyki Politechnika Śląska Jacek Lach. Programowanie komputerów Plan • printf • Typy danych Jacek Lach. Programowanie komputerów Temperatury – wersja 2 #include <stdio.h> /* print Fahrenheit-Celsius table for fahr = 0, 20, ..., 300; floating-point version, acc. to K&R */ int main() { float fahr, celsius; float lower, upper, step; lower = 0; /* lower limit of temperature scale */ upper = 300; /* upper limit */ step = 20; /* step size */ fahr = lower; while (fahr <= upper) { celsius = (5.0/9.0) * (fahr-32.0); printf("%3.0f %6.1f\n", fahr, celsius); fahr = fahr + step; } return 0; } Definiowanie nazw – krótko Jacek Lach. Programowanie komputerów • #define nazwa tekst_zastępujący • Wszystkie wystąpienia nazwy (za wyjątkiem stałych tekstowych i części innych nazw) zostaną zastąpione tekstem_zastępującym • nazwa ma postać identyfikatora • tekst_zastępujący może być dowolnym ciągiem znaków, niekoniecznie liczb Wersja 3 – pętla for #include <stdio.h> Jacek Lach. Programowanie komputerów #define LOWER 0 #define UPPER 300 #define STEP 20 /* dolny zakres tabeli */ /* górny zakres */ /* krok */ /* Wypisywanie tabeli Fahrenheit-Celsius, według K&R */ int main() { int fahr; for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP) printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32) ); return 0; } Instrukcja for Jacek Lach. Programowanie komputerów • Instrukcja for organizuje pętlę, jest uogólnieniem while • Wewnątrz nawiasów umieszczane są trzy części oddzielane średnikami: • inicjalizacja • warunek • modyfikacja • Przykład: • for(i=0;i<10;i++) {...} * jako specyfikator precyzji Jacek Lach. Programowanie komputerów • Szerokość lub precyzja mogą być zdefiniowane przez gwiazdkę (*). Wtedy określa je następny argument, koniecznie typu int. • Przykład: printf("%.*f", max, x); printf – konwersje Jacek Lach. Programowanie komputerów • • • • • • • • • • d,i int; decimal number o int; unsigned octal number (without a leading zero) x,X int; unsigned hexadecimal number (without a leading 0x or 0X), using abcdef or ABCDEF for 10, ...,15. u int; unsigned decimal number c int; single character s char *; print characters from the string until a '\0' or the number of characters given by the precision. f double; []m.dddddd, where the number of d's is given by the precision (def: 6) e,E double; []m.dddddde+/xx or []m.ddddddE+/xx, where the number of d's is given by the precision (default 6). g, G double; use %e or %E if the exponent is less than 4 or greater than or equal to the precision; otherwise use %f. Trailing zeros and a trailing decimal point are not printed. p void *; pointer (implementationdependent representation). % no argument is converted; print a % printf – sterowanie formatem Jacek Lach. Programowanie komputerów %[flagi] [szerokość] [precyzja] [modyfikator_wielkości] typ_parametru • Flagi: • wyrównuje liczbę do lewej (normalnie byłaby wyrównana do prawej) • + liczba zawsze zaczyna się od znaku "+" (dla dodatnich) lub "" (dla ujemnych), normalnie znak jest wyświetlany tylko dla liczb ujemnych printf – sterowanie formatem Jacek Lach. Programowanie komputerów %[flagi] [szerokość] [precyzja] [modyfikator_wielkości] typ_parametru • Szerokość: • n określa, ile znaków zostanie wyświetlonych. Jeśli n jest większe od szerokości liczby, to zostanie ona uzupełniona spacjami. Jeśli jest mniejsze to liczba nie zostanie ucięta. • 0n określa, ile znaków zostanie wyświetlonych. Jeśli n jest większe od szerokości liczby, to zostanie ona uzupełniona zerami. Jeśli jest mniejsze to liczba nie zostanie ucięta. printf – sterowanie formatem Jacek Lach. Programowanie komputerów %[flagi] [szerokość] [precyzja] [modyfikator_wielkości] typ_parametru • Modyfikator wielkości: • l określa, że parametr jest typu long (np. long int to %ld) • h określa, że parametr jest typu short (np. short int to %hd) printf – przykłady 0.521 Jacek Lach. Programowanie komputerów • "[%6.3f]" wyświetli się "[ 0.521]". Liczba 6 oznacza szerokość całej liczby, a nie tylko części przed przecinkiem. Ponieważ szerokość liczby jest równa pięć, to została dodana jedna spacja przed liczbą. • "[%6.3f]" wyświetli się "[0.521 ]". Jak wyżej, tylko spacja została dodana po liczbie (wyrównanie do lewej). • "[%06.3f]" wyświetli się "[00.521]". Zamiast spacji, zostało dodane zero. • "[%+6.3f]" wyświetli się "[+0.521]". Oczywiście dla wartości 0.521 wyświetli się znak minus, nie plus Jacek Lach. Programowanie komputerów printf – przykłady short s = 1235; int i = 12345; long l = 12345678; unsigned u = 65535; format wyjście |%d\%d| |12345|-12345| |%8d|%8d| | 12345| -12345| |%-8d|%-8d| |12345 |-12345 | |%+8d|%+8d| | +12345| -12345| |%-+8d|%-+8d| |+12345 |-12345 | |%08d|%08d| |00012345|-0012345| |% 08d|% 08d| | 0012345|-0012345| |%+08d|%+08d| |+0012345|-0012345| |%10.8d|%10.8d| | 00012345| -00012345| printf – przykłady Jacek Lach. Programowanie komputerów short int long unsigned s i l u = = = = 1235; 12345; 12345678; 65535; format wid = 14; ..."|%*d|\n", wid, i ); wid = 9; ..."|%*d|\n", wid, i ); "|%14ld|%14ld|", l, -l "|%10hd|,%10hd", s, -s "|%u|%d|", u, u |%3ld| wyjście | 12345| | 12345| | 12345678|... | 1235|... |65535|-1| |12345678| printf – przykłady Jacek Lach. Programowanie komputerów short hex = 0x0b52; format wyjście |%x| |%X| |%.4x| |%04x| |%10.8X| |%#x| |b52| |B52| |0b52| |0b52| | 00000B52| |0xb52| printf – przykłady Jacek Lach. Programowanie komputerów short oct = 0571; format wyjście |%o| |%5o| |%8.5o| |571| | 571| | 00571| printf – przykłady Jacek Lach. Programowanie komputerów long l = 12345678; format wyjście |%#lo| |%#lx| |%#ld| |057060516| |0xbc614e| |12345678| printf – przykłady Jacek Lach. Programowanie komputerów float f = 5.555555; format wyjście |%f| |%.2f| |%10f| |%10.2f| |%010.2f| |%-10f| |%+.2f| |5.555555| |5.56| | 5.555555| | 5.56| |0000005.56| |5.555555 | |+5.56| Jacek Lach. Programowanie komputerów printf – przykłady double ff = 1234000000.0; format wyjście |%.3e| |1.234e+09| |%E| |1.234000E+09| |%.3E| |1.234E+09| |%12.5e| | 1.234000e+09| |%g| |%g| |%12g| |1.234e+09| |1234| | 1.234e+09| 1.1 |%.4g| |%#.4g| |%.10g| |1.1| |1.100| |3.141592654| printf – przykłady Jacek Lach. Programowanie komputerów char c = 'A"; format |%c| |%4c| |%-4c| |%04c| wyjście |A| | A| |A | | A| Łańcuchy – precyzja Jacek Lach. Programowanie komputerów • ”hello, world” (12 znaków) z dwukropkami :%s: :%10s: :%.10s: :%-10s: :%.15s: :%-15s: :%15.10s: :%-15.10s: :hello, world: :hello, world: :hello, wor: :hello, world: :hello, world: :hello, world : : hello, wor: :hello, wor : printf – przykłady Jacek Lach. Programowanie komputerów char str[] = "This is all there is."; format wyjście |%s| |%30s| |%5s| |%.5s| |%-30s| |%10.2s| |This | |This |This |This | is all there is.| This is all there is.| is all there is.| | is all there is. | Th| Strumienie we/wy • Standardowe wejście: stdin • Standardowe wyjście: stdout Jacek Lach. Programowanie komputerów • Stand. strumień błędów: stderr • Szczegóły zostaną omówione później • Normalnie strumienie te są związane z konsolą: • stdin z klawiaturą • stdout i stderr z terminalem tekstowym • Strumienie mogą być przekierowywane • testapp.exe <dane.txt >wyniki.txt Wejście znakowe • Odczytanie pojedynczego znaku lub EOF: • int getc(FILE *stream); Jacek Lach. Programowanie komputerów • powyższa deklaracja nazywana jest prototypem • Przykład: • int c; • c = getc(stdin); • Dlaczego używamy int dla c zamiast char? • Czytanie jednego znaku z stdin: • int getchar(void); • getchar() działa jak getc(stdin) Wyjście znakowe • Zapis pojedynczego znaku do strumienia: • int putc(int c, FILE *stream); Jacek Lach. Programowanie komputerów • Przykład: • putc(’A’,stdout); • Zapis pojedynczego znaku do stdout: • int putchar(int c); • putchar(’A’) działa jak putc(’A’,stdout) • Zwracana wartość: wypisany znak Jacek Lach. Programowanie komputerów Kopiowanie #include <stdio.h> /* kopiowanie wejścia na wyjście: pierwsza wersja */ main() { int c; c = getchar(); while (c != EOF) { putchar(c); c = getchar(); } return 0; Kopiowanie Jacek Lach. Programowanie komputerów #include <stdio.h> /* copy input to output; 2nd version */ main() { int c; while ((c = getchar()) != EOF) putchar(c); return 0; } Zliczanie znaków Jacek Lach. Programowanie komputerów #include <stdio.h> /* count characters in input; */ main() { long nc; nc = 0; while (getchar() != EOF) ++nc; printf("%ld\n", nc); return 0; } Zliczanie znaków Jacek Lach. Programowanie komputerów #include <stdio.h> /* count characters in input; 2nd version */ main() { double nc; for (nc = 0; gechar() != EOF; ++nc) ; printf("%.0f\n", nc); return 0; } Zliczanie wierszy Jacek Lach. Programowanie komputerów #include <stdio.h> /* count lines in input */ main() { int c, nl; nl = 0; /* the number of lines so far */ while ((c = getchar()) != EOF) if (c == '\n') /* new line found */ ++nl; printf("%d\n", nl); return 0; } Zmienne w pamięci Jacek Lach. Programowanie komputerów • Każda zmienna pamiętana jest w pewnym miejscu pamięci ... lub w rejestrze procesora • Adres zmiennej jest indeksem tej komórki pamięci, w której znajduje się pierwszy bajt zmiennej • Liczba bajtów zajmowanych przez zmienną zależy od jej typu; operator sizeof informuje o tym rozmiarze: sizeof(type) Wskaźniki Jacek Lach. Programowanie komputerów • Wskaźnik jest adresem, pod którym znajduje się zwykle coś użytecznego • Definiowanie zmiennej przechowującej adres: <type> *<variable> • Przykład: int *pti; • Pobieranie adresu, pod którym przechowywana jest zmienna: operator & int x; pti = &x; Wskaźniki int x; Jacek Lach. Programowanie komputerów pti = &x; x = 5; *pti = *pti + 1; /* teraz x = 6 */ x++; printf(”%d”,x); /* 7 */ Wskaźniki dlaczego teraz? Jacek Lach. Programowanie komputerów • ...aby przeczytać z wejścia coś bardziej złożonego niż pojedynczy znak • scanf jest odpowiednikiem printf dla strumienia wejściowego • udostępnia wiele podobnych konwersji jak printf, ale w przeciwnym kierunku • Prototyp: • int scanf(char *format, ...) • scanf wymaga wskaźników do zmiennych scanf – przykład Jacek Lach. Programowanie komputerów #include <stdio.h> main() { int x; printf(” Podaj liczbę: ”); scanf(”%d”, &x); printf(”Kwadrat %d wynosi %d\n”, x, x*x); return 0; } scanf – błędne dane #include <stdio.h> main() Jacek Lach. Programowanie komputerów { int a,b; scanf("%d",&a); /* abc */ printf("a=%d\n",a); /* przypadkowa wart. */ scanf("%d",&b); /* nie czeka! */ printf("b=%d\n",b); /* znowu przyp. wart. */ return 0; } Typy danych • Jest tylko kilka podstawowych typów danych w C: Jacek Lach. Programowanie komputerów • char pojedynczy bajt, mogący przechowywać jeden znak z lokalnego zestawu znaków • int liczba całkowita, zwykle odzwierciedlająca rozmiar słowa maszynowego na danym komputerze • float liczba zmiennoprzecinkowa pojedynczej precyzji • double liczba zmiennoprzecinkowa podwójnej precyzji Typy danych • Dodatkowo mogą być stosowane kwalifikatory opisujące dodatkowe typy (modyfikacje): Jacek Lach. Programowanie komputerów • short i long stosowane do liczb całkowitych • Słowo int może być opuszczone w takich deklaracjach i zwykle tak się robi • signed lub unsigned mogą byś stosowane do char i innych typów całkowitych Typy danych • short i long s powinny być różnej długości Jacek Lach. Programowanie komputerów • int ma zwykle rozmiar wynikający z długości słowa maszyny • short ma zwykle 16 bitów, int ma 16 bitów lub 32 bity • Każdy kompilator może obsługiwać inne rozmiary typów całkowitych, zależnie od możliwości sprzętu. Zastrzega się, że short i int mają co najmniej 16 bitów, long co najmniej 32 bity, short jest nie dłuższy niż int, który jest nie dłuższy niż long. Typy danych Jacek Lach. Programowanie komputerów • Kwalifikator signed lub unsigned może być zastosowany do char lub innych typów całkowitych • Liczby unsigned są zawsze nieujemne, podlegają zasadom arytmetyki modulo 2n, gdzie n jest długością zmiennej danego typu w bitach • Na przykład, jeśli char ma 8 bitów: • unsigned char mają wartości od 0 do 255, • signed chars mają wartości od 128 do 127 (w arytmetyce dopełnień do 2) • Typ char może być signed lub unsigned zależy od maszyny. Znaki drukowalne są zawsze dodatnie. Typy danych Jacek Lach. Programowanie komputerów • Typ long double określa liczby zmiennoprzecinkowe o podwyższonej precyzji • Tak jak w przypadku liczb całkowitych, rozmiary typów zmiennoprzecinkowych są zależne od implementacji • float, double i long double mogą reprezentować jeden, dwa lub trzy różne rozmiary • Standardowe nagłówki <limits.h> i <float.h> zawierają stałe symboliczne dla wszystkich tych rozmiarów, wraz z innymi własnościami zależnymi od kompilatora i maszyny Typy danych – limits.h # define CHAR_BIT 8 Jacek Lach. Programowanie komputerów /* Minimum and maximum values a `signed char' can hold. # define SCHAR_MIN (-128) # define SCHAR_MAX 127 */ /* # /* # Maximum value an `unsigned char' can hold. (Minimum is 0.) define UCHAR_MAX 255 Maximum value an `unsigned int' can hold.(Minimum is 0.) */ define UINT_MAX 4294967295U /* # # # # # Minimum and maximum values a `signed long int' can hold. if __WORDSIZE == 64 define LONG_MAX 9223372036854775807L else define LONG_MAX 2147483647L endif */ */ Jacek Lach. Programowanie komputerów Typy danych – konwersje • Kiedy operator ma działać na operandach różnych typów, są one konwertowane przy zastosowaniu niewielkiego zbioru reguł. double x, y; int k; // Różne typy! y = x + k; • Ogólnie, jedynymi automatycznymi konwersjami są takie, które przekształcają typ „mniejszy” w „większy” bez utraty informacji. Konwersje • Wyrażenia, które nie mają sensu, są zakazane Jacek Lach. Programowanie komputerów • Przykład: użycie float jako indeksu • Wyrażenia, w których można utracić informację, powodują zgłoszenie ostrzeżenia, ale są dozwolone; przykłady: • kopiowanie większego typu całkowitego do mniejszego • przypisanie wartości zmiennoprzecinkowej do zmiennej całkowitej Konwersje Jacek Lach. Programowanie komputerów • Jeśli nie występują operandy unsigned, wystarczający jest następujący zestaw reguł: • Jeśli jeden z operandów jest typu long double, przekształć drugi na long double. • W przeciwnym wypadku, jeśli jeden operand jest double, przekształć drugi na double. • W przeciwnym wypadku, jeśli operand jest float, przekształć drugi na float. • W przeciwnym wypadku, przekształć char i short na int. • Potem, jeśli jeden z operandów jest long, przekształć drugi na long. Wymuszanie konwersji Jacek Lach. Programowanie komputerów • Jawna konwersja typu może być wymuszona w wyrażenie przez zastosowanie operatora rzutowania (ang. cast) • W następującej konstrukcji: (nazwa_typu) wyrażenie wyrażenie jest przekształcane na wyrażenie o podanym typie cels = ((double)5/9) * (fahr32); • Konwersje są również wykonywane w wywołaniach funkcji Stałe • Stała całkowita taka jak 1234 jest typu int Jacek Lach. Programowanie komputerów • Stałe long są zapisywane z przyrostkiem l lub L: 123456789L • Stałe całkowite bez znaku (unsigned) są zapisywane z przyrostkiem u lub U (ul oznacza unsigned long) Stałe • Poprzedzające stałą 0 (zero) oznacza stałą ósemkową Jacek Lach. Programowanie komputerów • System ósemkowy: np. 31 oct = 25 dec • Poprzedzające stałą 0x lub OX oznacza stałą szesnastkową • Przykład: • 31 = 037 = 0x1f • Inny przykład: • 0XFUL to stała typu unsigned long o wartości dziesiętnej 15 Stałe Jacek Lach. Programowanie komputerów • Stała znakowa (character constant) to wartość całkowita, zapisywana jako pojedynczy znak w apostrofach, np. 'x' • Wartość stałej odpowiada kodowi znaku w lokalnej tablicy kodów • Przykład: • '0' ma wartość 48 w kodzie ASCII Stałe Jacek Lach. Programowanie komputerów • Stałe znakowe biorą udział w operacjach arytmetycznych tak jak inne stałe całkowite • Niektóre znaki mogą być reprezentowane przez specjalne, dwuznakowe sekwencje przykład: • '\n' (znak nowego wiersza) • sekwencja, chociaż składa się z dwóch znaków, reprezentuje jeden znak Stałe Jacek Lach. Programowanie komputerów • Dowolna stała o rozmiarze bajtu może być zapisana jako • '\ooo' gdzie ooo to jedna to trzech cyfr ósemkowych (0...7) • lub jako: '\xhh' gdzie hh jest jedną lub więcej cyfr szesnastkowych (0...9, a...f, A...F) Jacek Lach. Programowanie komputerów Sekwencje specjalne • \a alert \' single quote • \b backspace \" double quote • \f form feed \ooo • \n newline \xhh • \r carriage return • \t horizontal tab • \v vertical tab • \\ backslash • \? question mark Przykład • char b[]="abc"; • b[0]: 'a' Jacek Lach. Programowanie komputerów • b[1]: 'b' • b[2]: 'c' • b[3]: '\x0' • (int)b[0]: 97 • (int)b[1]: 98 • (int)b[2]: 99 • (int)b[3]: 0 Przykład • char b[]="a0\n"; • b[0]: 'a' Jacek Lach. Programowanie komputerów • b[1]: '0' • b[2]: '\n' • b[3]: '\x0' • (int)b[0]: 97 • (int)b[1]: 48 • (int)b[2]: 10 • (int)b[3]: 0 Przykład • char b[]="\nn\n"; • b[0]: '\n' Jacek Lach. Programowanie komputerów • b[1]: 'n' • b[2]: '\n' • b[3]: '\x0' • (int)b[0]: 10 • (int)b[1]: 110 • (int)b[2]: 10 • (int)b[3]: 0 Przykład • char b[]="a\066b"; • b[0]: 'a' Jacek Lach. Programowanie komputerów • b[1]: '6' • b[2]: 'b' • b[3]: '\x0' • (int)b[0]: 97 • (int)b[1]: 54 • (int)b[2]: 98 • (int)b[3]: 0 Przykład • char b[]="\123c"; • b[0]: 'S' Jacek Lach. Programowanie komputerów • b[1]: 'c' • b[2]: '\x0' • (int)b[0]: 83 • (int)b[1]: 99 • (int)b[2]: 0 Przykład • char b[]="\567c"; • Błąd! Jacek Lach. Programowanie komputerów • Kod > 255 Przykład • char b[]="\xefgh"; • b[0]: '´' Jacek Lach. Programowanie komputerów • b[1]: 'g' • b[2]: 'h' • b[3]: '\x0' • (int)b[0]: 239 • (int)b[1]: 103 • (int)b[2]: 104 • (int)b[3]: 0 Przykład • char b[]="\x12x\n"; • b[0]: '\x12' Jacek Lach. Programowanie komputerów • b[1]: 'x' • b[2]: '\n' • b[3]: '\x0' • (int)b[0]: 18 • (int)b[1]: 120 • (int)b[2]: 10 • (int)b[3]: 0 Stałe i wyrażenia Jacek Lach. Programowanie komputerów • Stałe wyrażenie jest wyrażeniem, w którym występują tylko stałe • Stałe wyrażenie może być obliczone podczas kompilacji, a nie wykonania programu. Stałe łańcuchowe Jacek Lach. Programowanie komputerów • Stała łańcuchowa albo stała tekstowa (lub znakowa) jest ciągiem zera lub więcej znaków otoczonych przez znaki " • Przykład: • "Jestem łańcuchem znakowym" • Stałe znakowe mogą być łączone (konkatenowane) podczas kompilacji: • "hello, " "world" jest równoważne: • "hello, world" Stałe wyliczeniowe • Wyliczenie jest listą stałych o wartościach całkowitych, np. Jacek Lach. Programowanie komputerów • enum boolean { NO, YES }; • Pierwsza nazwa w enum ma wartość 0, następna 1 itd., chyba, że zostaną określone inne wartości. • Jeśli nie wszystkie wartości zostaną podane, to dla nieokreślonych przyjęte zostaną wartości będące kontynuacją ostatniej podanej wartości, jak np.: • enum months {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC }; /* FEB = 2, MAR = 3, itd. */ • Nazwy w tym samym i różnych wyliczeniach nie mogą się powtarzać. Wartości mogą się powtarzać.