Podstawy Informatyki Zmienne w języku C dr inż. Piotr Kaczmarek Piotr.Kaczmarek@put.poznan.pl
Systemy liczbowe Decimal Binary Hex (baza 10) (baza 2) (baza 16) 0 0000 0 1 0001 1 2 0010 2 3 0011 3 4 0100 4 5 0101 5 6 0110 6 7 0111 7 8 1000 8 9 1001 9 10 1010 A 11 1011 B 12 1100 C 13 1101 D 14 1110 E 15 1111 F 35 10 0011 23 100 110 0100 64 255 1111 1111 FF System dziesiętny 512=5*10 2 +1*10 1 +2*10 0 System binarny 110101b= 1*2 5 +1*2 4 +0*2 3 +1*2 2 +0*2 1 +1*2 0 System szesnastkowy 0xfa1= f*16 2 +a*16 1 +1*16 0 = 16*16 2 +10*16 1 +1*16 0
Bit, Bajt... Bit jest najmniejszą jednostką informacyjną Może przyjmować wartość 0 lub 1 Jest podstwą (bazą systemu binarnego) Bajt jest złożony z 8bit Oznacza to że bajt jest liczbą z zakresu najmniejsza wartość wynosi: 00000000b a największa 11111111b
Pojemność informacyjna Jest maksymalną ilością stanów które mogą być wyrażone za pomocą n cyfr Jest zdefiniowana jako N=(baza) n dziesiątkowy: xxx 3 cyfry binarny: xxxxxxxxb 8 cyfr szesnastkowy: 0x(xx) 2 cyrfy N=10 3 =1000 zakres 0-999 N=2 8 =256 zakres 00000000b-11111111b pojemność informacyjna jednej cyfry w systemie Hex odpowiada pojemności czterech cyfr w systemie binarnym N=16 2 =256 zakres 0x00-0xff
Typy w języku C Typy całkowitoliczbowe: char, bool, short, int, long, long long int8, int16, int32, int64, Typy całkowitoliczbowe bez znaku: unsigned int, unsigned long, unsigned char, Typy zmiennoprzecinkowe float, double
Rozmiary i zakresy typów (Visual Studio) typ zakres bool, char - -128 do 127 short, int16 - -32768 do 32767 int, long - 2147483648 do 2147483647 unsigned char - 0 do 255 unsigned short - 0 do 65535 float - 3.4E +/- 38 (7 cyfr) double - 1.7E +/- 308 (15 cyfr) Ilość bajtów wykorzystywana do reprezentacji danego typu zależy od kompilatora. wyjątek stanowi typ char. char<=short<=int<=long
Reprezentacja liczb naturalnych Liczby całkowite bez znaku (unsigned) liczba 1b wartość binarna 0 00000000b 1 00000001b 2 00000010b... 127 01111111b 128 10000000b... 255 11111111b Ile wynosi; 255+1?? dla arytmetyki dziesiętnej: 256 (100000000b) dla liczby 8bit: 0 (00000000b)
Reprezentacja liczb całkowitych Liczby całkowite ze znakiem liczba 1b wartość binarna 0-128 10000000b... 0-2 11111110b 0-1 11111111b 0 00000000b 1 00000001b 2 00000010b... 127 01111111b Ile wynosi; 127+1?? dla arytmetyki dziesiętnej: 128 (10000000b) dla liczby 8bit ze znakiem: -127 (10000000b)
Reprezentacja liczb zmiennoprzecinkowych IEEE Standard 754 Floating Point Numbers sign znak (z) 1b Exponent cecha (c) 8/11b Fraction mantysa(c) 23/52b Po przekroczeniu zakresu liczby przyjmują wartość: 'Inf' (infinity) chroni to przed przepełnieniem wartość w=(-1) z * 2 c-bias * (0.m) po błędnym przypisaniu przybiera wartość NaN (not a number)
Literały Literał (literal constant) jest stałą która może być wykorzystywana w programie literały całkowite 20, 0x14 liczba całkowita typu int wyrażona w różnych systemach 20L liczba całkowita typu long 128u liczba typu unsigned int 128Lu liczba typu unsigned long literały zmiennoprzecinkowe float: 0.1, 3.14159F, 0.1f, 3e1 double: 1.0L
Deklaracja/definicja zmiennych Zmienna (variable) jest wykorzystywana w programie do przechowywania pewnej wartości. Zmienna w programie identyfikowana jest za pomocą nazwy (identyfikatora) złożonej z liter cyfr i '_', nazwa zmiennej nie może zaczynać się od cyfry. Zmienna musi posiadać ściśle określony typ. Definicja/deklaracja zmiennej polega na określeniu typu i nazwy zmiennej w pewnym miejscu programu. Ogólnie definicja/deklaracja zmiennej ma postać: typ identyfikator; //definicja i deklaracja extern typ identyfikator; //deklaracja Począwszy od miejsca gdzie zmienna została zadeklarowana może być używana w programie
Definicja a deklaracja Definicja zmiennej oznacza że w miejscu jej definicji, jest przydzielany odpowiedni obszar pamięci w którym przechowywana będzie wartość reprezentowana przez tą zmienną Deklaracja określa typ danych reprezentowanych przez zmienną o określonym identyfikator. Deklaracja bez definicji mówi kompilatorowi, że zmienna ta została zdefiniowana (została zarezerwowana dla niej pamięć) gdzieś indziej (np w innym pliku)
Identyfikatory nazwy zmiennych Nazwy zmiennych zapisuje się zazwyczaj małymi literami (wartosc zamiast Wartosc czy WARTOSC) Nazwa pisana inną wielkością liter opisuje inny identyfikator Identyfikatorami powinny być słowa, które odpowiednio kojarzą się z przeznaczeniem obiektu Identyfikator złożony z kliku słów tworzy się oddziela się '_' lub każdy wyraz pisze się wielką literą np: int wartosccalkowita; lub int wartosc_calkowita; a nie int wartosccalkowita;
Definicje zmiennych Proste definicje: int main() { char znak; int liczba=12; //definicja z inicjacją double wspolczynnik;... return 0; } Definicja wielu zmiennych tego samego typu int liczba, wartosc=10, licznik;
Operacje arytmetyczne Operatory arytmetyczne: +,-,/,*,=,(,) np:. float a,b=5,c=3; a=b*c+2*(b+1.0); //przypisanie wartości zmiennej a jako wyniku operacji arytmetycznej Funkcje matematyczne (wymaga dołączenia pliku #include<math.h> a=c*sin(b*3.14159/180.0); //lub a=c*sin(b*pi/180.0); gdy PI zostało zdefiniowane a=pow(b,2)+pow(c+b,2); //b^2+(c+b)^2 a=sqrt(b); //pierwiastek kwadratowy z b inne funkcje: cos, sin, tan, pow, sqrt...
Inkrementacja, przypisanie Inkrementacja (zwiększenie o 1) int liczba=1; liczba = liczba +1; //liczba wynosi 2 analogiczny zapis: liczba+=1; liczba++; analogicznie liczba--; \\zmniejsza wartość o 1; operatory +=,-=,*=, /= liczba +=2; jest to samo co liczba = liczba+2; liczba -=2; jest to samo co liczba = liczba-2; liczba *=2; jest to samo co liczba = liczba*2;
Tablica ASCII reprezentacja znaków Zmienna typu char przechowuje liczby całkowite. Wartość odpowiada literze z tablicy ASCII char znak; znak='a'; jest równorzędne: znak=0x61; ` char znak; znak='a'; znak=znak+1; wtedy zmienna znak ma wartość 0x62!!!
Konwersja typów Operacje arytmetyczne na zmiennych różnych typów Analizowana jest prawa strona wyrażenia i określany jest typ najstarszy (najbardziej znaczący) zgodnie z schematem: char->int->long->float->double Wszystkie elementy wyrażenia konwertowane są do typu najstarszego Obliczane jest wyrażenie Wynik przypisywany jest do zmiennej po prawej stronie z zastosowaniem ew. konwersji. Wtedy przy konwersji z liczby rzeczywistej na całkowitą obcinana jest część dziesiętna, a odwrotnie znajdywana jest najbliższa liczba rzeczywista
Konsekwencje konwersji int a=1.0,b=2,c=3, d; float x=1.0, v; d=a/b; //konwertowane do int wynik 0 d=a/b*c; //wynik 0 d=c*a/b; // wynik 1!! d=x/b*c; //konwertowane do float a następnie do int wynik 1 v=a/b*c; //wynik 0.0 v=x/b*c; //wynik 1.5
Metody konwersji Konwersja niejawna float a=5.1; int b=a; Konwersja przez rzutowanie float a; int b=1,c=2; a=b/c; //konwersja niejawna wynik 0.0 a=(float)b/c; //wymuszenie konwersji b do float poprzez rzutowanie wynik 0.5 Konwersja przez wprowadzenie literału a=b/c*1.0; //konwersja do float wynik 0.5
a Wyświetlanie danych strumienie int a=3,b=4,c; float pole=a*b/2.0; b c=sqrt(a*a+b*b); cout<< przeciwprostokatna trojkata o przyprostokatnych <<a<< i <<b<< wynosi <<c<<, zas pole wynosi <<pole<<endl; spowoduje wyświetlenie na ekranie: przeciwprostokatna trojkata o przyprostokatnych 3 i 4 wynosi 5, zas pole wynosi 6 W strumieniu można umieścić zmienną dowolnego typu, jej wartość zostanie wyświetlona zgodnie z obowiązującymi zasadami formatowania c
a Wyświetlanie danych printf int a=3,b=4,c; float pole=a*b/2.0; b c=sqrt(a*a+b*b); printf( przeciwprostokatna trojkata o przyprostokatnych %d i %d wynosi %d, zas pole wynosi %f,a, b, c, pole); spowoduje wyświetlenie na ekranie przeciwprostokatna trojkata o przyprostokatnych 3 i 4 wynosi 5, zas pole wynosi 6 c
Formatowanie tekstu i specyfikatory konwersji Format przekazywany jako pierwszy argument funkcji printf zawiera 2 typy obiektów: zwykłe znaki (wyświetlane na ekranie) specyfikacje konwersji z których każda powoduje konwersję i wydrukowanie kolejnego argumentu: %d argument całkowity przekształcany do postaci dziesiętnej %x argument całkowity przekształcany do postaci szesnastkowej %u argument typu unsigned przekształcony do postaci dziesiętnej
Formatowanie tekstu i specyfikatory konwersji %f argument typu float lub double (w postaci ddd.ddd %e argument typu float lub double przekształcony do postaci d.ddde-dd %c argument typu char wyświetlany jako znak z tablicy ASCII %s argument typu tablica znaków, wyświetlany jako napis Ustawianie precyzji: %[szerokość].[precyzja]f gdzie szerokość określa minimalna ilość znaków a precyzja ilość znaków w części dziesiętnej
Przykład #include <stdio.h> int main() { printf ("Znaki: %c %d %c \n", 'a', 'A', 65); printf ("Dziesietne: %d %ld\n", 1977, 650000); printf ("Poprzedzone polami pustymi: %10d \n", 1977); printf ("Poprzedzone zerami: %010d \n", 1977); printf ("Rozne systemy numeryczne: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100); printf ("Rzeczywiste: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416); printf ("Zmienna szerokosc: %*d \n", 5, 10); printf ("%s \n", "Napis"); return 0; } Rezultat Znaki: a 65 A Dziesietne: 1977 650000 Poprzedzone polami pustymi: 1977 Poprzedzone zerami: 0000001977 Różne systemy numeryczne: 100 64 144 0x64 0144 Rzeczywiste: 3.14 +3e+000 3.141600E+000 Zmienna szerokosc: 10 Napis
Formatowanie strumienia Ustawianie precyzji cout.precision(n); gdzie n jest ilością cyfr w wyświetlanej liczbie, wpływa na wszystkie operacje aż do następnego wywołania metody. np. cout.precision(8); cout<<1234.56789; wyswietli 1234.5679 Systemy liczbowe cout.setf(ios::oct,ios::basefield); //ósemkowy cout.setf(ios::dec,ios::basefield);//dziesietny cout.setf(ios::hex,ios::basefield);//dziesietny
Formatowanie strumienia Minimalna szerokość pola (n) cout.width(n); Wyrównanie w ramach pola cout.setf(ios::left,ios::adjustfield); //do lewej cout.setf(ios::right,ios::adjustfield); //do prawej cout.setf(ios::internal,ios::adjustfield); //do obu np cout.width(5); cout.setf(ios::right,ios::adjustfield); cout<<'('<<-12<< )\n ; wyświetli ( -12)
Pobieranie danych Wczytywanie z klawiatury za pomocą strumienia wejściowego cin: int a; float b; cout<< podaj liczbe calkowita: ; cin>>a; cout<< podaj liczbe rzeczywista: ; cin>>b; strumień cin przy wykorzystaniu operatora>> pozwala na wczytanie zmiennej dowolnego typu.
Pobieranie danych Wczytywanie z klawiatury za pomocą standardowej funkcji C - scanf int a; float b; cout<< podaj liczbe calkowita: ; scanf( %d,&a); cout<< podaj liczbe rzeczywista: ; scanf( %f,&b); argument formatu musi zawierać specyfikacje konwersji zgodną z typem argumentu argumenty typów liczbowych poprzedzane są operatorem &
Pobieranie znaku z klawiatury Metody wczytywania znaku z klawiatury char znak; 1. cin>>znak; 2. scanf( %c,&znak); 3. znak=getchar(); 4. znak=_getch(); metody 1-3 wymagają wprowadzenie znaku i zatwierdzenie go enterem metody 1-3 wyświetlają znak na ekranie metoda 4 odczytuje znak natychmiast po jego wprowadzeniu i nie wyświetla go na ekranie, nie wymaga akceptacji enterem
Zmienne łańcuchowe (Null terminated string) Napisy reprezentowane są w C i C++ jako ciąg liter do przechowywania napisów służy tablica zmiennych char zdefiniowana jako: char napis[12]; //12-o elementowa tablica liter W tablicy może zostać umieszczony napis krótszy niż jej rozmiar Na końcu każdego napisu umieszczany jest znak pusty \0 (null terminated) W tablicy o rozmiarze N można przechować max N-1 znaków Nr elementu kod ASCII 0 1 2 3 4 5 6 7 8 9 10 11 P o d s t a w y \0 x x x Wartość 80 111 100 115 116 97 119 121 0???
Wyświetlanie i pobieranie napisów Pobieranie pojedynczych wyrazów char napis[100]; 1. cin>>napis 2. scanf( %s,napis); //UWAGA brak &!!! Pobieranie linii tekstu cin.getline(napis,100); //drugi argument określa maksymalną ilość znaków (np. rozmiar tablicy) gets(napis)
Inne operacje na łańcuchach inicjacja tablicy (możliwe wyłącznie w lini definicji) char napis[]= Podstawy Informatyki ; Wypełnianie tablicy char tekst[100]; strcpy(tekst,napis); \\lub strcpy(tekst, Podstawy Informatyki ); Łączenie łańcuchów strcat(tekst, semestr 1 ); // Podstawy Informatyki semestr 1
Inne operacje na łańcuchach Wyświetlanie do napisu int a=3,b=4,c; float pole=a*b/2.0; char napis[80]; c=sqrt(a*a+b*b); sprintf(napis, przeciwprostokatna trojkata o przyprostokatnych %d i %d wynosi %d, zas pole wynosi %f,a, b, c, pole); Instrukcja sprintf zamiast na ekranie sformatowany ciąg umieszcza w tablicy znaków
Makroinstrukcje dyrektywa #define pozwala na przypisanie pewnemu identyfikatorowi wyrażenia, które będzie podstawiane w jego miejscu w fazie poprzedzającej kompilację (preprocessing) Pozwala to np. na zdefiniowanie pewnych symboli np: #define PI 3.14159 definiuje symbol PI. We wszystkich miejscach programu gdzie ten symbol występuje, w trakcie kompilacji zostanie podstawiona odpowiadająca mu wartość. dobrym zwyczajem jest umieszczanie makroinstrukcji na początku pliku, lub w plikach nagłówkowych Makroinstrukcje nie muszą być stałe: #define d2r(kat) kat*pi/180.0 Użycie: float kat_stopnie=15.0; float x=sin(kat_stopnie*pi/180.0) lub: float x=sin(d2r(kat_stopnie))
Makroinstrukcje dyrektywa #define pozwala na przypisanie pewnemu identyfikatorowi wyrażenia, które będzie podstawiane w jego miejscu w fazie poprzedzającej kompilację (preprocessing) Pozwala to np. na zdefiniowanie pewnych symboli np: #define PI 3.14159 definiuje symbol PI. We wszystkich miejscach programu gdzie ten symbol występuje, w trakcie kompilacji zostanie podstawiona odpowiadająca mu wartość. dobrym zwyczajem jest umieszczanie makroinstrukcji na początku pliku, lub w plikach nagłówkowych Makroinstrukcje nie muszą być stałe: #define d2r(kat) kat*pi/180.0 Użycie: float kat_stopnie=15.0; float x=sin(kat_stopnie*pi/180.0) lub: float x=sin(d2r(kat_stopnie))
Makroinstrukcje cd.. Tworzenie literałów napisowych #define sciezka(usr,plik) /home/ #usr /Documents/ #plik Użycie: char MojPlik[]=sciezka(piotr,dokument.txt) Po kompilacji zmianna MojPlik będzie zawierala: /home/piotr/documents/dokument.txt Łączenie: #define połacz(nr) zmiena_ ##nr Użycie: int zmienna_1,zmienna_2,zmienna_calkowita; float zmienna_rzeczywista; polacz(1)=15; polacz(rzeczywista)=polacz(1);