AiP wyklad01


Algorytmika i Programowanie.
Podstawy języka C++ ze
wstępem do programowania
dla in\ynierów
Zakład Zastosowań Informatyki
w In\ynierii Lądowej
Wydział In\ynierii Lądowej
Politechnika Warszawska
Sławomir Czarnecki
Cel kursu:
" nauczenie podstaw programowania
strukturalnego w języku C++
" zastosowanie wybranych algorytmów
w rozwiązywaniu prostych problemów
in\ynierskich
Nie jest zakładana znajomość
jakiegokolwiek języka programowania !
Literatura
1. Ivor Horton: Beginning Visual C++ 6.0 , Wrox Press C++ Tutorial,
1998 Wrox Press Ltd, http://www.wrox.com/
2. Jeri R. Hanly: Essential C++ for Engineers and Scientists,
1997 Addison-Wesley Longman, Inc.
3. Jan Bielecki: ANSI C++,
1997 Intersofland, Warszawa
4. Bruce Eckel: Thinking in C++, Vol. 1 , 2
2000 Pearson Education, Inc.
5. Jerzy Grębosz: Symfonia C++. Programowanie w języku C++
orientowane obiektowo, Tom I, II, III
1994 Oficyna Kallimach, Kraków (pierwsze wydanie).
Ogólny Schemat Blokowy Komputera
Central Processing Unit
Secondary storage
(CPU)
Arithmetic/Logic
Control Unit (CU)
Unit (ALU)
Output devices
Input devices
Memory
Central Processing Unit (CPU)  procesor
Arithmetic/Logic Unit (ALU)  blok arytmetyczno-logiczny
Control Unit (CU)  dekoder kodu rozkazowego
Input/Output devices  urządzenia wejścia-wyjścia
Memory  pamięć operacyjna
Secondary storage  inne dodatkowe rodzaje pamięci
Central Processing Unit
Secondary storage
(CPU)
Arithmetic/Logic
Control Unit (CU)
Unit (ALU)
Output devices
Input devices
Memory
" CPU odczytuje kolejne rozkazy, które następnie musi rozpoznać -
dekodować.
" Po zdekodowaniu rozkazu, w zale\ności od treści tego rozkazu,
procesor podejmuje odpowiednią akcję.
" Akcja ta polega na wykonaniu odpowiedniej operacji.
Central Processing Unit
Secondary storage
(CPU)
Arithmetic/Logic
Control Unit (CU)
Unit (ALU)
Output devices
Input devices
Memory
" Pamięć komputera (jako model) mo\na porównać do zbioru
ponumerowanych skrzynek pocztowych.
" Dwa istotne atrybuty są bezpośrednio związane z pamięcią:
adres i zawartość.
" Ka\da komórka pamięci nigdy nie jest pusta - zawsze jest w niej
zapisana jakaś informacja. Wprowadzenie nowej wartości zawsze
prowadzi do zniszczenia, a tym samym utraty starej zawartości.
" Często u\ywany jest termin pamięć RAM (Random-Access Memory)
zamiast pamięć operacyjna, poniewa\ dostęp do ka\dej komórki jest
mo\liwy poprzez podanie jej adresu w dowolnej kolejności.
" Podobnie jak CPU, pamięć RAM wymaga stałego napięcia, bowiem
w przypadku jego braku następuje utrata aktualnych danych.
" Wszystkie dane są przechowywane w pamięci w postaci cyfrowej,
jako liczby w systemie binarnym  zło\onym z cyfr 0 i 1.
00000101 0000000001000001
ADRES ZAWARTOSC
00000101 =1 22 + 0 21 +1 20 =
5 0000000001000001 = ... = 65
" Najmniejszą jednostką informacji, która mo\e być przechowywana w
pamięci jest pojedyńcza cyfra binarna zwana bitem.
" Bajt (typowo 8 bitów) jest jednostką informacji, która umo\liwia
przechowywanie danej zwanej pojedyńczym znakiem.
Obszar pamieci zwany
stosem (ang. stack)
Obszar pamieci zwany
sterta (ang. heap)
Model wyobra\eniowy pamięci jako uszeregowanego zbioru komórek
Adres
Zawartosc
Central Processing Unit
Secondary storage
(CPU)
Arithmetic/Logic
Control Unit (CU)
Unit (ALU)
Output devices
Input devices
Memory
" Urządzenia wyjścia/wejścia umo\liwiają komunikację pomiędzy
 stworzeniami nie-cyfrowymi (takimi jak na przykład ludzie)
a komputerem.
" Najbardziej powszechnymi urządzeniami wejścia (input devices) są
klawiatura, myszka, skaner, TrackBall, TouchPad, TouchScreen
u\ywane łącznie z ikonami tzw. graficznego interfejsu u\ytkownika.
" Najbardziej powszechnymi urządzeniami wyjścia (output devices) są
monitor, drukarka, głośniki.
Central Processing Unit
Secondary storage
(CPU)
Arithmetic/Logic
Control Unit (CU)
Unit (ALU)
Output devices
Input devices
Memory
Oprócz pamięci operacyjnej RAM, istnieją jeszcze inne rodzaje pamięci
głównie z dwóch powodów:
1. istnieje potrzeba przechowywania informacji, niezale\nie od tego
czy urządzenie jest pod napięciem czy te\ nie (np. w momencie
wyłączenia komputera z sieci lub jego awarii)
2. z reguły, ilość przetwarzanych informacji przewy\sza pojemność
dostępnej (i dro\szej) pamięci operacyjnej.
Większość komputerów osobistych u\ywa wszelkiego rodzaju
alternatywnych nośników informacji w postaci przenośnych i
nieprzenośnych dysków.
Warto znać podstawowe terminy związane z definiowaniem
pojemności u\ywanych pamięci:
Termin Skrót Równowa\ne Porównanie
z potęgą 10
Języki Komputerowe
" Tworzenie nowego oprogramowania wymaga napisania listy instrukcji
(programu), które mogą być następnie przez komputer wykonane.
" Programiści rzadko piszą programy w języku maszynowym, który
 rozumieją komputery, poniewa\ ka\dy taki język musiałby u\ywać
wyłącznie systemu binarnego zło\onego z zer i jedynek.
" Inną, bardzo powa\ną wadą pisania programów w języku
maszynowym jest fakt zale\ności tych języków od typu procesora, a
zatem pisanie uniwersalnych programów komputerowych
przeznaczonych do uruchamiania na ró\nych typach komputerów
nie byłoby praktycznie mo\liwe.
" Stąd, pisanie programów komputerowych, które byłyby niezale\ne
od CPU, spowodowało powstanie tzw. języków wysokiego poziomu
(high-level languages), które najczęściej wykorzystują wyra\enia
algebraiczne stosowane w matematyce wraz z symbolami u\ywanymi
w języku angielskim.
Na przykład, instrukcja w języku wysokiego poziomu
a = a + b;
oznacza dodaj wartości zmiennych a i b, a następnie przechowaj
wynik w zmiennej a (zastępując starą wartość a nową wartością a+b).
Obecnie u\ywanych jest bardzo du\o języków programowania
wysokiego poziomu. Poni\ej wymieniono tylko kilka bardziej
popularnych języków, gdzie obok (hasłowo) podano dziedzinę,
w której są najczęściej wykorzystywane:
FORTRAN  nauka i technika
COBOL  biznes
Lisp  sztuczna inteligencja
C  programowanie systemów operacyjnych
Prolog  sztuczna inteligencja
Ada  programowanie współbie\ne w czasie rzeczywistym
Smalltalk  graficzny interfejs u\ytkownika
C++  programowanie zorientowane obiektowo i/lub
strukturalnie, nauka i technika :&
Java  tylko programowanie zorientowane obiektowo,
rzeczywista niezale\ność od CPU,
programowanie współbie\ne,
programowanie sieciowe :&:&
" Języki wysokiego poziomu nie są jednak zrozumiałe przez
 komputery .
" A zatem, aby kod programu napisanego w języku wysokiego poziomu
mógł być wykonany, musi być przedtem przetłumaczony na docelowy
język maszynowy komputera (procesora).
" Program, który tłumaczy oba te języki nazywa się kompilator.
" Danymi wejściowymi dla kompilatora jest plik zródłowy zawierający
tekst programu napisanego w języku wysokiego poziomu.
" Programista tworzy ten plik u\ywając zwykłego procesora tekstu.
" Format tego pliku jest typu tekstowego, co oznacza, \e jest on zbiorem
znaków.
" Kompilator  skanuje ten plik, sprawdzając czy jest on zgodny z
regułami gramatycznym zdefiniowanymi w danym języku wysokiego
poziomu.
" Jeśli program jest syntaktycznie poprawny, kompilator tłumaczy go na
język maszynowy i zapisuje w formacie binarnego pliku obiektowego
(object file).
" Jeśli natomiast w pliku zródłowym są błędy gramatyczne, to wtedy
kompilator wskazuje miejsca w kodzie programu, w którym te błędy
znalazł i z reguły podaje, krótki opis błędu (nie zawsze w pełni
adekwatny).
" W tej sytuacji, binarny plik obiektowy nie jest oczywiście tworzony.
" Programista musi wtedy poprawić kod programu we wskazanych
miejscach pliku tekstowego i ponownie uruchomić kompilator.
" Pomimo tego, \e binarny plik obiektowy zawiera instrukcje
maszynowe zrozumiałe przez procesor, nie wystarcza on z reguły do
uruchomienia programu, poniewa\, nie wszystkie polecenia są na tym
etapie kompletne.
" Języki wysokiego poziomu, dostarczają programistom wiele ró\nych
gotowych instrukcji, które są bardzo często u\ywane i bez których
nie byłoby mo\liwe efektywne pisanie programów.
" Prawie wszystkie języki wysokiego poziomu oferują co najmniej
wykorzystanie tzw. gotowych funkcji, które są niczym innym jak
skompilowanymi kodami, które zostały napisane wcześniej przez
innych programistów i które rezydują w innych binarnych plikach
obiektowych dostępnych dla programisty.
" Program, który nazywamy linkerem, łączy wszystkie potrzebne
obiektowe pliki binarne w jeden plik, który jest dopiero kompletnym
programem w języku maszynowym zwanym plikiem *.exe, gotowym
do uruchomienia.
" Jak długo plik  exe jest przechowywany na dysku, nie  robi
niczego.
" Uruchomienie programu polega na skopiowaniu wszystkich instrukcji
z pliku  exe do pamięci operacyjnej, a następnie wymuszeniu na
procesorze wykonanie pierwszej instrukcji.
" Większość języków wysokiego poziomu jest sprzedawana w tzw.
zintegrowanym pakiecie środowiskowym,
(Integrated Development Environment  IDE),
w którym edycja,kompilacja, linkowanie i uruchamianie programu
jest dla wygody programisty mo\liwa do przeprowadzenia w
jednym oknie przy dość znacznie rozbudowanym menu.
Edycja-Kompilacja-Linkowanie-Uruchomienie
Edytor Testu
Tekstowy
do tworzenia Dane
Wyniki
plik
i poprawiania wejsciowe
zrodlowy
programu
Tlumaczenie
programu przez
Porazka
Sukces
kompilator na
jezyk
maszynowy
Uruchomienie
Informacja o Binarny plik
wykonywalnego
bledach obiektowy
pliku binarnego
Laczenie
binarnych plikow
Inne binarne Binarny plik
obiektowych
pliki obiektowe wykonywalny (*.exe)
przez program
linkujacy
" Aplikacje konsolowe jako programy skompilowane w środowisku
Visual C++ są tworzone w MS-DOS-owych plikach tekstowych.
" Ka\dy program w C++ składa się z jednej lub większej liczby funkcji
" Ka\dy program w C++ przeznaczony do uruchomienia w środowisku
DOS, zawiera funkcję main().
" Funkcja jest blokiem instrukcji identyfikowanym przez nazwę
(funkcji).
" Schemat typowego programu DOS-owskiego pokazano na kolejnym
slajdzie.
" Ilustracja
wykonania
programu, który
zaczyna się od
wywołania funkcji
main().
" W funkcji main(),
wykonanie
programu
przejmuje funkcja
input_names(),
która kończy
wykonanie w
miejscu
pokazanym na
rysunku.
" Podobnie przebiega dalej wykonanie programu
dla funkcji sort_names() i output_names().
" Oczywiście ka\dy program DOS-owski ma inną strukturę wywołań
funkcji, ale ka\dy program DOS-owski zaczyna wykonanie od
wywołania funkcji main().
" Podstawową zaletą podziału wszystkich instrukcji programu na tzw.
funkcje jest przede wszystkim znaczne uproszczenie czytelności
kodu, co ma szczególne znaczenie w przypadku lokalizacji
błędów.
" Ponadto ka\da funkcja mo\e być tworzona a pózniej wykorzystana
przez ró\nych programistów w innych programach.
" Gotowe funkcje mogą zostać zebrane w tzw. biblioteki i dołączane
do naszych własnych programów. Fakt ten ma niezwykle istotne
znaczenie w rozwijaniu oprogramowania i korzystania z pracy innych
programistów.
" Na bardzo prostym przykładzie prześledzimy proces powstawania
programu przeznaczonego do uruchamiania w środowisku DOS.
" Zacznijmy od utworzenia nowego projektu, którego typ zostanie
wybrany z listy zamieszczonej w oknie Projects po kliknięciu na
opcję New... w menu File.
" Utworzyliśmy nowy plik tekstowy MainFunctionFile.cpp, w którym
mo\emy pisać kod naszego pierwszego programu w projekcie
FirstProgramInCpp.
" Pierwszy przykład ma na celu jedynie ilustrację sposobu u\ywania
podstawowych instrukcji C++.
" W naszym pierwszym programie, poka\emy sposób w jaki działają:
podstawowy operator wejścia >> i operator wyjścia <<.
" Typową operację wejścia mo\na przedstawić za pomocą instrukcji:
operator>>(cin,Fix);
a typową operację wyjścia za pomocą instrukcji:
operator<<(cout,Fix);
" operator>> i operator<< w podanych nawiasach są nazwami funkcji
wejścia/wejścia.
" cin i cout są nazwami obiektów reprezentujących wejściowy i
wyjściowy strumień danych (domyślnie pochodzących z klawiatury i
wysyłanych na ekran) a Fix jest nazwą zmiennej.
" operator>> pobiera jeden lub więcej znaków ze strumienia wejścia
w celu ich przechowania, zakładając, \e wartości numeryczne będą
oddzielone jednym lub większą liczbą znaków spacji, tabulacji
lub nowej linii.
" operator>> pomija znaki spacji lub nowej linii w trakcie poszukiwania
wartości numerycznych i próbuje interpretować ka\dą pierwszą grupę
kolejnych  niepustych znaków jako liczbę.
" kiedy oczekiwaną wartością jest zwykły znak, operator>> pobiera
pierwszy  niepusty napotkany znak.
" operator<< ma zadanie umieszczenia znaków w docelowym
strumieniu wyjściowym, do którego są przesyłane dane.
UWAGA !!!
" Istnieje mo\liwość u\ywania skróconego zapisu:
cin>>Fix;
cout<(zamiast: operator>>(cin,Fix) i operator<<(cout,Fix))
poniewa\ nazwy funkcji operator>>, operator<< zaczynają się
od słowa  operator .
" Ponadto rezultat operacji
cout<identyfikuje zmienną cout, więc wyra\enie
cout<(oraz mu podobne) mo\na traktować jako zło\enie operacji
cout<cout< " Sekwencja instrukcji:
wprowadzenie z klawiatury liczby całkowitej do zmiennej Fix
podniesienie tej liczby do drugiej potęgi (Fix*Fix)
wyprowadzenie wyniku na ekran
ma postać:
cin>>Fix;
cout<jednak ta sekwencja nie jest programem, poniewa\:
" ka\dy identyfikator programu musi być zadeklarowany,
" deklaracja identyfikatora musi poprzedzać jego pierwsze u\ycie,
" ka\dy program musi zawierać funkcję main.
" Dwie pierwsze linijki kodu w C++
// MainFunctionFile.cpp
są komentarzami.
// Our first program in C++
" Komentarze są bardzo wa\ną
częścią ka\dego programu, lecz nie
#include
są one kodem wykonywalnym  są
using namespace std;
przeznaczone wyłącznie dla
programisty lub innej osoby
int main()
czytającej program.
{
" Wszystkie komentarze są
ignorowane przez kompilator.
int Fix;
" W ka\dej linii kodu, dwa
cin>>Fix;
następujące po sobie znaki //,
które nie są zawarte w tzw.
cout<łańcuchu znaków oznaczają,
return 0;
\e reszta znaków w tej linii jest
komentarzem.
}
/* MainFunctionFile.cpp " Mo\liwe jest u\ywanie alternatywnej
formy komentarza ograniczonego
Our first program in C++
przez znaki /* i */.
*/ " Forma /*...*/ definiuje  wszystko co
jest zawarte  pomiędzy znakami
#include
/*...*/ jako komentarz i mo\e być
using namespace std; rozciągnięta na dowolną liczbę linii
kodu.
int main()
{
int Fix;
cin>>Fix;
cout<return 0;
}
" Po komentarzach, mamy tzw.
//MainFunctionFile.cpp
dyrektywę #include:
//Our first program in C++
#include , która narzuca
kompilatorowi umieszczenie
#include
(wstawienie) w tym miejscu deklaracji
using namespace std;
funkcji bibliotecznych, z których
ewentualnie będzie mógł on korzystać
w czasie kompilacji i dzięki temu
int main()
sprawdzać czy posługujemy się tymi
funkcjami poprawnie.
{
" Brak w naszym programie tej
int Fix;
dyrektywy spowodowałby błędy
kompilacji, poniewa\ w programie
cin>>Fix;
wykorzystywane są funkcje
cout<wyjścia/wejścia, których deklaracje
są właśnie zawarte w bibliotece
return 0;
.
}
" Istnieje bardzo du\o innych ró\nych
//MainFunctionFile.cpp
plików  bibliotek reprezentowanych
//Our first program in C++
właśnie przez pliki nagłówkowe, które
są dostarczane razem ze środowiskiem
#include
programistycznym Visual C++ i które
using namespace std;
są niezbędne do efektywnego oraz
ekonomicznego programowania w
tym języku.
int main()
" Dyrektywa #include jest jedną z
wielu tzw. dyrektyw preprocesora.
{
" To, \e jest to dyrektywa preprocesora
int Fix;
informuje nas znak # umieszczony
przed tzw. słowem kluczowym
cin>>Fix;
include.
cout<" Kompilator Visual C++ rozpoznaje
wszystkie słowa kluczowe ju\ na
return 0;
etapie pisania kodu i podświetla
}
je (domyślnie) na niebiesko.
" Ka\da taka biblioteka jest zbiorem
//MainFunctionFile.cpp
procedur (funkcji, podprogramów),
//Our first program in C++
które zostały napisane w celu
uproszczenia pisania kodu,
#include
realizującego typowe zadania
using namespace std;
spotykane w niemal ka\dym
programie, np..:
dotyczącymi instrukcji
int main()
wyjścia/wejścia,
przeprowadzania podstawowych
{
działań matematycznych itp..
int Fix;
" Za pomocą dyrektywy preprocesora
#include będziemy w przyszłości
cin>>Fix;
mogli tak\e dołączać nasze własne
cout<pliki, które zawierać będą u\yteczne
funkcje  nadające się do
return 0;
wielokrotnego wykorzystania w
}
niejednym programie.
//MainFunctionFile.cpp
//Our first program in C++
#include
using namespace std;
Ta linijka kodu w naszym programie,
informuje kompilator, \e korzystać będziemy
z procedur, które nale\ą do tzw. biblioteki
int main()
standardowej.
Ta linijka będzie z reguły niemal zawsze
{
dodawana we wszystkich naszych programach
int Fix;
pisanych jako aplikacje konsolowe
(console application).
cin>>Fix;
cout<return 0;
}
//MainFunctionFile.cpp
" Funkcja main() w naszym przykładzie
składa się z tzw. nagłówka funkcji
//Our first program in C++
definiującego ją właśnie jako main()
#include
oraz kodu zawartego pomiędzy
pierwszym nawiasem otwierającym
using namespace std;
{
...
int main()
a korespondującym mu nawiasem
{
zamykającym
...
int Fix;
}.
cin>>Fix;
" Nawiasy te obejmują wszystkie
cout<wykonywalne instrukcje funkcji
return 0;
main(), które nazywamy ciałem
funkcji.
}
//MainFunctionFile.cpp " Zobaczymy wkrótce, \e wszystkie
funkcje składają się z nagłówka
//Our first program in C++
funkcji, który definiuje m.in.
#include nazwę funkcji i poprzedza ciało
funkcji (jej instrukcje) zawarte
using namespace std;
pomiędzy nawiasami {...}.
" Ciało funkcji mo\e nie zawierać
\adnych instrukcji i w takim
int main()
przypadku funkcja po prostu
{  nic nie robi .
int Fix;
cin>>Fix;
cout<return 0;
}
//MainFunctionFile.cpp
//Our first program in C++
#include
using namespace std;
" Ka\da instrukcja w ciele funkcji kończy
się średnikiem ; .
int main()
" Pojedyńcza instrukcja jest podstawową
{
 jednostką większego zadania , które
jest realizowane przez program.
int Fix;
cin>>Fix;
cout<return 0;
}
" Pierwsza instrukcja w programie
//MainFunctionFile.cpp
int Fix; jest instrukcją deklaracyjną i
//Our first program in C++
deklaruje zmienną Fix.
" W napisie tym słowo kluczowe int jest
#include
nazwą typu całkowitego, a Fix jest
using namespace std;
arbitralnie wybranym identyfikatorem.
" Taka instrukcja mo\e być umieszczona
zarówno w ciele jak i poza ciałem
int main()
funkcji.
" Zmienna jest nazwanym obszarem
{
w pamięci operacyjnej przydzielonym
int Fix;
do przechowywania danych
odpowiedniego typu.
cin>>Fix;
" Instrukcja wprowadzająca nazwę
cout<zmiennej nazywana jest deklaracją
zmiennej.
return 0;
" Słowo kluczowe int oznacza, \e zmienna
}
ta ma przechowywać liczby całkowite.
//MainFunctionFile.cpp " W następnej instrukcji wczytujemy
(inicjalizujemy) wartość zmiennej
//Our first program in C++
Fix u\ywając klawiatury.
#include " Instrukcja wczytania liczby
całkowitej
using namespace std;
cin>>Fix;
jest realizowana od lewej do prawej
strony.
int main()
" Wykonanie instrukcji kończy się
{ w momencie naciśnięcia klawisza
Enter po uprzednio wczytanej z
int Fix;
klawiatury i widocznej na ekranie 
cin>>Fix; wartości liczby całkowitej, którą ma
być zainicjalizowana zmienna Fix.
cout<" Po poprawnym wczytaniu, sterowanie
return 0; programu przenosi się następnej linii
kodu.
}
//MainFunctionFile.cpp " Następna instrukcja:
cout<//Our first program in C++
jest instrukcją wyjścia.
#include " Operator <<  wskazuje kierunek
przepływu danych.
using namespace std;
" Najpierw wartość kwadratu liczby Fix
zostaje wyświetlona na ekranie
Fix*Fix.
int main()
po czym wprowadzenie znaku nowej
{ linii
endl
int Fix;
powoduje pojawienie się na ekranie
cin>>Fix; kursora w nowej linii  poni\ej
wyświetlonej wartości kwadratu
cout<liczby Fix.
return 0;
}
//MainFunctionFile.cpp " Znaczenie słów cin, cout
i symboli operatorów >>, << jest
//Our first program in C++
zdefiniowane w kontekście
#include dołączonego na początku programu
pliku nagłówkowego iostream 
using namespace std;
dyrektywa #include .
" Poniewa\ cin, cout zostały w nim
zdefiniowane w kontekście
int main()
przesyłania danych przy
{ wykorzystaniu standartowych
strumieni wejścia/wyjścia
int Fix;
stowarzyszonych odpowiednio
cin>>Fix; z klawiaturą i z ekranem, zatem
nie powinniśmy u\ywać słów cin,
cout<cout do innych celów, na przykład
return 0; jako identyfikatorów własnych
zmiennych.
}
//MainFunctionFile.cpp
//Our first program in C++
#include
using namespace std;
" Ostatnia instrukcja w naszym programie,
int main()
return 0;
kończy jego wykonywanie i zwraca
{
kontrolę do systemu operacyjnego.
int Fix;
cin>>Fix;
cout<return 0;
}
" Biały znak (Whitespace) jest terminem u\ywanym w C++ jako
synonim znaku spacji, tabulacji, nowej linii czy te\ komentarza.
" Biały znak oddziela jedną część instrukcji od drugiej i umo\liwia
kompilatorowi na poprawną identyfikację gdzie jeden składnik
instrukcji kończy się a gdzie zaczyna się inny jej składnik.
" Przykładowo, w instrukcji int Fix; pomiędzy int a Fix musi być co
najmniej jeden biały znak, aby kompilator poprawnie odró\nił słowo
kluczowe int od identyfikatora zmiennej Fix.
" Zapis intFix byłby zatem w tym przypadku niepoprawny.
" Z drugiej strony, w instrukcji Fix = Fix + Fix; nie są niezbędne białe
znaki pomiędzy Fix a =, jak i pomiędzy Fix a Fix, chocia\ są one
dozwolone, a nawet zalecane dla lepszej czytelności kodu.
" Wynika to z faktu, \e znak = nie jest znakiem alfabetycznym ani
numerycznym i kompilator mo\e oddzielić go bez problemu od
pozostałych znaków w procesie kompilacji, podobnie jak w
przypadku znaku + . Zatem zapis Fix=Fix+Fix; jest poprawny.
Definiowanie zmiennych
" W ka\dym procesie rozwiązywania problemów, u\ywanie precyzyjnie
zdefiniowanych nazw jest oczywistym faktem.
" Nazwy te najczęściej kojarzone są z wielkościami, które muszą w
procesie programowania mieć zagwarantowany obszar w pamięci do
przechowywania danych.
" Ka\dy indywidualny i nazwany fragment pamięci skojarzony
jednoznacznie z danym typem wielkości nazywamy dla uproszczenia
zmienną.
" Ka\da zmienna przechowywać mo\e zatem tylko szczególny rodzaj
danych, których wartość  z reguły  zmienia się w trakcie obliczeń.
" Zmienna, która została wybrana do przechowywania danych
jednego typu nie jest z reguły odpowiednia do przechowywania
danych innego typu (np. zmienna przeznaczona do przechowywania
liczb całkowitych nie mo\e być  bez utraty informacji  u\yta do
przechowywania liczb zmiennoprzecinkowych, chocia\ w drugą
stronę taka zamiana jest oczywiście mo\liwa).
Reguły nadawania nazw zmiennym
Nazwa zmiennej (identyfikator) mo\e zawierać:
litery A-z (du\e i małe),
cyfry 0-9 i
znak podkreślenia _ ,
np. Dimension , ELEMENT , length , i , K2 , j23 , name_44 , _bee .
" Wszystkie inne znaki są nielegalne.
" Nazwa zmiennej musi zaczynać się od litery lub od znaku
podkreślenia _:
np. nazwa 7Up jest nielegalna.
" Zaleca się, aby nazwy były wybierane w taki sposób aby kojarzyły
się łatwo z nazwami wielkości u\ywanych w rzeczywistym
problemie.
" W Visual C++, nazwy zmiennych nie mogą przekroczyć 247 znaków.
" Język C++ jest czuły na wielkość liter (case-sensitive) i np. nazwy:
k2 , K2 , j23 , J23 oznaczają 4 ró\ne zmienne.
Słowa kluczowe w C++
" W języku C++, są nazwy  zwane słowami kluczowymi, które mają
szczególne znaczenie.
" Są one podświetlane (np. na niebiesko) w momencie pojawienia się
w oknie edytora tekstu.
" Jeśli pisane słowo kluczowe nie zmienia koloru, oznacza to, \e zostało
ono niepoprawnie zapisane.
" Poni\ej podana lista słów kluczowych nie jest kompletna!
inline , break , case , catch , char , class , const , continue ,default ,
delete , do , double , else , enum , extern , false , float , for , friend ,
goto , if , inline , int , long , namespace , new , operator , private ,
protected , public , register , return , short , signed , sizeof , static ,
struct , switch , template , this , throw , true , try , typedef ,
typename , union , unsigned , using , virtual , void , volatile , while .
" Kompletną listę słów kluczowych mo\na znalezć w dokumentacji
języka C++.
Deklaracja i definicja zmiennej
" Deklaracja zmiennej w programie jest instrukcją, w której pojawia
się nazwa zmiennej i typ danych, które ma ona przechowywać.
" Np. instrukcja
int Fix;
deklaruje zmienną o nazwie Fix, która mo\e przechowywać liczby
całkowite.
" Zauwa\my, \e deklaracja zawsze kończy się średnikiem ; .
" Pojedyńcza deklaracja mo\e obejmować kilka zmiennych, lecz zaleca
się deklarować ka\dą zmienną w jednej linii w celu lepszej czytelności
kodu programu, a więc
np. zamiast jednej deklaracji: int Fix1, Fix2;
lepiej deklarować dwukrotnie: int Fix1;
int Fix2;
" W celu przechowywania danych potrzebne jest  fizyczne
przydzielenie fragmentu pamięci.
" Proces rzeczywistego rezerwowania fragmentu w pamięci komputera
nazywamy definiowaniem zmiennej.
" Z reguły, w języku C++, deklaracja zmiennej jest jednocześnie jej
definicją (za wyjątkiem kilku wa\nych przypadków).
" A zatem instrukcja
int Fix;
jest zarówno deklaracją jak i definicją zmiennej Fix, która mo\e
przechowywać liczby całkowitoliczbowe.
" Nale\y pamiętać, \e przed ka\dym pierwszym u\yciem zmiennej,
musimy ją zawsze wcześniej zadeklarować (zdefiniować).
UWAGA !!!
" Rozró\nianie pojęć deklaracja i definicja jest w pewnych sytuacjach
wygodne a nawet konieczne. Większe znaczenie mają jednak te
pojęcia w odniesieniu do funkcji patrz dalszy ciąg wykładu.
Inicjalizowanie zmiennych
" W momencie deklaracji zmiennej, mo\emy ją tak\e zainicjalizować.
" Deklaracja zmiennej (definicja), w której jest ona jednocześnie
inicjalizowana nazywany jest jej inicjalizacją.
np.
int Fix1=0;
int Fix2=1;
" W tym przykładzie, Fix1 będzie przechowywać wartość 0, a Fix2
wartość 1.
" Obie powy\sze instrukcje są jednocześnie:
deklaracją,
definicją i
inicjalizacją.
" Mo\liwy jest tak\e inny, tzw. funkcyjny sposób inicjalizacji
w momencie definiowania zmiennych, w którym zamiast znaku
równości u\ywany jest nawias w sposób pokazany poni\ej
int Fix1(0); //zamiast int Fix1=0;
int Fix2(1); //zamiast int Fix2=1;
" W przypadku niezainicjalizowania definiowanych zmiennych,
zwykle będą ona przechowywać jakieś przypadkowe wartości
( śmieci ) będące pozostałościami po poprzednio uruchamianych
programach.
" Zaleca się zatem, aby zawsze jak to jest tylko mo\liwe, inicjalizować
zmienne w momencie ich definicji, co w znacznym stopniu pomaga
lokalizować pózniej ewentualne błędy w programie.
" Brak inicjalizacji jest często zródłem trudnych do wykrycia błędów
wykonania programu (tzw. run-time errors).
Typy danych w C++
" Wszystkie zmienne u\ywane w programie muszą być mieć
zdefiniowany typ.
" W języku C++ zdefiniowane zostały tzw. standardowe typy, których
nazwy są słowami kluczowymi.
" W języku C++ mo\emy definiować tak\e własne typy, co jest
podstawą programowania zorientowanego obiektowo.
" Zaczniemy od przeglądu podstawowych typów wbudowanych,
w które jest wyposa\ony język C++.
Zmienne typu całkowitego
" Zmienne całkowite to zmienne, które mogą przechowywać wyłącznie
liczby całkowite.
int Fix = 123;
" W C++, słowo kluczowe short tak\e definiuje zmienną typu
całkowitego.
short i = 0;
" C++ tak\e jest wyposa\ony w zmienne całkowite typu long,
long j = 1000000L;
" Litera L dodana na końcu stałej 1000000 informuje, \e jest to liczba
typu long.
Zmienne typu znakowego
" Typ char stosuje się z dwóch powodów.
" Specyfikuje jedno bajtową zmienną do przechowywania liczb
całkowitych lub do przechowywania pojedyńczych znaków ASCII
(American Standard Code for Information Interchange).
" Deklarujemy zmienną typu char instrukcją:
char letter = 'A';
" Zdefiniowana powy\ej zmienna letter została zainicjalizowana stałą 'A'.
" Zauwa\my, \e inicjalizacja pojedyńczego znaku odbywa się przy
u\yciu pojedyńczych znaków cudzysłowu '...', a nie podwójnego
znaku  ... zarezerwowanego dla stałego łańcucha znaków.
" Poniewa\ znak 'A' jest reprezentowany dziesiętnie w kodzie ASCII
przez liczbę 65, mo\liwa jest inicjalizacja: char letter = 65;
równowa\na inicjalizacji: char letter = 'A'; .
Uwagi !!!
'A' oznacza du\ą literę A
'3' oznacza cyfrę 3 (cyfrę, nie liczbę)
Są tak\e znaki, których nie da się wprost umieścić między apostrofami.
Słu\ą one do sterowania wypisywaniem tekstu. W takich przypadkach
u\ywamy ukośnika \ (backslash) obok którego stawiamy
odpowiednią literę, która ma przypisane znaczenie sterowania
wypisywanym tekstem:
'\b'  cofacz (backspace)
'\f'  nowa strona (form feed)
'\n'  nowa linia (new line)
'\r'  powrót karetki (carriage return)
'\t'  tabulator poziomy (tabulator)
'\v'  tabulator pionowy (vertical tabulator)
'\a'  sygnał dzwiękowy (alarm)
Inne  wyjątkowe przypadki
'\\'  znak \
'\''  znak '
'\'''  znak cudzysłów ''
'\0'  znak NULL o kodzie 0
'\?'  znak pytajnik ?
Zmienne typu zmiennoprzecinkowego
Wartości numeryczne, które nie liczbami całkowitymi są zaliczane do
tzw. typu zmiennoprzecinkowego.
" Stała typu zmiennoprzecinkowego mo\e być wyra\ona jako liczba
dziesiętna, np.112.5, lub w postaci potęgowej 1.125E2 (1.125e2)
gdzie część dziesiętna jest mno\ona przez potęgę liczby 10
wyspecyfikowaną po literze E (e), tzn. 1.125e2 =1.125102 = 112.5 .
" Mamy typ zmiennoprzecinkowy double:
double x = 112.5;
" Zmienna typu double zajmuje 8 bajtów w pamięci i przechowuje
liczby z dokładnością do 15 cyfr po przecinku.
" Jeśli chcemy zmniejszyć dokładność, mo\emy u\yć słowa kluczowego
float do zdefiniowania zmiennej typu zmiennoprzecinkowego
przechowywanej w 4 bajtach, np. instrukcja float h=2.153f;
definiuje zmienną h i inicjalizuje ją wartością 2.153 (f na końcu stałej
specyfikuje ją jako typ float).
Zmienne typu logicznego
" Zmienna logiczna przybiera tylko dwie wartości:
- prawda, określana słowem kluczowym true
- fałsz, określana słowem kluczowym false.
" Ten typ zmiennych oznaczamy słowem kluczowym bool.
" Zmienne typu bool są u\ywane do przechowywania rezultatów
testów, których wynik mo\e być prawdziwy lub fałszywy, np. przy
porównywaniu wartości po obu stronach równości.
" Zmienne typu bool deklarujemy następująco:
bool b;
" Mo\emy je oczywiście tak\e jednocześnie inicjalizować:
bool b1=true;
bool b2=false;
Rząd wielkości typów podstawowych na typowych 16-bitowych
mikroprocesorach
float 10-37 1038
double 10-307 10308
int -32767 32767
long -2147483647 2147483647
UWAGA !!!
Powy\sza tabelka ma jedynie charakter orientacyjny i zawsze
powinno się zajrzeć do dokumentacji wykorzystywanego
kompilatora w celu wiarygodnego ustalenia rzeczywistego zakresu
typów dla danego procesora.
Stały zakres typów, niezale\ny od typu procesora, jest
gwarantowany np. w języku Java.
Obliczenia numeryczne w C++
Instrukcja przypisania
" Instrukcję przypisania stosowaliśmy ju\ wielokrotnie przy
inicjalizacji zmiennych.
" Typowa instrukcja przypisania wygląda następująco:
whole = part1 + part2 + part3;
" Instrukcja przypisania umo\liwia nam po obliczeniu wartości
wyra\enia o prawej stronie znaku równości = (w naszym przypadku
sumy part1, part2 i part3) i przechowanie rezultatu w zmiennej
wyspecyfikowanej po jego lewej stronie (w naszym przypadku
w zmiennej whole).
" Zauwa\my, \e jak zawsze, instrukcja = kończy się średnikiem.
" Mo\liwe jest ponadto wielokrotne u\ycie instrukcji przypisania,
A = B = 1;
co jest równowa\ne przypisaniu wartości 1 do B, a pózniej przypisaniu
wartości B do A (co oznacza, \e w zmiennej A i B przechowywana
będzie od tej pory wartość 1).
Operatory arytmetyczne
" Mamy do naszej dyspozycji m.in. następujące operatory
+
dodawania
-
odejmowania
*
mno\enia
/
dzielenia
" Mo\emy zatem napisać taką na przykład instrukcję:
netPay = hours * rate - deductions;
" W tej instrukcji najpierw iloczyn hours i rate będzie obliczony, potem
deductions będzie odjęty od otrzymanej wartości i wreszcie, na końcu,
otrzymany wynik przechowany zostanie w zmiennej netPay, poniewa\
działania mno\enia * i dzielenia / są wykonywane przed
dodawaniem + i odejmowaniem -, a instrukcja przypisania = jest
uruchamiana na końcu.
" Operator - jest w tym przypadku nazywany binarnym operatorem
arytmetycznym, poniewa\  działa on na dwóch wyra\eniach, zarówno
po jego lewej jak i prawej stronie.
" Znak minus tak\e u\ywamy jako operator słu\ący do zmiany znaku
wartości zmiennej pojawiającej się po jego prawej stronie i w tym
przypadku jest nazywany operatorem unarnym (unarny minus).
" Mo\emy zatem pisać np.:
int A = 0;
int B = -5;
A = -B;
" W tym przypadku, A będzie miała ostatecznie wartość +5
" W instrukcji,
A = A + 1;
czytamy:  dodaj 1 to bie\ącej wartości przechowywanej w zmiennej A
i przechowaj wynik z powrotem w zmiennej A .
" Oczywiście, matematycznie powy\szy zapis nie ma sensu.
" W przypadku zastosowania operatorów / , % do zmiennych typu
całkowitego, obliczany będzie odpowiednio iloraz całkowity i reszta
z dzielenia, np.
int i = 4;
int j = 3;
int q = i / j;
int r = i % j;
" Otrzymamy wtedy wynik:
q = 1 (4/3)
r = 1 (4%3)
" C++ \ąda aby wartości i, j w instrukcji i % j były nieujemne.
" W pozostałych przypadkach nie ma zagwarantowanego poprawnego
wyniki i zale\eć on mo\e od typu architektury komputera.
" Niech
double a=3.0;
double b=2.0;
" Jako rezultat dzielenia
double c=a/b;
otrzymamy oczywiście
c = 1.5 (:&!)
" Ale w przypadku
pewna  subtelność !!!.
int d=a/b;
" Zmienna d do przechowywania wyniku,
została zadeklarowana jako int i mo\e
otrzymamy
przechowywać tylko wartości typu int .
" Konsekwentnie, ka\da wartość
d = 1 ( ?)
zmiennoprzecinkowa będzie zaokrąglana
 w dół do największej liczby całkowitej,
1 w naszym przypadku i ta właśnie wartość
zostanie przechowana.
Rzutowanie
" Zamiana (konwersja) wartości jednego typu na drugi nazywana jest
rzutowaniem.
" W prezentowanym przykładzie mamy do czynienia z tzw. domyślnym
rzutowaniem, poniewa\ z kodu instrukcji przypisania nie wynika
explicite, \e rzutowanie takie jest konieczne i kompilator sam w takim
przypadku podejmuje decyzję jak zinterpretować to wyra\enie
(int d=a/b;)
" Nale\y jednak być zawsze ostro\nym przy tego typu rzutowaniach.
" Kompilator zresztą ostrzega nas o tym: warning C4244: 'initializing' :
conversion from 'double' to 'int', possible loss of data
co oznacza, \e próbujemy przypisać wartości zmiennej typu o
mniejszym zakresie, wartość typu zmiennej szerszego zakresu,
powodując tym samym utratę informacji (co czasami jest działaniem
po\ądanym, czy wręcz koniecznym).
" W przypadku ignorowania takich ostrze\eń mo\emy jednak
doprowadzić do pojawienia się trudnych do zlokalizowania błędów
w naszych programie.
" Jeśli jednak przypisania takie są nieuniknione, zaleca się aby w takich
przypadkach rzutować jawnie typy, co oznacza tyle, \e dajemy
sygnał kompilatorowi: wiemy co robimy  wszystko pod kontrolą .
" Instrukcja rzutowania jawnego wygląda następująco:
d = static_cast(a/b);
" Wyra\enie w nawiasie () w instrukcji static_cast() jest w takim
przypadku konwertowane do typu podanego w nawiasie <>.
" Słowo kluczowe static_cast odzwierciedla fakt, \e rzutowanie w tym
przypadku jest sprawdzane statycznie  tj. wtedy kiedy program jest
kompilowany.
" Znane są jeszcze trzy inne typy rzutowania wykorzystywane w
bardziej zaawansowanych programach:
const_cast, reinerpret_cast, dynamic_cast.
" Nie jest obecnie zalecany stary, choć najprostszy sposób jawnego
rzutowania z u\yciem zwykłych nawiasów ():
d = (int)(a/b);
Modyfikator const
" Mo\liwa jest deklaracja zmiennej u\ywanej w programie posiadająca
pewną nową cechę:
const double gamma = 0.5772156649015328;
" Deklaracja ta zaczyna się od słowa kluczowego: const
" Taki modyfikator oznacza, \e zmienna gamma jest nie tylko typu
double, ale dodatkowo, \e jest ona stała.
" Skutkiem takiej deklaracji, sprawdzane są w czasie kompilacji
wszystkie miejsca wystąpienia tej zmiennej w celu wyeliminowania
wszelkich prób jej modyfikacji w programie, uznawanych odtąd za
błąd.
" Nie jest zatem mo\liwa instrukcja jak poni\ej:
gamma = 0; error
Modyfikowanie zmiennych
" Jednym z bardzo często spotykanych sposobów modyfikacji
zmiennych jest tzw. inkrementacja lub dublowanie.
" Mo\emy np. inkrementować zmienną count w instrukcji:
count = count + 5;
" Powoduje to dodanie 5 do bie\ącej wartości przechowywanej w count,
i przechowanie wyniku z powrotem w zmiennej count, co da nam
ostatecznie np. 15, dla załó\my, początkowej wartości count jako 10.
" Mamy w takich przypadkach alternatywny sposób wykorzystania
nowego operatora, który znacznie skraca notację, mianowicie:
count += 5;
co czytamy  wez aktualną wartość zmiennej count, dodaj do niej 5
i przechowaj wynik z powrotem w zmiennej count  .
" Dla szeregu innych operatorów mo\liwa jest podobna skrócona notacja
np. instrukcja count *= 5; skutkuje przemno\eniem aktualnej wartości
zmiennej count przez 5 i przechowaniem wyniku z powrotem w
zmiennej count, co jest równowa\ne instrukcji count = count * 5;
" Ogólnie, piszemy w takich przypadkach instrukcję,
lhs op= rhs;
gdzie op jest dowolnym operatorem:
+ - * / %
(nie wszystkie operatory zostały wymienione !)
" lhs oznacza wyra\enie stojące po lewej stronie znaku przypisania,
które jest zazwyczaj (ale nie koniecznie) nazwą zmiennej.
" rhs oznacza wyra\enie stojące po prawej stronie instrukcji.
" Powy\sza forma jest równowa\na zapisowi:
lhs = lhs op (rhs);
co na przykład oznacza, \e wartość zmiennej A po wykonaniu
instrukcji,
A /= B + C;
będzie identyczna jak po wykonaniu instrukcji,
A = A/(B + C);
Operatory inkrementacji i dekrementacji
" Istnieje jeszcze kilka innych i bardzo często wykorzystywanych
operatorów arytmetycznych zwanych operatorami inkrementacji i
dekrementacji.
" Są to unarne operatory, które zmniejszają lub zwiększają wartość
zmiennej o jeden.
" Prześledzmy następujący przykład, zakładając, \e zmienna count jest
typu int. Trzy poni\sze instrukcje (traktując ka\dą z osobna !) są
równowa\ne i dają ten sam wynik:
count = count + 1;
count += 1; Ka\da z nich zwiększa wartość zmiennej count o 1.
++count;
" Ostatnia forma, wykorzystująca operator inkrementacji, jest najbardziej
zwarta.
" Ponadto, jeśli będzie ona u\yta wewnątrz jakiegoś wyra\enia, to
najpierw będzie przeprowadzona inkrementacja wartości zmiennej,
a dopiero pózniej, zwiększona w ten sposób wartość będzie u\yta w
jako argument pozostałych działań.
" Przykładowo, jeśli count ma wartość 5, a zmienna total jest typu
int, wtedy wartość zmiennej total po wykonaniu instrukcji
total = ++count + 6;
będzie równa 12.
" Jak dotąd, operator ++, był u\ywany przed identyfikatorem zmiennej
której dotyczył.
" Ta forma nazywana jest formą prefix.
" Dodatkowo, operator inkrementacji ma swoją formę postfix, w której
operator stoi za identyfikatorem zmiennej której dotyczy.
" Efekt działania, w bardziej zło\onych wyra\eniach, jest w takim
przypadku z reguły nieco inny...
" Zmienna, której operator ten dotyczy jest inkrementowana dopiero po
wykonaniu wszystkich pozostałych działań przypisanych danemu
wyra\eniu.
" Na przykład, niech ponownie count ma wartość początkową 5 i
zapiszmy teraz poprzednie wyra\enie (total = ++count + 6;) jako:
total = count++ + 6;
" W tym przypadku, wartość zmiennej total będzie 11, poniewa\
początkowa wartość zmiennej count będzie najpierw u\yta w
obliczeniu wartości wyra\enia a dopiero pózniej zwiększona o 1.
" W równowa\ny sposób moglibyśmy to zapisać jako:
total = count + 6;
++count;
" Dokładnie te same reguły obowiązują dla operatora dekrementacji --.
" Przykładowo, jeśli count miałaby początkową wartość 5, wtedy
po wykonaniu instrukcji
total = --count + 6;
total będzie równe 10, podczas gdy po wykonaniu instrukcji
total = count-- + 6;
wartość total będzie równa to 11.
" W obu przypadkach, wartość zmiennej count będzie oczywiście równa
4 po wykonaniu którejkolwiek z powy\szych instrukcji.
" Oba operatory: ++(...) , (...)++ i --(...) , (...)--
są przewa\nie stosowane do typów całkowitych, ale mogą być
stosowane tak\e dla innych typów.
Kolejność wykonywania obliczeń
" Jak dotychczas, problem kolejności wykonywania działań w
zło\onych wyra\eniach nie był jeszcze szczegółowo omawiany.
" Mo\na przyjąć generalnie zasadę, \e znane jeszcze ze szkoły reguły
wykonywania działań arytmetycznych (ich kolejność) są prawdziwe
i w języku C++, ale oprócz operatorów arytmetycznych, mamy cały
szereg innych operatorów (niearytmetycznych).
" Wa\ne jest aby poprawnie móc przewidzieć, który z nich
 ruszy najpierw do akcji w przypadku bardziej zło\onych wyra\eń.
" Ustalenie, obowiązujących w języku C++ reguł, jest oparte o
pojęcie priorytetu i łączności operatorów (precedence, associativity).
Priorytet i łączność operatorów
" Priorytet operatorów szereguje kolejność ich u\ycia w zło\onych
wyra\eniach.
" W ka\dym wyra\eniu, operator o większym priorytecie jest zawsze
u\yty najpierw, przed operatorami o mniejszym priorytecie.
" Kompletna lista priorytetów operatorów w języku C++ jest dostępna
w dokumentacji języka.
" W przypadku nieu\ywania w zło\onych wyra\eniach nawiasów ( ),
kolejność wykonywania określonych działań dla operatorów
posiadających ten sam priorytet jest zdeterminowana przez ich
łączność.
" Aączność będzie zilustrowana przykładami.
" Warto te\ zauwa\yć, \e unarna wersja operatora ma zawsze większy
priorytet ni\ jego wersja binarna.
" Zawsze mo\emy zmienić kolejność działań, która wynika z
priorytetów operatorów, u\ywając nawiasy.
" Poniewa\ jest du\o operatorów w języku C++, trudno jest pamiętać
o ich priorytetach.
" Dlatego te\, zaleca się u\ywać nawiasów, które z reguły ułatwiają
czytanie kodu i zabezpieczają przed pomyłkami.
" W poni\szych tablicach zestawiono priorytety i łączność wszystkich
u\ywanych w języku C++ operatorów.
" W tablicy operatory zostały uszeregowane kolejno od tych o
najwy\szym priorytecie do tych o najni\szym priorytecie.
" Operatory umieszczone w tym samym segmencie tabeli mają taki
sam priorytet.
C++ Operator Precedence and Associativity
int a,b,c,d,e; " Najwy\szy priorytet ma operator unarny: -.
a = b / c * d + (-e);
b=3;
" Ni\szy priorytet mają operatory binarne: / , *.
c=2; i obliczamy wyra\enie od lewej do prawej (tabela).
a = (b / c) * d + (-e);
d=2;
a = ((b / c) * d) + (-e);
e=3; " Jeszcze ni\szy priorytet ma operator binarny: +.
a = (((b / c) * d) + (-e));
a = b / c * d + -e;
" Najni\szy priorytet ma binarny operator: =.
(a = (((b / c) * d) + (-e)));
" A zatem otrzymamy ostatecznie wynik:
(a = (((3 /2) * 2) + (-3)));
(a = ((1 * 2) + (-3)));
(a = (2 + (-3)));
(a = (-1));
a = -1;
a+b+c+d+e; Lewostronna łączność binarnego operatora dodawania
+, pozwala nam napisać wyra\enie w równowa\ny
sposób:
((((a+b)+c)+d)+e);
poniewa\:
(a+b)+c+d+e;
((a+b)+c)+d+e;
(((a+b)+c)+d)+e;
((((a+b)+c)+d)+e);
a=b=c=d=e; Prawostronna łączność binarnego operatora przypisania
=, pozwala nam napisać wyra\enie w równowa\ny
sposób:
(a=(b=(c=(d=e))));
poniewa\:
a=b=c=(d=e);
a=b=(c=(d=e));
a=(b=(c=(d=e)));
(a=(b=(c=(d=e))));
Zakres wa\ności nazwy i czas \ycia zmiennej
Czas \ycia zmiennej
" Ka\da zmienna ma skończony  czas \ycia podczas uruchamiania
programu.
" Zmienne zaczynają istnieć od momentu ich powstania, a\ po pewnym
czasie  znikają  najpózniej w chwili gdy program się zakończy.
" Długość \ycia zmiennej jest związana z własnością czas \ycia
(storage duration).
" Wyró\niamy trzy rodzaje czasu \ycia zmiennej:
automatyczny
statyczny
dynamiczny
i od którego z nich zale\y czas \ycia zmiennej  wynika ze sposobu jej
tworzenia.
Zasięg
" Inną własnością jest zasięg zmiennej (scope) zmiennej.
" Zasięgiem nazywamy po prostu część naszego programu w którym
zmienna jest dostępna.
" Je\eli zmienna jest w zasięgu, to mo\emy się do niej odwoływać,
modyfikować ją, u\ywać w wyra\eniach itd..
" Je\eli zmienna jest poza zasięgiem, nie mamy mo\liwości u\ywania
jej nazwy i jakakolwiek próba odwołania się do niej jest
interpretowana przez kompilator jako błąd.
" Zauwa\my, \e ciągle istniejąca zmienna mo\e być jednak poza naszym
zasięgiem  odwrotna sytuacja nie mo\e mieć oczywiście miejsca.
Zmienne automatyczne
" Dotychczas deklarowaliśmy zmienne w obrębie bloku, tj. pomiędzy
nawiasami {...}.
" Tak tworzone zmienne są nazywane automatycznymi i mają lokalny
zasięg od miejsca, w którym zostały zadeklarowane a\ do końca
bloku, w którym zostały zadeklarowane.
#include
using namespace std;
int main()
{ //Function scope starts here
int count1 = 10;
int count3 = 50;
cout<<<"Value of outer count1 = "<<{ //New scope starts here...
int count1 = 20;//This hides the outer count1
int count2 = 30;
cout<<"Value of inner count1 = "<<count1+=3; //This affects the inner count1
count3+=count2;
} //...and ends here
cout<<"Value of outer count1 = "<<<<"Value of outer count3 = "<<//cout<return 0;
} // Function scope ends here
#include
" Dwie pierwsze instrukcje
using namespace std;
int main()
deklarują i definiują dwie
{ //Function scope starts here
zmienne typu całkowitego,
int count1 = 10;
int count3 = 50;
count1 i count3, zainicjalizowane
cout<odpowiednio wartościami 10 i 50.
<<"Value of outer count1 = "<<" Obie te zmienne istnieją od tego
{ //New scope starts here...
miejsca a\ do zamykającego
int count1 = 20;//This hides the outer count1
int count2 = 30;
nawiasu, kończącego program.
cout<<"Value of inner count1 = "<" Zasięg tych zmiennych tak\e
<count1+=3; //This affects the inner count1
rozciąga się do końca funkcji
count3+=count2;
main().
} //...and ends here
cout<<"Value of outer count1 = "<<<<"Value of outer count3 = "<<//cout<return 0;
} // Function scope ends here
#include
using namespace std;
int main()
{ //Function scope starts here
int count1 = 10;
int count3 = 50;
cout<" Wartość zmiennej count1
<<"Value of outer count1 = "<<dodatkowo wyświetlamy na
{ //New scope starts here...
ekranie.
int count1 = 20;//This hides the outer count1
int count2 = 30;
cout<<"Value of inner count1 = "<<count1+=3; //This affects the inner count1
count3+=count2;
} //...and ends here
cout<<"Value of outer count1 = "<<<<"Value of outer count3 = "<<//cout<return 0;
} // Function scope ends here
#include
" Mamy drugi nawias otwie-
using namespace std;
rający nowy blok instrukcji.
int main()
{ //Function scope starts here
" Dwie zmienne, count1 i
int count1 = 10;
count2, są zdefiniowane w tym
int count3 = 50;
cout<bloku i zainicjalizowane
<<"Value of outer count1 = "<odpowiednio wartościami 20 i
<{ //New scope starts here...
30.
int count1 = 20;//This hides the outer count1
" Zmienna count1
int count2 = 30;
cout<<"Value of inner count1 = "<<inną zmienną ni\ count1
count1+=3; //This affects the inner count1
count3+=count2; zadeklarowana wcześniej.
} //...and ends here
" Pierwsza count1 ciągle istnieje,
cout<<"Value of outer count1 = "<<<<"Value of outer count3 = "<przez drugą zmienną count1.
<//cout<return 0;
w tym bloku, skutkuje
} // Function scope ends here
odwołaniem do zmiennej count1
wyłącznie z tego bloku.
#include
using namespace std;
int main()
{ //Function scope starts here
int count1 = 10;
int count3 = 50;
cout<" Wyświetlona w drugiej linijce
<<"Value of outer count1 = "<<wartość zmiennej count1
{ //New scope starts here...
potwierdza ten fakt.
int count1 = 20;//This hides the outer count1
int count2 = 30;
" Zmienna count1jest
cout<<"Value of inner count1 = "<inkrementowana o 3 :
<count1+=3; //This affects the inner count1
count1+=3;
count3+=count2;
" Inkrementacja dotyczy
} //...and ends here
cout<<"Value of outer count1 = "<wyłącznie zmiennej w
<wewnętrznym bloku, poniewa\
<<"Value of outer count3 = "<<zewnętrzna zmienna count1
//cout<jest ciągle zasłonięta.
return 0;
} // Function scope ends here
#include
" Zmienną, count3, zdefiniowaną
using namespace std;
w bloku zewnętrznym,
int main()
{ //Function scope starts here
inkrementujemy bez problemu:
int count1 = 10;
count3+=count2;
int count3 = 50;
cout<" Zmienna count3, zdefiniowana
<<"Value of outer count1 = "<w bloku zewnętrznym jest
<{ //New scope starts here...
ciągle dostępna w bloku
int count1 = 20;//This hides the outer count1
wewnętrznym.
int count2 = 30;
cout<<"Value of inner count1 = "<<count1+=3; //This affects the inner count1
count3+=count2;
} //...and ends here
cout<<"Value of outer count1 = "<<<<"Value of outer count3 = "<<//cout<return 0;
} // Function scope ends here
#include
using namespace std;
int main()
{ //Function scope starts here
int count1 = 10;
int count3 = 50;
cout<" Koniec bloku wewnętrznego jest
<<"Value of outer count1 = "<<końcem \ycia zmiennych count2
{ //New scope starts here...
i (tylko wewnętrznej) count1.
int count1 = 20;//This hides the outer count1
int count2 = 30;
" Zmienne count1 i count3 ciągle
cout<<"Value of inner count1 = "<istnieją w bloku zewnętrznym,
<count1+=3; //This affects the inner count1
a wyświetlana na ekranie w
count3+=count2;
trzeciej linijce wartość count1
} //...and ends here
cout<<"Value of outer count1 = "<oraz w czwartej linijce wartość
<count3 potwierdzają poprzednie
<<"Value of outer count3 = "<<komentarze.
//cout<return 0;
} // Function scope ends here
#include
using namespace std;
int main()
{ //Function scope starts here
int count1 = 10;
int count3 = 50;
cout<" Wprowadzenie instrukcji
<<"Value of outer count1 = "<<(tutaj potraktowanej jako
{ //New scope starts here...
komentarz w celu uniknięcia
int count1 = 20;//This hides the outer count1
int count2 = 30;
błędu)
cout<<"Value of inner count1 = "<cout<<count1+=3; //This affects the inner count1
oczywiście błędem, poniewa\
count3+=count2;
zmienna count2 w tym miejscu
} //...and ends here
cout<<"Value of outer count1 = "<ju\ nie istnieje.
<" Otrzymalibyśmy informację o
<<"Value of outer count3 = "<<błędzie kompilacji:
//cout<error C2065: 'count2':
return 0;
} // Function scope ends here
undeclared identifier
Zmienne globalne
" Zmienne zadeklarowane poza wszystkimi blokami i (klasami)
są nazywane zmiennymi globalnymi i mają globalny zasięg.
" Oznacza to, \e są one dostępne przez wszystkie funkcje w pliku od
miejsca gdzie zostały zadeklarowane.
" Zadeklarowanie ich na samym początku programu, czyni je
dostępnymi wszędzie w pliku, w którym kodowany jest program.
" Zmienne globalne mają domyślnie tzw. statyczny czas \ycia (static
storage duration) i istnieją od początku do końca działania programu.
" Jeśli ponadto nie zostaną one zainicjalizowane w momencie ich
definicji, będą (w odró\nieniu od zmiennych automatycznych)
zainicjalizowane wartością 0 i to jeszcze przed wywołaniem funkcji
main().
" Zmienne value1 i value4,
są globalne.
" Ich zasięg rozciąga się od miejsca
ich powstania do końca pliku w
którym zostały zdefiniowane.
" Pomimo faktu, \e zmienna value4
istnieje od momentu kiedy
program rozpoczyna działanie, to
jednak nie jest mo\liwe odwołanie
się do niej w funkcji main()
poniewa\ funkcja main() nie jest
w zasięgu tej zmiennej.
" Aby funkcja main() mogła
u\ywać zmienną value4,
nale\ałoby przesunąć jej
deklarację na początek pliku.
" Obie zmienne value1 i value4
będą zainicjalizowane 0.
" Zauwa\my jeszcze, \e lokalna
zmienna value1 w funkcji
function() zasłania globalną
zmienną value1.
" Poniewa\ zmienne globalne istnieją tak długo jak długo działa
program, mo\e pojawić się pytanie: dlaczego nie deklarować
wszystkich zmiennych jako globalne i tym samym nie mieć problemów
z ich czasem \ycia oraz zakresem ?
" Odpowiedz jest negatywna z kilku istotnych powodów.
" Rzeczywiste programy operują z reguły na bardzo du\ej zmiennych.
" Deklarowanie wszystkich tych zmiennych jako globalne
zwiększyłoby nie tylko znacznie prawdopodobieństwo przypadkowej
modyfikacji którejś z nich ale tak\e stworzyłoby powa\ny problem
nadawania im ró\nych nazw.
" Ponadto, zmienne te zajmowałyby niepotrzebnie pamięć operacyjną
w czasie działania programu, co mogłoby znacznie ograniczyć
rozmiary rzeczywistego problemu.
#include
" Zmienna globalna count1
using namespace std;
int count1 = 100;//Global version of count1
jest dostępna w całej funkcji
int main()
main().
{//Function scope starts here
int count1 = 10;
" Zmienną globalną
int count3 = 50;
inicjalizujemy wartością 100.
cout<int count3 = 50;
funkcji main() zasłonięta zmienną
cout<{// New scope starts here...
pozwala na odniesienie się
int count1 = 20;//This hides the outer count1
int count2 = 30;
wewnątrz funkcji main() do
cout<<"Value of inner count1="<globalnej zmiennej count1.
<< endl;
cout<<"Value of global count1="
<<::count1//From inner block
<< endl;
count1 += 3;// This affects the inner count1
count3 += count2;
}// ...and ends here.
cout<<"Value of outer count1="<<<"Value of outer count3="<return 0;
}
#include
using namespace std;
int count1 = 100;//Global version of count1
int main()
{//Function scope starts here
int count1 = 10;
int count3 = 50;
cout<<< ::count1//From outer block
globalna count1jest zasłonięta a\
<< endl;
{// New scope starts here...
przez dwie zmienne count1: lokalną
int count1 = 20;//This hides the outer count1
zmienną count1 i zewnętrzną
int count2 = 30;
cout<<"Value of inner count1="<zmienną count1.
<< endl;
" Jednak u\ycie operatora zakresu i
cout<<"Value of global count1="
<<::count1//From inner block
w tym przypadku umo\liwia nam
<< endl;
na odwołanie się do zmiennej
count1 += 3;// This affects the inner count1
count3 += count2;
globalnej count1.
}// ...and ends here.
cout<<"Value of outer count1="<<<"Value of outer count3="<return 0;
}


Wyszukiwarka

Podobne podstrony:
AiP wyklad03
AiP wyklad05
AiP wyklad04
AiP wyklad02
Sieci komputerowe wyklady dr Furtak
Wykład 05 Opadanie i fluidyzacja
WYKŁAD 1 Wprowadzenie do biotechnologii farmaceutycznej
mo3 wykladyJJ
ZARZĄDZANIE WARTOŚCIĄ PRZEDSIĘBIORSTWA Z DNIA 26 MARZEC 2011 WYKŁAD NR 3
Wyklad 2 PNOP 08 9 zaoczne
Wyklad studport 8
Kryptografia wyklad
Budownictwo Ogolne II zaoczne wyklad 13 ppoz

więcej podobnych podstron