ażanie operatorów
1
Cel zadanie
Realizacja niniejszego zadania powinna unaocznić wybrane cechy, które są wspólne dla języ-ków C i C++ oraz te, które je różnią. Drugim podcelem niniejszego zadania jest zapoznanie się z podstawowymi mechanizmami przeciążania operatorów.
2
Opis zadania
2.1
Różnice C i C++
W tej części należy obejrzeć dostarczone przykładowe programy napisane w języku C. Następnie należy przeprowadzić ich kompilację i konsolidację, aby uzyskać program wykonywalny.
Operację należy wykonać za pomocą kompilatora języka C (zalecane jest przeprowadzenie tej operacji zarówno za pomocą kompilatora cc jak też gcc). Następnie należy tę operację powtó-
rzyć używając kompilatora języka C++. Jeżeli proces ten zakończył się powodzeniem, to należy porównać działanie programów.
Jeżeli proces kompilacji lub konsolidacji nie powiódł się, należy spróbować znaleźć przyczynę. Podobnie jeśli okaże się, że działanie programów różni się. Niezbędne informacje zamieszczone są w materiałach dostępnych pod adresem: http://rab.ict.pwr.wroc.pl/˜kreczmer/po/materialy/roznice.pdf Znalezione przyczyny dla poszczególnych przypadków należy krótko opisać i dostarczyć jako sprawozdanie z realizacji zadania.
Poniżej opisany jest sposób postępowania dla czterech dostarczonych programów, których działanie należy wypróbować i porównać. Źródła programów znajdą się na diablo w podkatalogu: ˜bk/edu/po/zad/z1. Zalecane jest utworzenie analogicznej struktury podkartotek i przekopiowanie całej zawartości, np.:
mkdir -p ~/po/zad
cd
~/po/zad
cp -r ~bk/edu/po/zad/z1 .
cd
z1
W podkatalogu z1 znajdują się następujące podkatalogi: test1, test2, test3, test4, oper, zly_program. Pierwsza część zadania dotyczy zawartości czterech pierwszych podkatalogów.
2.1.1
z1/test1
W podkatalogu tym znajduje się plik rownanie.c. Zawiera on kod programu obliczającego pierwiastki równania kwadratowego. Należy utworzyć program wykonywalny za pomocą kompilatora języka C i C++, a następnie porównać jego działanie.
2.1.2
z1/test2
W podkatalogu znajduje się plik konwerter.c. Należy przeprowadzić analogiczne operacje jak w punkcie poprzednim.
1
z1/test3
W podkatalogu znajduje się pliki: prog.c i modul.c. Należy przeprowadzić osobną kompilację i konsolidację za pomocą kompilatora/konsolidatora dla języka C i C++. Następnie należy porównać otrzymane wyniki. Przykładowy sposób postępowania: Kompilacja i konsolidacja dla języka C
cc -c modul.c
# etap kompilacji modułu pomocniczego
cc -c prog.c
# etap kompilacji modułu głównego
cc prog.o modul.o
# konsolidacja
Kompilacja i konsolidacja dla języka C++
CC -c modul.c
# etap kompilacji modułu pomocniczego
CC -c prog.c
# etap kompilacji modułu głównego
CC prog.o modul.o
# konsolidacja
2.1.4
z1/test4
W podkatalogu, tak jak wcześniej, znajduje się pliki: prog.c i modul.c. Należy przeprowadzić identyczne operacja jak we wcześniejszym podpunkcie i dokładnie w takiej samej kolejności.
3
Poprawność programów, plik core
W podkatalogu zly_program znajduje się program przetworz.c. Zawiera on jeden istotny błąd. Aby go zidentyfikować, konieczne jest przetestowanie programu. Najpier należy go skompilować na diablo wykorzystując kompilator cc, a następnie uruchomić program.
cc przetworz.c
./a.out
Po jego uruchomieniu należy sprawdzić, czy wyświetlane wyniki są poprawne. Następnie wspomniany program należy skompilować za pomocą kompilatora gcc i uruchomić otrzymany plik wynikowy.
gcc przetworz.c
./a.out
Jeżeli program spowodował błąd naruszenia pamięci i pojawił się plik core, to trzeba podjąć próbę zlokalizwania źródła problemu poprzez obejrzenie zawartości stosu wywołań funkcji. W
tym celu należy uruchomić program gdb.
gdb a.out core
Wyświetlenie stosu wywołań można uzyskać poprzez polecenie bt. Zakończenie współpracy z programem dokonujemy za pomocą polecenia q. Następnie należy powtórnie skompilować program w trybie generacji dodatkowej informacji dla debugera (opcja -g).
gcc -g przetworz.c
Tak jak poprzednio należy uruchomić program wywołaniem ./a.out, a następnie obejrzeć stos wywołań funkcji za pomocą debugera gdb. Na podstawie otrzymanych informacji trzeba zlokalizować źródło błędu i wyjaśnić przyczynę dziwnego zachowania się programu.
2
Przeci ˛
ażanie operatorów
W podkatalogu oper znajduje się plik dzialania.cpp. Jest on szkieletem programu, który należy uzupełnić tak, aby utworzyć program implementujący strukturę algebraiczną pierścienia S = ( S + ∗), gdzie S = { e a b c d} jest zbiorem symboli, + – operacja dodawania, ∗ – opera-
,
,
,
,
,
,
cja mnożenia.
Tabelki dla obu działań mają postać:
Działanie "+"
Działanie "∗"
e
a
b
c
d
e
a
b
c
d
e
e
a
b
c
d
e
e
e
e
e
e
a
a
b
c
d
e
a
e
a
b
c
d
b
b
c
d
e
a
b
e
b
d
a
c
c
c
d
e
a
b
c
e
c
a
d
b
d
d
e
a
b
c
d
e
d
c
b
a
Przedstawione tabelki reprezentują działanie modulo 5, z tą różnicą, że jest ono wykonywane na symbolach.
W programie należy dokonać odpowiedniego przeciążenia operatorów, aby zaimplementować operacje ”dodawania” i ”mnożenia”. Operacje te należy zaimplementować za pomocą funkcji Dodaj oraz Mnoz.
W programie należy te same wyrażenie arytmetyczne podane przez prowadzącego zapisać i obliczyć za pomocą wywołań funkcji Mnoz i Dodaj, a następnie również wywołań operatorów.
Wynik obliczeń powinien zostać porównany i wyświetlony komunikat, czy wyniki obliczeń są identyczne, czy też nie.
Materiały pomocnicze można znaleźć w dokumencie pod adresem: http://rab.ict.pwr.wroc.pl/˜kreczmer/po/materialy/operatory-cz1.pdf 3
Zawartość pliku dzialania.cpp
#include <iostream>
using namespace std;
/*
Definicja typu wyliczeniowego "Symbol" dla symboli a, b, c, d, e.
*/
/*
Definicja funkcji Dodaj i Mnoz
*/
/*
Definicja przeciążeń operatorów
*/
void Porownaj(Symbol wynik_alg, Symbol wynik_ope, Symbol wynik_fun)
{
cout << ((wynik_alg == wynik_fun) ? "Identyczne" : "Rozne")
<< " wyniki wyrazenia algebraicznego i funkcyjnego." << endl; cout << ((wynik_ope == wynik_fun) ? "Identyczne" : "Rozne")
<< " wyniki wyrazenia operatorowego i funkcyjnego." << endl; cout << ((wynik_ope == wynik_alg) ? "Identyczne" : "Rozne")
<< " wyniki wyrazenia operatorowego i algebraicznego." << endl;
}
int main()
{
Symbol wynik_alg, wynik_ope, wynik_fun;
wynik_alg = WYRAZENIE_ALG; // <- Wyrażenie zapisane w sposób zwyczajowy wynik_fun = WYRAZENIE_FUN; // <- Wyrażenie wykorzystujące funkcje wynik_ope = WYRAZENIE_OPE; // <- Wyrażenie z jawnym wywołaniem operatorów Porownaj(wynik_alg,wynik_ope,wynik_fun);
return 0;
}
4
Przykład realizacji zapisu działań dla wyrażenia: (e + a) * c wynik_alg = (e + a) * c;
wynik_fun = Mnoz(Dodaj(e,a),c);
wynik_ope = operator * (operator + (e,a), c); 5