Języki programowania

Transkrypt

Języki programowania
Języki programowania
Nowoczesne techniki programowania
Wykład 1
Witold Dyrka
[email protected]
5/10/2011
Prawa autorskie
Slajdy do wykładu powstały
w oparciu o slajdy Bjarne Stroustrupa
do kursu Foundations of Engineering II (C++)
prowadzonego w Texas A&M University
http://www.stroustrup.com/Programming
Program wykładów
1. Pierwszy program. Obiekty, typy i wartości
2. Wykonywanie obliczeń. Błędy
3. Pisanie i wykańczanie programu
4. Techniki pisania funkcji i klas
5. Strumienie wejścia/wyjścia
6. Wskaźniki i tablice
7. Systematyka technik i języków programowania
Program laboratorium
●
Pisanie algorytmów
●
Język C++
Materiały
Literatura
●
Bjarne Stroustrup. Programowanie: Teoria i praktyka z
wykorzystaniem C++. Helion (2010)
●
Jerzy Grębosz. Symfonia C++ standard. Edition 2000 (2008)
●
Dowolny podręcznik języka C++ w standardzie ISO 98
Środowisko programistyczne
●
Microsoft Visual C++ (rekomendowane)
●
Dowolne środowisko korzystające z GCC
Warunki zaliczenia
●
●
Projekt programistyczny (50%)
●
po trzecim wykładzie (2.XI.2011 r.)
●
termin oddania (4.I.2012 r.)
Kolokwium (50%)
●
●
środa, 18.01.2011 r.
Na zaliczenie >50% pkt.
Zasady
●
Nie toleruję plagiatów
●
●
Nie toleruję ściągania
●
●
dot. projektów i programów na laboratorium
dot. kolokwium i sprawdzianów na laboratorium
Zachęcam do korzystania z konsultacji
●
ze mną: PT 10-11, pok. 118A/D-1
●
pomiędzy sobą
Dlaczego programowanie?
Programowanie w medycynie
Na przykład:
●
Tomografia
oprogramowanie skanera, przesyłanie sygnałów, przetwarzanie obrazu
●
Chirurgia wspomagana robotami
wizualizacja, precyzyjne sterowanie narzędziami, sterowanie na odległość
●
Inne: automatyczne badania (np. krwii), urządzenia ultradźwiękowe,
komputery kieszonkowe i tzw. mobile health care
●
●
Natychmiastowy dostęp do danych pacjenta
Projekty medyczne realizowane przez znajomą, niewielką firmę
informatyczną z Wrocławia:
●
obsługa magazynu lekarstw i apteki szpitala
●
optymalizacja produkcji granulatu w dużej firmie farmaceutycznej
Czym jest programowanie?
●
Powiedzeniem bardzo szybkiemu kolesiowi co ma
dokładnie robić
●
Planem rozwiązywania problemu przez komputer
●
Określeniem kolejności wykonywanych działań
●
Z tym, że:
●
●
współczesne programy zawierają miliony linii kodu
●
i koncentrują się na manipulacji danymi
Może więc:
Określeniem struktury i zachowania programu oraz
sprawdzeniem czy wykonuje on zadanie prawidłowo
i dostatecznie sprawnie
Czy programowanie jest trudne?
●
Zasadniczo jest łatwe:
●
●
Napisz maszynie co ma robić
Dlaczego jest więc trudne? ;-)
●
●
●
●
Chcemy by komputer robił złożone rzeczy, a on jest
tylko maszyną
Rzeczywistość jest bardziej skomplikowana niż
nam się wydaje, a my nie zawsze zdajemy sobie
sprawę z implikacji tego czego chcemy
„Programowanie jest rozumieniem”, tego co
chcemy zautomatyzować
Programowanie łączy teorię i praktykę
Pierwszy program
#include <iostream>
// dołącza plik nagłówkowy biblioteki przydatnych
// narzędzi
int main()
{
// main() jest początkiem każdego programu C++
std::cout << "Hello, world!\n";
return 0;
// wyświetla 13 znaków: Hello, world!
// i przechodzi do nowej linii
// zwraca wartość oznaczającą sukces
}
// Cudzysłów typu " " ogranicza literał łańcuchowy
// \n oznacza początek nowej linii
// Średnik ; kończy każdą instrukcję
// Nawiasy klamrowe { … } grupują instrukcje w blok
// main() jest funkcją, która nie pobiera argumentów i zwraca wartość całkowitą (int)
oznaczającą sukces (0) lub błąd (!0)
Pierwszy program (2)
/* Pierwszy program - cele
– poznanie:
kompilatora,
środowiska deweloperskiego (IDE)
środowiska uruchomieniowego
– sprawdzenie reakcji na błędy
zapomniany nagłówek,
zapomniany cudzysłów kończący łańcuch znakowy
pomyłka w nazwie (np. retrun)
zapomniany średnik lub nawias klamrowy
*/
#include <iostream>
int main()
{
cout << "Hello, world!\n";
system(“pause”);
return 0;
}
// dołącza plik nagłówkowy biblioteki narzędzi
// main() jest początkiem każdego programu C++
// wyświetla 13 znaków: Hello, world!
// i przechodzi do nowej linii
// czeka na wciśnięcie klawisza
// zwraca wartość oznaczającą sukces
Liczy się styl
●
●
●
Większa część kodu to jakby gotowy formularz
Jedyna instrukcja, która „coś” robi to:
cout << "Hello, world!\n"
I taki podział jest zupełnie normalny:-)
●
●
bez komentarzy, dołączania bibliotek itp.
kod nie będzie prosty, zrozumiały, godny zaufania
i efektywny
Nie wystarczy by jakoś działało
●
kod musi być elegancki i poprawny
Kompilacja i konsolidacja
Kod źródłowy C++
hello_world.cpp
Kompilator C++
Program wykonywalny
hello_world.exe
●
●
Konsolidator
(ang. linker)
Kod obiektowy
hello_world.obj
Kod obiektowy
biblioteki
iostream.obj
Kompilator
- sprawdza kod napisany w języku programowania
- generuje kod obiektowy, specyficzny dla architektury komputera
i systemu operacyjnego
Konsolidator dołącza kod obiektowy wykorzystywanych bibliotek
i porządkuje przestrzeń programu
Obiekty, typy i wartości
Programowanie polega przede wszystkim na
manipulowaniu danymi.
Teraz zajmiemy się:
●
wprowadzeniem i wyświetlaniem danych
●
zmiennymi przechowującymi dane
●
pojęciem typu i bezpieczeństwa typu
Wprowadzanie i wyświetlanie
/* Program wczytujący imię i witający się z użytkownikiem */
#include <iostream>
#include <string>
int main()
{
std::cout << "Prosze podac swoje imie (i nacisnac" << " 'enter'):\n";
string imie;
// Ta instrukcja to deklaracja zmiennej (imie)
// Zmienna posiada określony typ (string)
std::cin >> imie;
std::cout << "Czesc, " << imie << '\n';
}
// Kilka wartości może zostać wyświetlonych w jednej instrukcji
// Pominięto return 0; jest ono opcjonalne w main()
Wczytywanie zmiennych
●
Typ zmiennej określa co można z nią zrobić
●
W naszym przypadku:
std::cin >> imie;
wczytuje znaki ze standardowego wejścia (np. klawiatury),
aż do znaku białego (ang. whitespace)
●
Znak biały to np. spacja, tabulator, znak nowej linii
Wprowadzenie łańcuchów
/* Program wczytujący imię i nazwisko oraz witający się z użytkownikiem */
#include <iostream>
#include <string>
int main()
{
std::cout << "Prosze podac swoje imie i nazwisko:\n";
string pierwszy;
string drugi;
std::cin >> pierwszy >> drugi;
// wczytuje dwa łańcuchy znakowe
string nazwisko = pierwszy + ' ' + drugi; // deklaracja oraz inicja(liza)cja
// zmiennej nazwisko
std::cout << "Czesc, " << nazwisko << '\n';
}
// Dla typu string, operator + oznacza konkatenację, czyli sklejanie łańcuchów.
Wprowadzenie liczb całkowitych
/* Program wczytujący imię i wiek oraz witający się z użytkownikiem */
#include <iostream>
#include <string>
int main()
{
std::cout << "Prosze podac swoje imie i wiek:\n";
string imie;
int wiek;
// Zmienna całkowita jest typem wbudowanym,
// więc nie potrzebuje dołączania nagłówka
std::cin >> imie >> wiek;
std::cout << "Czesc, " << imie << ', masz ' << wiek <<lat'\n';
}
Liczby zmiennoprzecinkowe
// Proste działania arytmetyczne
#include <iostream>
#include <cmath>
int main()
{
std::cout << "Podaj liczbę zmiennoprzecinkową: ";
double n;
// zmienna zmiennoprzecinkowa typu double
std::cin >> n;
std::cout << "n = " << n
<< "\nn+1 = " << n+1
// '\n' oznacza nową linię
<< "\ntrzy razy n = " << 3*n
<< "\ndwa n = " << n+n
<< "\nn kwadrat = " << n*n
<< "\npolowa z n = " << n/2
<< "\npierwiastek kwadratowy z n = " << sqrt(n) // funkcja biblioteczna
<< std::endl;
// to też oznacza nową linię
}
Typy i literały
●
Typy wbudowane
●
●
●
bool – logiczny (Boolowski)
char – znakowy
int – całkowitoliczbowy
–
●
●
●
●
Literały znakowe: 'a', 'x', '4', '\n', '$'
●
Literały całkowitoliczbowe
0, 1, 123, -6, 0x34, 0xa3
●
float
Typy biblioteki standardowej
●
Literały logiczne: true false
short, long, signed, unsigned
double – zmiennoprzecinkowy
–
●
string – łańcuch znakowy
complex<Scalar> – liczby
zespolone
Literały zmiennoprzecinkowe
1.2, 13.345, .3, -0.54, 1.2e3, . 3F, .3F
●
Literały łańcuchowe
"asdf",
"Howdy, all y'all!“
●
Literały zespolone
complex<double>(12.3,99)
complex<float>(1.3F)
●
Typy użytkownika
Deklaracja i inicjacja zmiennej
int a = 7;
int b = 9;
a:
7
b:
9
char c = 'a';
c:
'a'
double x = 1.2;
x:
1.2
string s1 = "Hello, world";
s1:
12
s2:
3
|
"Hello, world"
string s2 = "1.2";
|
"1.2"
Obiekty


Obiekt jest fragmentem pamięci, który przechowuje wartość
pewnego typu
Zmienna jest nazwanym obiektem == deklaracja nazywa obiekt
int a = 7;
char c = 'x';
complex<double> z(1.0,2.0);
string s = "qwerty";
s:
6
a:
c:
z:
7
'x'
1.0
2.0
"qwerty"
Bezpieczeństwo typów
Zasada bezpieczeństwa typów:
●
Każdy obiekt będzie użyty tylko zgodnie z jego typem
●
●
●
Zmienna będzie użyto dopiero po inicjacji
Tylko operacje zdefiniowane dla zadeklarowanego typu zmiennej będą użyte
Każda operacja zdefiniowana dla zmiennej nadaje jej prawidłową wartość
Ideał statycznej kontroli typów
●
Program naruszający bezpieczeństwo typów nie zostanie
skompilowany
●
Kompilator zgłasza każde naruszenie
Ideał dynamicznej kontroli typów
●
Jeśli program narusza bezpieczeństwo typów, zostanie to wykryte
w czasie uruchomienia
●
Istnieje kod, który wykrywa każde naruszenie nie znalezione przez kompilator
Bezpieczeństwo typów w C++
C++ nie zapewnia (pełnej) statycznej kontroli typów
●
Żaden powszechnie używany język nie jest w pełni bezpieczny
●
Pełna statyczna kontrola typów mogłaby za bardzo ograniczać programistę
C++ nie zapewnia (pełnej) dynamicznej kontroli typów
●
Istnieją inne języki, które ją zapewniają
●
Pełna dynamiczna kontrola typów mogłaby za bardzo ograniczać programistę
●
Pełna dynamiczna kontrola typów często generuje większy i wolniejszy kod
Będziemy uczyć się technik zapewniających bezpieczeństwo typów.
Naruszenie bezpieczeństwa typów
niejawne zawężanie (ang. implicit narrowing)
// Uwaga: C++ nie zabrania próby umieszczenia dużej wartości
// w małej zmiennej (chociaż kompilator może ostrzec przed tym).
int main()
{
int a = 20000;
a:
char c = a;
int b = c;
if (a != b)
// != oznacza relację nierówności
cout << "ups!: " << a << "!=" << b << '\n';
else
cout << "Świetnie! Mamy duże znaki\n";
}
20000
c:
Spróbuj, jaka będzie wartość b na Twoim komputerze
???
Naruszenie bezpieczeństwa typów
(niezainicjowana zmienna)
// Uwaga: C++ pozwala użyć niezainicjowanej zmiennej.
// Jednak kompilator przeważnie ostrzega przed tym.
int main()
{
int x;
char c;
double d;
// x otrzymuje “losową” wartość początkową
// c otrzymuje“losową” wartość początkową
// d otrzymuje “losową” wartość początkową
// – nie każda zawartość komórki pamięci stanowi poprawną
//
wartość zmiennoprzecinkową
double dd = d;
// potencjalny błąd: niektóre implementacje
// nie kopiują niepoprawnych wartości zmiennoprzecinkowych
cout << " x: " << x << " c: " << c << " d: " << d << '\n';
}
Zawsze inicjuj swoje zmienne.
Wyjątek: zmienne, których wartości są wprowadzane z zewnątrz.
Uwaga: tryb debugowania może inicjować zmienne
Ideały programistyczne
●
Bezpieczeństwo typów
●
Szybkość wykonywania
●
Dostosowanie do danej platformy sprzętowej i systemowej
●
Możliwość uruchomienia na wielu platformach
oraz otrzymanie tych samych wyników
●
Zgodność z innym kodem lub systemem
●
Łatwość konstrukcji
●
Łatwość utrzymania
Jako inżynierowie jesteśmy zawsze skazani na kompromisy.
Ideały programistyczne
●
Bezpieczeństwo typów
●
Szybkość wykonywania
●
Dostosowanie do danej platformy sprzętowej i systemowej
●
Możliwość uruchomienia na wielu platformach
oraz otrzymanie tych samych wyników
●
Zgodność z innym kodem lub systemem
●
Łatwość konstrukcji
●
Łatwość utrzymania
Jako inżynierowie jesteśmy zawsze skazani na kompromisy.
Poprawne nazwy w C++
●
rozpoczynają się zawsze literą
●
mogą zawierać litery, cyfry i podkreślenia
●
np. poprawne nazwy to:
x, liczba_elementow, Fouriera_transformata, z2
●
niepoprawne są natomiast:
12x, czas$do$konca, glowna linia
●
●
Nie należy rozpoczynać nazw podkreślnikiem, np. _foo,
– składnia zarezerwowana dla kompilatora
Nie może definiować nazw, używanych jako słowa
kluczowe języka, np. int, if, while, double
Dobre nazwy w C++
DOBRE:
●
Nazwy znaczące w danym kontekście:
●
●
suma_czesciowa, licznik_elementow, eksport_pszenicy
Krótkie nazwy używane konwencjonalnie:
●
x – jako zmienna lokalna,
●
i – jako indeks pętli.
ZŁE:
●
Skróty i skrótowce są mylące
●
Za długie nazwy → program nieczytelny, łatwo o literówkę:
●
suma_wszystkich_elementow,
pozostale_wolne_miejsca_w_tablicy_symboli
Jeszcze jeden pomysł na program...
// Konwersja cali na cm i centymetrów na cale:
#include <iostream>
int main()
{
const double cm_na_cal = 2.54;
int wartosc;
char jednostka;
while (std::cin >> wartosc >> jednostka) {
// wczytuje w pętli
if (jednostka == '\"')
// znak cala jest znakiem specjalnym w C++
std::cout << wartosc << "\" == " << wartosc*cm_na_cal << "cm\n";
else if (jednostka == 'c') // 'c' jak w cm
std::cout << wartosc << "cm == " << wartosc/cm_na_cal << "\"\n";
else
return 0;
// kończy jeśli podana “zła” jednostka, np. 'q'
}
}
Dziś najważniejsze było to, że...
●
Warto, aby inżynier biomedyczny nauczył się dobrze
programować
●
W programowaniu liczy się styl
●
Możemy korzystać ze zmiennych różnych typów
●
Zmienna to nazwany obiekt
●
Każdy obiekt należy używać tylko zgodnie z jego typem
A za 2 tygodnie...
●
Wykonywanie obliczeń
●
Radzenie sobie z błędami