background image

Język C/C++

Typy, stałe, zmienne, tablice

background image

Typy zmiennych 

Języki C dostarczają dwa rodzaje typów: 

 typy podstawowe,

 typy pochodne, wyprowadzane z typów 

podstawowych za pomocą operatorów deklaracji i 

mechanizmu deklarownia struktury

Typ danej określa jakie operacje mogą być 

wykonywane na danej danego typu i jak te 

operacje są intrerpretowane

Z każdą daną związany jest typ określony:

 jawnie (w deklaracji/definicji), 
poprzez użycie literału (napisu z którego 

ten typ wynika)

background image

Typy podstawowe

(nazwy są słowami kluczowymi)

Typami podstawowymi są:

char 

int

do reprezentownia zmiennych całkowitych różnych rozmiarów,

float

double

do reprezentownia zmiennych zmiennopozycyjnych 
Modyfikatory typu  unsigned / signed (domniemany) short / 

long do zmiany dokładności i znakowości danych 

(np. unsigned long int to całkowita, 4 bajtowa, zakres od 0 –do  

ok.4 mld)

CHAR jest LICZBĄ

background image

Typy 

(kombinacje signed/unsigned; 
short/long; 
nazw int, char, float, double)

char (ze znakiem)  

-  1 bajt

-128 do 127

unsigned char 

-  1 bajt

0 do 255

unsigned short

-  2 bajt

0 do 65535

signed short   

-  2 bajty

-32768 do 32767

 

unsigned int

-  2 bajty

0 do 65535

signed int             

-  2 bajty      -32768 do 32767

unsigned long int -  4 bajty

0 do 4294967295

signed long int   -  4 bajty

-2147483648 do 2147483647

float   

-  4 bajty      3.4 E- 38  do 3.4e+38

double   

-  8 bajtów    1.7 E-308 do 1.7 E+308

long double

- 10 bajtów   3.4 E-4932 do1.1E+4932 

Gdy brak nazwy – to domyślnie jest int
Przy wyborze typu należy pamiętać, że za lepszą dokładność płaci się 
większymi żądaniami zasobowymi, a powyższa elastyczność ma różnice 
implementacyjne

background image

Standard języka zapewnia

signed char, unsigned char, char – to różne typy, 
choć zajmują tyle samo miejsca w pamięci

1=sizeof(char)<=sizeof(short)<=sizeof(int)<=size
of(long)

sizeof(float)<=sizeof(double)<=sizeof(long 
double)

sizeof(T)=sizeof(signed T)=sizeof(unsigned T)
gdzie T – typ char, short, int, long

background image

Literały (stałe)

W programach często posługujemy się 
stałymi. Możemy używać:

stałych całkowitych (np. 15)

- stałych zmiennopozycyjnych  (np. –1.3E-2)

- stałych znakowych (np. ‘A’)

- literałów napisowych (np. ”Ala ma kota”)

W większości implementacji brak 
logicznych

background image

Stałe całkowite

Dziesiętne (bez znaków wiodących) np.:

15, -100

Ósemkowe (jeśli napis zaczniemy od cyfry 0)

014 to 1*8

1

+4*8

0

=12

10

Szesnastkowe (jeśli zapis zaczniemy od 0x/0X)

z cyframi a-f lub A-F (10-15)

0xA1 to 10*16

1

+1*16

0

=17

10

Stałe całkowite traktowane są jak int, chyba, 

że trzeba traktować je jako long – wtedy 

dopisujemy (przyrostkowo) l/L np. 200L

background image

Stałe zmiennoprzecinkowe

Zapis klasyczny (z kropką), np. 8.22 3.  -.6

Notacja naukowa z wykładnikiem
8e2  (to 800)     -6.8E-5  (to -0,000068)

Część całkowitą i ułamkową można pominąć, ale 
nie obie naraz.

Stałe są traktowane jako double, chyba że 
musimy ustalić rozmiar jawnie - używamy 
przyrostka f/F lub l/L

Jak widać tutaj nie rozróżnia się wielkości liter!!!

background image

Stałe znakowe

Ujmujemy znaki w symbole apostrofu!!!
‘a’   ‘7’   (cyfra 7 – nie liczba 7)

Podajemy kod znaku ósemkowo lub 
szesnastkowo (ale też w apostrofach)
‘\x6B’ to mała litera k  (kod 107)

‘\061’ to znak cyfry 1 (kod 49)

background image

Są jednak znaki, których nie można bezpośrednio 
umieścić między apostrofami. Służą one do 
sterowania wypisywanym tekstem. Są to znaki nie 
mające reprezentacji graficznej

'\b' - cofacz(Bsp )

'\v' - tabulator pionowy

'\f' - nowa strona

'\a' - sygnał alarmowy

'\n' - nowa linia -NL(LF)

'\r' - powrót karetki

'\t' - tabulator poziomy 

'\\' backslash '\' ' - apostrof

'\" '  - cudzysłów

'\?' = pytajnik.

 '\0' - NULL specjalny znak o kodzie 0

‘\0oo’

-  ASCII ósemkowo (oktalna)    

‘\xhh’

-  ASCII szesnastkowo 

(heksadecymalna)

background image

Stałe tekstowe (stringi)

Ciągi znaków ujęte w cudzysłów

Przechowywane są w pamięci jako ciąg znaków zakończony 

znakiem o kodzie 0(zero) - NULL, dlatego jednoznakowy 

string ma długość 2 char’y (jeden na znak i drugi na NULL)

Ze względu na szczególny charakter znaków w rodzaju ” ‘ \ 

i podobnych, musimy je w stringu poprzedzić 

backslashem \

”Witamy w świecie \”C\\C++\””

co daje napis : Witamy w świecie ”C\C++”

Jeśli w napisie umieścimy znak zero \0 to tam się napis 

skończy (na ogół)

Jeśli napis jest długi i nie mieści się w jednej linii programu, 

kończymy cudzysłowem w jednej i zaczynamy od 

cudzysłowu w kolejnej linii. Kompilator je złączy.

background image

Deklaracje stałych (nie-
literałów)

Za pomocą słowa kluczowego const np.:

const float pi=3.14;

Każda próba przypisania stałej pi 

wartości (nawet 3.14) jest traktowana 

jako błąd

Za pomocą dyrektywy preprocesora 

#define np.:

#define pi 3.14

Przed analizą tekstu przez kompilator 

następuje automatyczna zamiana tokenów pi 

na stałą liczbową 3.14

background image

Typ void

Specyfikuje pusty zbiór wartości

Nie występuje jako typ podstawowy (nie 
może być zmiennej/stałej tego typu) 

Jest typem funkcji, która nie przekazuje 
żadnej wartości

Jest wskaźnikiem do obiektu nieznanego 
typu
(coś w rodzaju Pointer pascala)

background image

To były typy proste – a 
złożone?

Istnieje nieskończenie wiele typów 

pochodnych konstruowanych z typów 

podstawowych (tablice, funkcje, wskaźniki, 

stałe <const>, klasy, struktury, unie)

Można je wyprowadzić z prostych, za pomocą 

operatorów:

Indeksowania []

Wskazania *

Deklarowania funkcji ()

Referencji &

Indeksowanie i funkcje są przyrostkowe, 

wskazanie i referencja przedrostkowe.

background image

Deklaracje zmiennych

Postać deklaracji:

typ

 

lista

;

Gdzie:

lista

 to oddzielone przecinkami:

nazwa zmiennej

nazwa zmiennej=stała

nazwa tablicy[liczba elementów]

nazwa tablicy[liczba elementów]={lista 

stałych}

nazwa tablicy[ ]={lista stałych}

*nazwa zmiennej adresowej

Należy pamiętać, że w C/C++ jak w każdym języku o znaczeniu praktycznym, 
użycie zmiennej musi być poprzedzone jej deklaracją

background image

Tablice

To dane jednego typu (niekoniecznie 
prostego) zajmujące ciągły (przyległy) obszar 
pamięci (wektor pamięci)

Lokalizacja pojedynczego (atomowego) 
składnika tablicy wymaga podanie jej nazwy 
oraz indeksu (indeksów) ujętego (dla każdego 
wymiaru) w operator indeksowania []

Rozmiar/rozmiary tablicy muszą być znane w 
trakcie kompilacji (dynamiczna alokacja 
pamięci to praca ze wskaźnikami – później)

background image

Deklaracja tablicy 
(jednowymiarowej)

Typ nazwa[liczba elementów]

indeks może zmieniać się od zero do liczba 

elementów-1.

Uwaga program nie kontroluje (na ogół) 

przekroczenia zakresu, np. 

float boki[3];

deklaruje tablicę zmiennoprzecinkowych : 

boki[0], boki[1], boki[2]

przypisanie boki[3]=5; spowoduje zniszczenie 

(wstawienie float 5.0) w komórki pamięci 

leżące bezpośrednio za tablicą boki

background image

Tablica jednowymiarowa cd

Nadanie wartości elementom tablicy może 
odbywać się:

Programowo np. boki[2]=7.e-3;

Podczas deklaracji np.
float boki[3]={3,7.5,20e-2};
gdy wymienionych stałych jest mniej, reszta 
uzupełniana jest zerami, np.
float boki[3]={3}; //boki

0

=3, boki

1,2

=0

Możliwa jest kombinacja bez podania rozmiaru, jeśli 
podana jest lista stałych – rozmiar jest taki jak długość 
listy, np.
int a[]={1,2,3,4,5,0,0}; // tak jak int a[7]={1,2,3,4,5};

background image

Tablice wielowymiarowe

To tablice tablic, operator indeksowania działa na 
jednym indeksie 

int tab[2][3]; // macierz  2 wierszex3 kolumny

Nadajemy wartości jak poprzednio, pamiętając, że:

Odwołanie w programie – każdy indeks w nowym 
nawiasie 

Nadanie wartości w deklaracji - najszybciej zmienia się 
ostatni indeks

Niepełna lista stałych generuje brakujące zera

Kombinacja z brakującym rozmiarem jest 
dozwolona tylko dla pierwszego indeksu

background image

Uwagi o deklaracji 
zmiennych

C/C++ są elastyczne, jeśli chodzi o 
miejsce deklaracji (nie jak w Pascalu, 
gdzie sekcje deklaracji i instrukcji były 
rozdzielone)

Istnieją różnice implementacyjne 
dotyczące zakresu ważności deklaracji 
w wewnętrznych blokach (albo od 
deklaracji do końca funkcji, albo tylko 
wewnątrz bloku)

background image

Program o algorytmie liniowym 
to nieporozumienie (albo 
przykład)

Wykonaniem instrukcji trzeba sterować

Instrukcją wyboru

Instrukcją wielokrotnego wyboru

Instrukcjami iteracyjnymi

Rekurencją 

Pozostałymi instrukcjami sterującymi

Prawie zawsze za wyborem stoją 
uwarunkowania logiczne

background image

W języku C/C++ brak typu 
logicznego

Decyduje wartość wyrażenia dowolnego 
typu

Wartość 0 (zero) odpowiada fałszowi 

Wartość niezerowa odpowiada prawdzie

Operacje relacji i operacje logiczne dają 
wynikową wartość zero gdy wynikiem 
jest fałsz i różną od zera gdy wynikiem 
jest prawda

background image

Instrukcja if

Składnia instrukcji if

if (wyrażenie decydujące)instrukcja1;

Składnia instrukcji if else

if (wyrażenie decydujące)instrukcja1;

 else instrukcja2;

Instrukcja1 zostanie wykonana gdy wyrażenie będzie niezerowe 

a instrukcja2 tylko w przypadku gdy wystąpiła konstrukcja z else 

i wyrażenie ma wartość zero

Gdy instrukcja1 lub/i instrukcja2 są złożone, należy użyć 

nawiasów { }, uwarunkowane jest wówczas wykonanie 

wszystkich instrukcji wewnątrz nawiasów. Użycie nawiasów { } 

jest manierą tzw. „prawdziwych Cecowców” nawet gdy 

uwarunkowana jest tylko jedna instrukcja 

background image

Jeszcze o zagnieżdżonych if 
else

Instrukcja else wiązana jest z ostatnią if, 
która nie ma else

Do zmiany tego przyporządkowania 
używamy { }

if(a>0) if (b<0) printf(”a>0 i b<0”);else 
print(”a>0 i b>=0”);

if(a>0){if (b<0) printf(”a>0 i b<0”);}else 
print(”a<=0”);

background image

Namiastka if else - ?:

W C/C++ występuje unikalna konstrukcja 

szacowania wartości, która w prostych 

przypadkach alternatywego wyznaczania wartości 

zastępuje if else. Ma postać:

(warunek)?wyrażenie1:wyrażenie2

wynikiem jest wartość wyrażenia1 gdy warunek 

jest prawdziwy (różny od zera) lub wartość 

wyrażenia2 gdy warunek jest fałszywy (równy 

zeru)

Uwaga: ta konstrukcja (zwana operatorem 

pytajnikowym) zastępuje if else tylko w 

określonych przypadkach. if else służy bowiem do 

warunkowania wykonania instrukcji (a nie tylko 

pojedynczego podstawienia) 

background image

Wybór wielokrotny

W przypadku, gdy od wartości jednego 

wyrażenia (o typie porządkowym) zależy 

wybór instrukcji używa się zdania switch 

o postaci:

switch (wyrażenie desygnujące)

case wyrażenie stałe1:instrukcje1;

default : instrukcje_w_przeciwnym_razie:

background image

Uwagi o switch

Wyrażeń stałych nie można grupować, tworzyć 
z nich listy, okrojeń itp. – przed każdą 
wartością musi stać słowo case a po niej 
dwukropek

Równość wyrażenia stałego z desygnującym to 
”punkt wejścia” do listy instrukcji. Od tego 
miejsca do końca switch wykonywane są 
kolejne instrukcje (także z innymi case). Do 
przerwania służy instrukcja break

Manierą jest ujmowanie instrukcji (po 
dwukropku) w klamry

background image

Instrukcje iteracyjne

Wykonywanie pętli programowych to 

wykorzystanie naturalnych zalet komputera. 

Jak wszystkie praktyczne języki, C/C++ 

mają kilka konstrukcji iteracyjnych: 

while, do i for

Zawsze należy dbać o poprawne 

skonstruowanie warunków zakończenia pętli 

– powszechność pętli w algorytmach to 

także powszechność zawieszania się 

programów w wyniku złej konstrukcji końca 

pętli 

background image

Instrukcja while 

 Instrukcja while

Składnia tej instrukcji jest następująca:

while  (wyrażenie) instrukcja;

W pętli while wykonanie instrukcji 

powtarza się tak długo, jak długo wartość 
wyrażenia jest różna od zera (prawdziwa). 
Sprawdzenia tego warunku dokonuje się 
przed każdym wykonaniem instrukcji.

background image

Przykłady z while

#include<stdio.h>
void main()
{

char znak;
znak = getchar();     // pobierz znak, <enter>
while(znak != ‘t’) 

       {                               // blok instrukcji

   putchar(znak);       //wypisz znak      

       znak = getchar();
        }

#include<stdio.h>
void main()
{

char znak;
while ((znak = getchar())!= ‘t’) 

       {                             // blok instrukcji

   putchar(ch);             

        }

Pętle są częstym (i wdzięcznym) polem „manieryzmu” skutecznie 
zmniejszającego czytelność tekstu programu 

background image

Instrukcja do..while

Instrukcja do...while

Składnia instrukcji jest następująca:

do  instrukcja  while  wyrażenie;

W pętli do...while wykonanie instrukcji 

powtarza się tak długo, jak długo wartość 

wyrażenia jest różna od zera (prawdziwa). 

Sprawdzenia tego dokonuje się po każdym 

wykonaniu instrukcji, dlatego pętla wykona się 

zawsze conajmniej raz; to różni ją od pętli while 

która może nie wykonać się wcale. 

Od znanej z Pascala repeat..until różni ją 

przeciwne uwarunkowanie kontynuacji

background image

Porównanie while z do while

#include<stdio.h>
#include<conio.h>
void main()
{
 int i=0;  float licznik=0;
 clrscr(); 
 while(i) 
       {    // blok instrukcji

    printf (”i=%d\n”,i);

        i--;
        licznik++;
        }
printf (”po pętli licznik=%f”,licznik);

Wartość licznika 0

#include<stdio.h>
#include<conio.h>
void main()
{
 int i=0;  float licznik=0;
 clrscr(); 
 do
   {    // blok instrukcji
    printf (”i=%d\n”,i);
    i = i-1; 
    licznik++;
    } while (i);
printf(”po pętli licznik=%f”,licznik);

Wartość licznika 65536 (???)

background image

Potężna pętla for

 Instrukcja for

Składnia pętli for ma postać:

for  (inst_ini;   wyr_war;   wyr_krok)  instrukcja;

inst _ini  wykorzystywana jest zwykle do deklarowania 

(C++) 

i inicjowania początkowych wartości zmiennych na 

potrzeby pętli,

wyr_war  wyrażenie warunkowe wykorzystywane jest do 

testowania warunków wykonywania pętli,

wyr_krok określa zmianę stanu pętli i używane jest 

zwykle do zwiększania lub zmniejszania zmiennej 

indeksującej pętlę.

Wszystkie składniki w nawiasie są opcjonalne, jednak 

muszą być zachowane średniki je oddzielające 

background image

Dalszy ciąg for

Praca pętli for wykonywana jest według 
nastepującego algorytmu:

1. Wykonują się instrukcje inicjujące pętlę inst_inic.

2. Obliczana jest wartość wyrażenia wyr_war. Jeśli 

wartość tego wyrażenia jest równa zero, praca  pętli 
jest przerywana.

3. Jeśli powyżej okazało się, że wyr_war jest != 0

wtedy wykonywana jest instrukcja

4. Po wykonaniu instrukcji, obliczana jest wartość 

wyrażenia wyr_krok. 

Powtarzany jest punkt 2. 

background image

Jeszcze o pętlach

Pętlami tzw. nieskończonymi są 

pętle:

for (;;) 
{
//instrukcje
}

while( 1)

 

{                                                  
// instrukcje                                     
}

do
{
//instrukcje
 } while (1);

background image

Pozostałe konstrukcje 
sterujące

Do tej grupy instrukcji należą:

break;

continue;

return wyrażenie;

goto etykieta;

background image

pozostałe sterujące

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. 

background image

Pozostałe sterujące

continue -Instrukcja ta może być 
używana tylko w pętli for, while, 
do...while.
 Powoduje przeniesienie 
sterowania na koniec pętli, pomijając 
ciąg instrukcji do końca ciała pętli – 
inaczej przechodzi do następnego 
„obiegu” pętli. 

background image

Pozostałe sterujące

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). 

background image

Pozostałe sterujące

 Instrukcja goto
Instrukcja ta, wykonuje bezwarunkowe 
przeniesienie sterowania do miejsca 
gdzie występuje dana etykieta. Etykieta 
musi być umieszczona w tej samej 
funkcji. Etykietą jest identyfikator po 
którym występuje : (dwukropek)

background image

Często używane w pętlach

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ą 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

Przykład :  

i=10; x=++i; //daje i=11 oraz x=11
i=10; x=i++; // daje i=11 oraz x=10

Pytanie (do domu) co daje: i=1;j=3; a=i+++j; 


Document Outline