Języki i metody programowania

Transkrypt

Języki i metody programowania
Dr inż. Robert Wójcik
E-mail:
[email protected]
Strona internetowa: www.ict.pwr.wroc.pl/~wojcik
Języki i metody programowania
1. Wprowadzenie do programowania
1.1. Podstawowe definicje
1.2. Charakterystyka języka Pascal
1.3. Metodologia programowania
1.4. Ogólna struktura programu w języku Pascal
Literatura
[1] Koleśnik K., Wstęp do programowania z przykładami w Turbo Pascalu,
Wydawnictwo Helion, Gliwice, 1999.
[2] Marciniak A., Borland Pascal 7.0 z elementami programowania, Wydawnictwo
Nakom, Poznań, 1994.
[3] Sielicki A., Laboratorium programowania w języku Pascal, Oficyna Wydawnicza
Politechniki Wrocławskiej, Wrocław, 1994.
[4] Jarża R., Turbo Pascal. Szkoła programowania, Wydawnictwo Robomatic,
Wrocław, 1996.
1. Wprowadzenie do programowania
1.1. Podstawowe definicje
Problem – zadanie do rozwiązania.
Specyfikacja zadania – określenie danych wejściowych oraz wyników, które
powinny być uzyskane, a także warunków jakie
powinny one spełniać; może zawierać również
związki pomiędzy danymi a wynikami; definiuje
abstrakcyjny model rzeczywistego problemu.
Algorytm
jest skończonym ciągiem czynności, które prowadzą
rozwiązania zadania lub osiągnięcia określonego celu.
do
Komputer – urządzenie elektroniczne służące do automatycznego
przetwarzania danych według zadanego algorytmu.
Z punktu widzenia techniki komputerowej.
Algorytm – sposób przetwarzania danych wejściowych na dane wyjściowe
(wyniki) w skończonej liczbie kroków.
Algorytm definiuje:
• abstrakcyjne obiekty, na których wykonywane są działania,
reprezentowane przez odpowiednie struktury danych;
• operacje realizujące cel algorytmu;
• kolejność wykonywania działań.
Program komputerowy – algorytm zapisany w odpowiednim języku
programowania zrozumiałym przez komputer (np. w języku
maszynowym procesora – ciąg liczb stanowiących rozkazy
i dane dla procesora).
Język maszynowy jest trudno przyswajalny przez człowieka, gdyż składa się
z liczb reprezentujących instrukcje procesora (wszystkie dane, a w tym
i programy są przechowywane w pamięci komputera w kodzie binarnym).
W praktyce algorytmy są zapisywane za pomocą instrukcji języków programowania wyższego poziomu (języków algorytmicznych), które udostępniają
podstawowe elementy programowania strukturalnego (np. Pascal, C, Java,
Fortran, Cobol, Modula).
Kod źródłowy – ciąg instrukcji języka programowania (np. Pascal, C),
w którym zakodowano algorytmy stanowiące rozwiązanie problemu.
Przed wykonaniem program źródłowy należy przetłumaczyć na postać
zrozumiałą dla komputera czyli na kod wynikowy.
Kod wynikowy - kod pośredni w języku maszynowym, który jest zrozumiały
dla komputera; ciąg rozkazów i danych procesora,
zapisanych w pamięci komputera w kodzie binarnym.
Kod wynikowy jest przekształcany przez program linkera do postaci
wykonywalnej.
Linker – program łączący kody wynikowe odpowiednich modułów programu
w kod wykonywalny, który może być wielokrotnie uruchamiany
w komputerze.
W praktyce linker łączy w jeden plik wykonywalny następujące elementy:
• pliki wynikowe (obiektowe), otrzymane w wyniku kompilacji modułów
programu;
• standardowy kod startowy programu dla danego systemu operacyjnego;
• kody wynikowe funkcji, wykorzystywanych w programie, zapisane
w odpowiednich bibliotekach.
Kod wykonywalny - zawiera liczby, które są pobierane z pamięci komputera
przez procesor i interpretowane jako rozkazy
podlegające wykonaniu lub jako dane stanowiące
argumenty rozkazów.
Translator – realizuje przekształcenie programu z postaci źródłowej
na postać wynikową.
Rodzaje translatorów:
• kompilatory,
• interpretatory.
Kompilator – program przetwarzający kod źródłowy na kod wynikowy
(kod pośredni w języku maszynowym, który jest zrozumiały
dla komputera).
Interpretator – realizuje translację instrukcji naprzemiennie z ich
wykonywaniem; przy zastosowaniu interpretatora każde
wykonanie programu jest związane z jego ponowną
translacją (np. Basic, SQL).
Plik – wydzielony, posiadający nazwę obszar pamięci (najczęściej dyskowej),
w którym przechowywane są dane.
Z punktu widzenia języków programowania plik jest ciągiem danych
o odpowiedniej strukturze (w najprostszym przypadku ciągiem bajtów).
Każdy plik posiada rozmiar określony w bajtach.
1 Bajt [B] = 1 znak, 1 KB = 1024 B,
1MB = 1024 KB,
1 GB = 1024 MB.
Etapy rozwiązywania problemów z wykorzystaniem komputera:
•
•
•
•
•
•
•
•
•
•
•
•
•
•
specyfikacja problemu,
określenie danych wejściowych,
określenie celu (wyniku końcowego),
analiza problemu i wybór modelu,
synteza algorytmu prowadzącego do rozwiązania,
przedstawienie algorytmu:
- w postaci opisu słownego,
- w postaci listy kroków,
- w postaci schematu blokowego (postać graficzna algorytmu),
- za pomocą jednego z języków formalnych (np. UML).
analiza poprawności rozwiązania,
ocena efektywności algorytmu (złożoności obliczeniowej),
kodowanie algorytmu w postaci instrukcji języka programowania
(projekt programu komputerowego),
zapis programu do pliku,
kompilacja i usuwanie usterek,
utworzenie wersji wykonywalnej,
automatyczne wykonanie programu w komputerze,
testowanie i analiza wyników.
Algorytm
Problem
Model
Kodowanie
Program
Komputer
Plik
Etapy programowania
1. Utworzenie za pomocą edytora tekstu pliku źródłowego zawierającego
algorytm zapisany w wybranym języku programowania, np. program.pas
(program w języku Pascal), program.cpp (program w języku C++).
2. Kompilacja programu za pomocą kompilatora i utworzenie pliku
wynikowego (obiektowego), np. program.obj.
3. Połączenie za pomocą linkera kodu wynikowego programu, kodów
wynikowych funkcji bibliotecznych oraz kodu startowego w jeden plik
wykonywalny, np. program.exe.
Kompilacja programów
Kompilacja
Kod
źródłowy
programu
Łączenie
Kod
wynikowy
programu
Kod
wykonywalny
programu
Kod
startowy
Kod
wynikowy
z bibliotek
Wykonywanie programów
DANE
Programy (algorytmy)
WYNIKI
System operacyjny komputera – zbiór programów sterujących pracą
urządzeń wchodzących w skład systemu
komputerowego i nadzorujących
wykonywanie programów użytkowników.
Oprogramowanie użytkowe – programy uruchamiane pod kontrolą systemu
operacyjnego.
Podczas projektowania algorytmów należy pamiętać, aby opracowywane
algorytmy posiadały niską złożoność obliczeniową.
Czasowa złożoność obliczeniowa – określa liczbę elementarnych kroków
obliczeniowych (tzw. operacji elementarnych, np. porównań, sumowań, itp.).
Pamięciowa złożoność obliczeniowa – określa rozmiar pamięci niezbędnej
do wykonania programu.
W praktyce złożoność obliczeniową określa się za pomocą funkcji
ograniczających z góry ponoszony nakład obliczeniowy, np. O(n), O(nlog(n)).
Algorytmy efektywne –
złożoność obliczeniową.
posiadają
wielomianową
lub
logarytmiczną
Przetwarzanie sekwencyjne – wykonywanie instrukcji programów kolejno
jedna za drugą.
Przetwarzanie współbieżne – wykonywanie instrukcji programów
równocześnie na tym samym procesorze (z podziałem czasu procesora).
Przetwarzanie równoległe – wykonywanie instrukcji programów
równocześnie na różnych procesorach.
1.2. Charakterystyka języka Pascal
Geneza języka
Język algorytmiczny wysokiego poziomu i ogólnego przeznaczenia.
Został opracowany w 1968 roku przez Niklausa Wirtha na uniwersytecie w
Zurychu. Wzorem dla powstania języka Pascal był język Algol 60. Pierwszy
kompilator Pascala wzorcowego powstał w 1970 roku.
Język Pascal jest ukierunkowany na programowanie strukturalne. Ze
względu na łatwość opanowania i niewystępowanie zbędnych elementów
został powszechnie przyjęty do nauki programowania oraz jako język
publikacyjny. Umożliwia tworzenie programów czytelnych, efektywnych i
bezbłędnych.
Podstawowe elementy języka
Język Pascal jest wyposażony w podstawowe konstrukcje sterujące
wykorzystywane w programowaniu strukturalnym:
• grupowanie instrukcji ( begin ... end;);
• podejmowanie decyzji ( if );
• powtarzanie ze sprawdzaniem warunku zatrzymania na początku (while,
for) lub na końcu pętli (repeat until);
• wybór jednego z kilku możliwych przypadków (case of);
• procedury i funkcje (podprogramy).
Ponadto, w języku Pascal występują wskaźniki, które służą do przechowywania adresów oraz wykonywania różnych operacji na łańcuchach i blokach
pamięci.
W języku Pascal możliwe są dwa sposoby przekazywania argumentów do
procedur i funkcji:
• przekazywanie przez wartości – argumenty są kopiowane do procedur
(funkcji); nie jest możliwa zmiana wartości argumentów w miejscu
wywołania funkcji;
• przekazywanie przez zmienne (adresy zmiennych) – do funkcji są
przesyłane adresy argumentów; funkcja ma możliwość zmiany wartości
argumentów.
Procedury i funkcje można wywoływać rekurencyjnie. Zmienne lokalne
procedur i funkcji są „automatyczne”, tzn. tworzone na nowo przy każdym jej
wywołaniu. Definicje procedur i funkcji mogą być zagnieżdżone, a ponadto
mogą być zawarte w modułach (units) zapisanych w różnych plikach i
kompilowanych osobno.
W języku Pascal dane przechowywane są w zmiennych i stałych.
Zmienne w języku Pascal można podzielić na:
• zmienne wewnętrzne procedur i funkcji;
• zmienne zewnętrzne, ale znane w obrębie jednego modułu;
• zmienne zewnętrzne o charakterze globalnym (widoczne w obrębie całego
programu).
W języku Pascal możliwe są konwersje typów danych (tzw. rzutowanie
zmiennych i wskaźników). Język ten dostarcza narzędzi wejścia i wyjścia
umożliwiających automatyczny dostęp do plików, np. za pomocą procedur
READ (czytaj) lub WRITE (pisz). Są to w przypadku języka Pascal
mechanizmy wbudowane, które są dostępne w każdym programie bez
konieczności dołączania dodatkowych bibliotek.
Zalety języka Pascal
• Wysoka użyteczność – język udostępnia większość funkcji sterujących,
które są pożądane w teorii i praktyce programowania strukturalnego.
• Brak zbędnych elementów i dobra wydajność - język charakteryzuje
wysoka przejrzystość, a przy tym dobra efektywność.
• Łatwość opanowania – język posiada niezbyt duży zbiór podstawowych
konstrukcji strukturalnych i może być stosunkowo łatwo opanowany.
Wady języka Pascal
• Brak rozbudowanych bibliotek.
• Mała przenośność oprogramowania pomiędzy różnymi systemami.
• Brak rozróżnienia dużych i małych liter w identyfikatorach.
• Niska efektywność kodu wynikowego.
Znaczną część wymienionych wad eliminują współczesne implementacje
Pascala. Rozszerzają one Pascal wzorcowy o możliwość programowania
obiektowego, programowania w trybie rzeczywistym i wirtualnym z ochroną
dostępu oraz programowania pod Windows.
Do najpopularniejszych pakietów umożliwiających programowanie w
języku Pascal w środowisku MS Windows należą: system Borland Pascal 7.0
opracowany w 1992 roku przez firmę Borland oraz jego następca system
Delphi wprowadzony na rynek w 1995 roku. Oba systemy udostępniają zintegrowane środowiska programowania IDE (ang. Integrated Developement
Environment), które łączą w jedną całość podstawowe narzędzia umożliwiające tworzenie i uruchamianie programów: kompilator, linker, edytor i
program uruchomieniowy (debugger). Ponadto IDE zawierają rozbudowane
systemy pomocy kontekstowej, które udostępniają użytkownikom obszernych
informacji na temat samego środowiska oraz języka programowania.
1.3. Metodologia programowania
Punktem wyjścia dla każdego programu jest algorytm umożliwiający
rozwiązanie określonego zadania. Algorytm można przedstawić na wiele
różnych sposobów:
- w postaci opisu słownego,
- w postaci listy kroków,
- w postaci schematu blokowego (postać graficzna algorytmu),
- za pomocą jednego z języków formalnych (np. UML).
Proste algorytmy mogą zostać opisane bezpośrednio w języku programowania. W dalszej części przedstawiono przykłady tworzenia programów
umożliwiających rozwiązanie określonych zadań.
Problem 1. Znaleźć minimum spośród dwóch liczb całkowitych a i b.
Wyprowadzić wartość minimum. Jeśli liczby są równe, to wyprowadzić
odpowiedni komunikat.
Opis słowny algorytmu
Po wczytaniu danych wejściowych a i b porównać wprowadzone liczby.
Jeśli a < b, to min = a. Wyprowadzić wynik. Jeśli a >= b, to sprawdzić
czy b < a. Jeśli tak, to min = b. Wyprowadzić wynik. W przeciwnym
przypadku min = a = b. Wyprowadzić wynik.
Opis algorytmu za pomocą listy kroków
Krok 1. Wprowadź dwie liczby całkowite a i b. Przejdź do kroku 2.
Krok 2. Jeśli a < b, to podstaw min = a, wyprowadź wynik min = a.
Przejdź do kroku 5. W przeciwnym przypadku przejdź do kroku 3.
Krok 3. Sprawdź, czy b < a? Jeśli tak, to podstaw min = b, wyprowadź wynik
min = b. Przejdź do kroku 5. W przeciwnym przypadku przejdź
do kroku 4.
Krok 4. Podstaw min = a, wyprowadź wynik min = a = b. Przejdź do kroku 5.
Krok 5. Zakończ program.
Postać graficzna algorytmu (sieć działań)
W sieciach działań (schematach blokowych) definiujących algorytmy są
wykorzystywane następujące bloki.
• Blok początkowy (start programu)
START
• Blok wejścia / wyjścia (wprowadzanie lub wyprowadzanie danych)
Wprowadź
Wyprowadź
• Blok operacyjny (wykonywanie działań)
Operacja
• Blok decyzyjny (warunkowy)
Warunek
?
Tak
Nie
• Blok wyboru (wybór jednego z możliwych wariantów w zależności
od wartości zmiennej lub wyrażenia)
Zmienna =
Wyrażenie =
w1 w2 ... wi ... wn
• Blok podprogramu (definiuje nazwę funkcji i realizowane przez nią
zadania)
Nazwa funkcji
Zadania
• Blok kolekcyjny (łączy dwie różne drogi algorytmu)
• Blok wejściowy lub wyjściowy łącznika na stronie (przejście pomiędzy
fragmentami algorytmu w ramach tej samej strony)
N
• Blok wejściowy lub wyjściowy łącznika stronicowego (przejście pomiędzy
fragmentami algorytmu znajdującymi się na różnych stronach)
Strona
| Nr
• Blok końcowy (koniec programu)
STOP
Opisując algorytmy za pomocą sieci działań należy pamiętać, aby:
- do każdego bloku dochodziła jedna strzałka,
- linie łączące bloki nie rozgałęziały się.
Schemat blokowy algorytmu wyznaczania min(a,b)
START
Wprowadź a = ?
Wyprowadź b = ?
a<b
Tak
min = a
Pisz
min = a
min = b
Pisz
min = b
Nie
b<a
Nie
min = a
Pisz
min = a = b
STOP
Tak
Implementacja algorytmu w postaci programu w języku Pascal
{ Obliczanie min(a,b) }
uses crt;
{ dla clrscr }
{ zmienne globalne do przechowywania danych }
Var a, b, min: integer;
begin { początek programu }
clrscr; { wyczysc ekran }
writeln('Wprowadz dane');
readln(a);
readln(b);
if (a<b) then
begin min:=a; writeln('Min = a = ', a); end
else
if (b<a) then
begin min:=b; writeln('Min = b = ', b); end
else
begin min:=a; writeln('Min = a = b = ', a); end;
end.
Implementacja algorytmu w postaci programu w języku C
#include <stdio.h>
#include <conio.h>
// dla printf i scanf
// dla clrscr i getch
int a, b, min;
//zmienne globalne
//do przechowywania danych
// Obliczanie min(a,b)
void main(void) // główna (startowa) funkcja programu
{
clrscr();
// wyczyść ekran
printf("Wprowadz dane \n");
scanf("%d", &a);
scanf("%d", &b);
if (a<b) { min=a; printf("\nMin = a = %d \n", a); }
else
if (b<a) { min=b; printf("\nMin = b = %d \n", b); }
else { min=a; printf("\nMin = a = b = %d \n", a); }
getch();
// czekaj na enter
}
Problem 2. Znaleźć minimum spośród n wczytanych liczb a0, a1, ... , an-1.
Wyprowadzić wartość minimum.
Opis słowny algorytmu
Po wczytaniu danych wejściowych ai, dla i=0, ... , n-1, przyjąć min = a0. Jeśli
są jeszcze elementy do sprawdzenia (0<n-1), to sprawdzić czy ai < min, dla
i=1? Jeśli tak, to podstawić min = ai. Powtórzyć sprawdzenie dla i=2, ... , n-1.
Wyprowadzić wynik.
Opis algorytmu za pomocą listy kroków
Krok 1. Wczytaj dane a0, ..., an-1.
Krok 2. Podstaw min = a0 oraz i = 1.
Krok 3. Jeśli i > n-1 (nie ma więcej elementów), to przejdź do kroku 6.
Krok 4. Jeśli ai < min, to podstaw min = ai.
Krok 5. Podstaw i = i + 1. Przejdź do kroku 3.
Krok 6. Wyprowadź wartość min.
Krok 7. Zakończ program.
Schemat blokowy algorytmu znajdowania min(a0, ..., an-1)
START
Wprowadź n = ?
i=0
Wprowadź ai = ?
i = i+1
Nie
i > n-1
Tak
i=0
min = a0
i = i+1
Nie
Tak
Nie
i > n-1
Tak
Pisz min
STOP
ai < min
min = ai
Implementacja algorytmu w postaci programu w języku Pascal
uses crt; {moduł zawierający procedurę clrscr}
{ Obliczanie min(a[0],a[1], ... ,a[n-1]) }
const ROZ = 10; { stala - maksymalny rozmiar tablicy}
{definicja typu tablicy}
type
ttab = array[1..ROZ] of integer;
Var
{a - zmienna tablicowa typu ttab - rezerwacja pamieci}
{min - zmienna przechowujaca wartosc minimum}
a: ttab;
min: integer;
n,i: integer; {zmienne pomocnicze}
{n < ROZ liczba wprowadzanych (losowanych) elementow}
{i zmienna pomocnicza indeksujaca kroki petli}
Begin {poczatek programu}
clrscr; { wyczysc ekran }
randomize; { inicjuj generator liczb losowych }
writeln('Wprowadz liczbe elementow 0 < n <= ', ROZ);
readln(n);
if (0<n) and (n<=ROZ) then
{ czy n < = ROZ ? }
begin
for i:=1 to n do
begin
{losowanie danych z zakresu od 0 do 99 }
a[i]:= random(100); writeln('a[', i, '] = ', a[i]);
end;
i:=1;
{ wart. pocz. i }
min:= a[1];
{ wartosc pocz. minimum }
i:=i+1;
while (i<=n) do
begin
if (a[i] < min) then min:= a[i];
i:= i+1;
end;
writeln; { przejscie do nowej linii }
writeln('Wartosc minimum = ', min);
end
else
begin
writeln; writeln('Wartosc n wykracza poza zakres !');
writeln('Uruchom ponownie program !');
end;
readln; { czekaj na enter }
End.
{ koniec programu }
Przykładowe wyniki:
Wprowadz liczbe elementow 0 < n <= 10
5
a[1] = 93
a[2] = 1
a[3] = 93
a[4] = 73
a[5] = 6
Wartosc minimum = 1
Implementacja algorytmu w postaci programu w języku C++
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
// Obliczanie min(a[0],a[1], ... ,a[n-1])
// Zmienne globalne
const ROZ = 10;
// stała określająca
// maksymalny rozmiar tablicy
int a[ROZ]; //tablica - zawsze od 0, tj. a[0],...,a[ROZ-1]
int min; //wartosc minimum
void main(void)
//glowna (startowa) funkcja programu;
// void - bezparametrowa
{ // Zmienne lokalne funkcji main()
int n;
//liczba n < ROZ wprowadzanych
//(losowanych) elementów
int i;
//zmienna pomocnicza indeksująca kroki pętli
clrscr();
// wyczyść ekran
randomize();
// inicjuj generator liczb losowych
printf("Wprowadź liczbę elementów 0 < n <= %d \n", ROZ);
scanf("%d", &n);
if (0<n && n<=ROZ) {
// czy n nie przekracza ROZ?
for (i=0; i<n; i++) {
a[i] = random(100); // losowanie danych
printf("a[%d] = %d \n", i, a[i]); }
i=0;
// wart. pocz. i
min = a[0]; // wart. pocz. minimum
i=i+1;
while ( !(i>n-1) ) {
if (a[i] < min) min = a[i];
i++;
// i = i+1
}
printf ("\n Wartosc minimum = %d \n", min);
} else
{ printf("\nWartosc n wykracza poza zakres !\n");
printf("Uruchom ponownie program\n");
}
getch(); //czekaj na enter
}
1.4. Ogólna struktura programu w języku Pascal
Najprostszy program nie wykonuje żadnego zadania, a jedynie zawiera
informacje o miejscu rozpoczęcia głównej procedury programu i miejscu jej
zakończenia.
Przykład 1. Najprostszy program.
START
STOP
BEGIN
{ komentarz - najprostszy program w języku Pascal }
END.
Przykład 2. Wyprowadzenie napisu na ekran i zatrzymanie programu
w oczekiwaniu na Enter.
Begin {poczatek programu}
START
writeln('To jest tekst!');
readln; { czekaj na enter }
End. { koniec programu }
Wyświetl tekst:
‘To jest tekst!’
Czekaj na Enter
STOP
Przykład 3. Obliczanie sumy dwóch liczb całkowitych a i b.
Schemat blokowy
START
Czyść ekran
Wczytaj a i b
suma = a + b
Pisz
‘Suma liczb = ‘, suma
Czekaj na Enter
STOP
Program w języku Pascal
uses crt;
{ modul definiujacy procedure clrscr }
{ obliczanie sumy liczb całkowitych}
Var a, b: integer;
suma: longint;
{ zmienne calkowite od -32768.. 32767 }
{ suma - zmienna calkowita o wiekszym }
{ zakresie od -2147483648..2147483647 }
Begin {poczatek programu}
clrscr;
{ czyszczenie ekranu }
write('Podaj liczbe calkowita a = '); readln(a);
write('Podaj liczbe calkowita b = '); readln(b);
suma:=a+b;
writeln('Suma liczb = ', suma);
readln;
End.
{ czekaj na enter }
{ koniec programu }
Ogólna struktura programu w języku Pascal
program nazwa_programu;
{Nagłówek programu - opcjonalny}
............................................................................ { SEKCJA DEKLARACJI }
uses
lista_nazw_modułów ;
const
sekwencja_definicji_stałych ;
{Definicje stałych}
type
sekwencja_definicji_typów ;
{Definicje typów}
label
lista_etykiet ;
{Deklaracja etykiet}
var
sekwencja_deklaracji_zmiennych ;
{Deklaracje zmiennych}
procedure nazwa_procedury_1 ;
{Definicje procedur}
{Definicje_składowych_procedury_1 – kod procedury}
procedure nazwa_procedury_2 ( lista_parametrów ) ;
{Definicje_składowych_procedury_2 – kod procedury}
. . .
function nazwa_funkcji_1 : typ_wartosci ;
{Definicje funkcji}
{Definicje_składowych_funkcji_1 – kod funkcji}
function nazwa_funkcji_2( lista_parametrów ) : typ_wartości ;
{Definicja_składowych_funkcji_2 – kod funkcji}
. . .
............................................................................. { SEKCJA INSTRUKCJI }
begin
instrukcja_1 ;
instrukcja_2 ;
...
instrukcja_N ;
end .