Laboratorium programowania w C

background image

Jacek Czekaj,

Data ostatniej modyfikacji: 30.IX.2009.

Instytut Matematyki,
Uniwersytet Śląski

Laboratorium programowania w C++

0. Literatura

[1] Brian W. Kernighan, Dennis M. Ritchie, Język ANSI C, Wydawnictwa Naukowo-Techniczne.
[2] Bjarne Stroustrup, Język C++, Wydawnictwa Naukowo-Techniczne.

1. Podstawy  powtórka z C

Zadanie 1.1. Opisać działanie poniższego programu.

#include <iostream>
using namespace std;

int main(int argc, char** argv) {

int i;

cout << "Wpisz 0 lub 1: ";

cin

>> i;

switch (i) {

case

0: cout << "Wpisano liczbe 0.";

case

1: cout << "Wpisano liczbe 1.\n";

default: cout << "Wpisano liczbe rozna od 0 i 1.\n";

}

return 0;

}

Zadanie 1.2. Opisać działanie poniższego programu.

#include <iostream>
#include <cstring>
using namespace std;

int main(int argc, char** argv) {

union rekord {

char kategoriaWojskowa;
char nazwiskoPanienskie[256];

} r;

r.kategoriaWojskowa = ’E’;

strcpy(r.nazwiskoPanienskie, "Nowak");

cout << r.nazwiskoPanienskie << endl << r.kategoriaWojskowa;

return 0;

}

Zadanie 1.3. Opisać działanie poniższego programu.

#include <iostream>
using namespace std;

int main(int argc, char** argv) {

1

background image

const int i = 123;
const int * p;

cout << i << endl;

p = &i;

*p = 997;

cout << i << endl;

return 0;

}

Zadanie 1.4.

Wykorzystując wskaźniki, wypisać wartości wszystkich bajtów, które składają się na wewnętrzną

reprezentację liczby typu int. Wykonać to samo zadanie wykorzystując unie.

Przykładowe rozwiązanie:

#include <iostream>
using namespace std;

int main(int argc, char** argv) {

int n;

cout << "Podaj jakas liczbe calkowita: ";
cin

>> n;

union {

int n;
unsigned char c[sizeof(int)];

} u;
u.n = n;
for(int i = 0; i < sizeof(int); i ++)

cout << u.c[i] << ", ";

cout << endl;

unsigned char *c = (unsigned char *) &n;
for(i = 0; i < sizeof(int); i++)

cout << *(c+i) << ", ";

return 0;

}

Zadanie 1.5. Przeanalizować działanie poniższego programu.

#include <iostream>
#define MAX_X 10
#define MAX
_Y 15
using namespace std;

int main(int argc, char ** argv) {

int ** tab = new int * [MAX_Y];

tab[0] =

new int [MAX_X * MAX_X];

for (int y = 1; y < MAX_Y; y ++)

tab[y] = tab[y-1] + MAX_X;

for (int y = 0; y < MAX_Y; y ++)

for (int x = 0; x < MAX_X; x ++)

tab[y][x] = x*y;

for (int y = 0; y < MAX_Y; y ++) {

for (int x = 0; x < MAX_X; x ++)

2

background image

cout << tab[y][x] << ", ";

cout << endl;

}

delete [] tab[0];
delete [] tab;

return 0;

}

Zadanie 1.6. Napisz program, który zapyta użytkownika o imię i nazwisko, po czym napisze „Witam Panią!”, albo

„Witam Pana!”, w zależności od płci użytkownika.

Zadanie 1.7. Napisz program, który zapyta użytkownika o jedgo numer PESEL i numer albumu, po czym napisze

„Witam Panią!”, albo „Witam Pana!”, w zależności od płci użytkownika.

Zadanie 1.8. Napisać program obliczający medianę z podanych liczb.

Zadanie 1.9. Napisać program, który obliczy i wypisze iloczyn macierzy o wartościach i wymiarach wprowadzonych

przez użytkownika.

2. Strumienie wejścia/wyjścia

Zadanie 2.1. Przeanalizować działanie poniższego programu.

#include <iostream>
#include <fstream>
using namespace std;

int main(int argc, char **argv)
{

//TEST STRUMIENI WYJSCIOWYCH

cout << "standardowy strumien wyjsciowy znakow\n";

cerr << "standardowy niebuforowany strumien wyjsciowy komunikatow o bledach\n";

clog << "standardowy strumien wyjsciowy komunikatow o bledach\n";

wcout << "szeroki strumien odpowiadajacy cout\n";

wcerr << "szeroki strumien odpowiadajacy cerr\n";

wcerr << "szeroki strumien odpowiadajacy clog\n";

//wypisywanie liczb calkowitych

cout << "\n" << 123

<< ", " << showpos << 123;

cout.unsetf(ios_base::showpoint|ios_base::showpos);

cout << ", " << 123

<< ", " << showpos << 123;

cout.unsetf(ios_base::showpoint|ios_base::showpos);

cout << "\n" << oct << 64

<< ", " << showbase << 64 << endl;

cout << "\n" << hex << 64

<< ", " << showbase << 64

<< ", " << uppercase << 64 << endl;

cout.unsetf(ios_base::hex|ios_base::showbase|ios_base::uppercase);

//wypisywanie wartosci boole-owkich

cout <<

"true = " << true << ", false = " << false << endl;

cout << boolalpha << "true = " << true << ", false = " << false << endl;

cout <<

"true = " << true << ", false = " << false << endl;

3

background image

//wypisywanie liczb zmiennopozycyjnych

cout << "\nformat domyslny: " << 1234.56789; //zostanie zaokraglone, a nie obciete!!!

cout.setf(ios_base::scientific,ios_base::floatfield); //maksymalnie 2 argumenty

cout << "\nformat naukowy: " << 1234.56789;

cout.setf(ios_base::scientific,ios_base::floatfield);

cout << "\njszcze raz format naukowy: " << uppercase << 1234.56789;

cout.setf(ios_base::fixed,ios_base::floatfield);

cout << "\nformat staly: " << 1234.56789;

cout.setf(ios_base::floatfield);

cout << "\nznowu format domyslny: " << 1234.56789;

cout.precision(8);

cout << "\nzmiana domyslnej precyzji (bylo 6): " << 1234.56789 << ", " << 1234.56789;

cout.precision(4);

cout << "\nkolejna zmiana: " << 1234.56789 << ", " << 1234.56789;

//pola wyjsciowe

cout << "\n";

cout.width(4);

cout << "ab";

cout.width(4);

cout << "\n";

cout << "ab"; //teraz nie bedzie spacji wiodacych!!!

cout.width(4);

cout.fill(’0’);

cout << endl << "ab";

cout.width(4);

cout.fill(’0’);

cout << endl << 12 << ’,’ << 13; //nie wypisze 0012000,0013 tylko 0012:13 !!!

cout.fill(’0’);

cout.width(6);

cout.setf(ios_base::left,ios_base::adjustfield);

cout << endl << -12;

cout.width(6);

cout.setf(ios_base::right,ios_base::adjustfield);

cout << endl << -12;

cout.width(6);

cout.setf(ios_base::internal,ios_base::adjustfield);

cout << endl << -12;

//wypisywanie wskaznikow
int i;
int *p = new int;
cout << "\nlokalnie: " << &i << ", pamiec wolna: " << p;

//TEST STRUMIENI WEJSCIOWYCH
char s[4];
cout << "\nPROSZE NA TERMINALU WPISAC NAPIS MAJACY WIECEJ NIZ TRZY ZNAKI\n";

cin

>> s; //standardowy strumien wejsciowy znakow

cout << s << endl;

cout << "\nPROSZE ZNOWU NA TERMINALU WPISAC NAPIS MAJACY WIECEJ NIZ TRZY ZNAKI\n";

cin.width(4); //nastepne cin wczyta co najwyzej trzy znaki i doda na koniec ’\0’

cin

>> s;

cout << s << endl;

cout << "\nPROSZE JESZCZE RAZ NA TERMINALU WPISAC NAPIS MAJACY WIECEJ NIZ TRZY ZNAKI\n";

cin.get(s, 4, ’\0’);

cout << s << endl;

4

background image

//TEST STRUMIENI PLIKOWYCH

ifstream fin ( "streams_test.cpp", ios_base::binary);

ofstream fout("˜streams_test.cpp", ios_base::binary);
unsigned char c;
fin >> noskipws;
while (!fin.eof()) {

fin

>> c;

fout << c;

}

fin.close();

fout.close();

//NA KONIEC COS, NA CO TRZEBA UWAZAC!!!
int x = 0;
cout << x << ++x << ++x << std::endl; // 221 zamiast 012

return 0;

}

Zadanie 2.2. Napisać program rysujący „choinkę” o zadanej przez użytkownika wysokości. Np. choinka o wysokości

4 powinna wyglądać następująco:

*
*

***

*

***

*****

*

***

*****

*******

Przykładowe rozwiązanie:

#include <iostream>
using namespace std;

int main(int argc, char** argv) {

int liczbaSegmentow;
cout << "Podaj liczbe ,,segmentow’’ choinki: ";

cin

>> liczbaSegmentow;

for (int segment = 1; segment <= liczbaSegmentow; segment ++)

{

for (int liniaSegmentu = 1; liniaSegmentu <= segment; liniaSegmentu ++)

{

for (int spacja = 1; spacja <= liczbaSegmentow-liniaSegmentu; spacja ++)

cout << ’ ’;

for (int gwiazdka = 1; gwiazdka <= 2*liniaSegmentu-1; gwiazdka ++)

cout << ’*’;

cout << endl;

}

}

return 0;

}

Zadanie 2.3. Napisać program wypełniający „po spirali” tablicę kwadratową o zadanej wielkości boku.

Przykładowe rozwiązanie:

#include <iostream>
using namespace std;

int main(int argc, char** argv) {

5

background image

int i, n, x = 0, y = 0, dir = 0, tab[100][100];

cout << "Podaj rozmiar tablicy (max 100): ";

cin

>> n;

for (i = 1; i <= n*n; i ++) {

if (x+y==n-1 || (x==y && x>=n/2) || (x+1==y && x<n/2))

dir = (dir+1) % 4;

tab[y][x] = i;

x += dir==0?1:(dir==2?-1:0);

y += dir==1?1:(dir==3?-1:0);

}

for (y = 0; y < n; y ++) {

for (x = 0; x < n; x ++) {

cout.width(4);

cout << tab[y][x];

}

cout << endl;

}

return 0;

}

Zadanie 2.4. Wykorzystując strumieine plikowe, napisać program, który będzie przyjmował dwa argumenty ozna-

czające odpowiednio nazwę pliku wejściowego oraz nazwę pliku wyjściowego, a następnie z podanego pliku wejściowego
usunie wszystkie komentarze w stylu języka C++, a wynik zapisze do podanego pliku wyjściowego.

Przykładowe rozwiązanie:

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

int main(int argc, char** argv) {

ifstream

fin(argv[1], ios_base::binary);

ofstream fout(argv[2], ios_base::binary);
unsigned char c, o = 0;
int state = 0;

fin >> noskipws;
while (!fin.eof()) {

fin >> c;

if (state == 0)

state = 1;

else if (state == 1 && o == ’/’ && c == ’/’)

state = 2;

else if (state == 1 && o == ’/’ && c == ’*’)

state = 3;

else if (state == 1)

fout << o;

else if (state == 2 && c == ’\n’)

{ state = 0; fout << c; }

else if (state == 3 && o == ’*’ && c == ’/’)

state = 0;

o = c;

}

fin.close();

fout.close();

return 0;

}

3. Biblioteka standardowa STL

Zadanie 3.1. Przeanalizować działanie poniższego programu.

6

background image

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;

class inicjal {

public:

inicjal(

char cc): c(cc) { }

bool

operator()(const string &s) const { return (s[0] == c); }

private:

const char c;

};

class nieInicjal {

public:

nieInicjal(

char cc): c(cc) { }

bool

operator()(const string &s) const { return (s[0] != c); }

private:

const char c;

};

inline bool specialStringsCompare(const string &s, const string &t) {

string::

const_iterator is = s.begin();

string::

const_iterator it = t.begin();

while (is != s.end() && it != t.end() && toupper(*is) == toupper(*it)) {

is ++;

it ++;

}

if (is == s.end())

return it != t.end();

if (it == t.end())

return false;

return toupper(*is) < toupper(*it);

}

class printElement {

public:

printElement(ostream& out) : os(out) {}
void operator() (const string &s) const { os << s << endl; }
ostream& os;

};

void printElement2(const string &s) {

cout << s << endl;

}

struct pairOfDoubles {

double x, y;
pairOfDoubles(

double xx = 0, double yy = 0) : x(xx), y(yy) {}

};

int main(int argc, char** argv) {

char s1[] = "Wektor zainicjowany przy konstrukcji napisem w stylu C...";
char s2[] = "Wektor zainicjowany _po_ konstrukcji napisem w stylu C...";
int

i;

vector<

char> vc1(s1, s1 + sizeof(s1) - 1); //vector<char> vc1(s1, &s1[sizeof(s1) - 1]);

vector<

char> vc2;

7

background image

vc2.assign(s2, s2 +

sizeof(s2) - 1);

cout << "\nwektor vc1 (dostep poprzez przeciazony operator []):\n";
for (i = 0; i < vc1.size(); i ++)

cout << vc1[i];

cout << endl;

vector<

char>::iterator ivc;

cout << "\nwektor vc2 (dostep poprzez iterator):\n";
for (ivc = vc2.begin(); ivc != vc2.end(); ivc ++)

cout << *ivc;

cout << endl;

vector<string> vs;

vs.push_back("kiwi");

vs.push_back("Mango");

vs.push_back("mango");

vs.push_back("gruszka");

vs.push_back("awokado");

vs.push_back("morela");

vs.push_back("zurawina");

cout << "\nwektor vs (dostep poprzez przeciazony operator []):\n";
for (i = 0; i < vs.size(); i ++)

cout << vs[i] << endl;

sort(vs.begin(), vs.end());

cout << "\nwektor vs (wynik po sortowaniu):\n";
for (i = 0; i < vs.size(); i ++)

cout << vs[i] << endl;

sort(vs.begin(), vs.end(), specialStringsCompare);

cout << "\nvektor vs (wynik po specjalnym sortowaniu):\n";
for (i = 0; i < vs.size(); i ++)

cout << vs[i] << endl;

sort(vs.begin(), vs.end());

vector<string>::iterator ivs1 = find_

if(vs.begin(), vs.end(), inicjal(’m’));

vector<string>::iterator ivs2 = find_

if(ivs1

, vs.end(), nieInicjal(’m’));

vs.erase(ivs1, ivs2);

cout << "\nwektor vs (wynik po usunieciu owocow na ’m’):\n";
for (i = 0; i < vs.size(); i ++)

cout << vs[i] << endl;

list<string> l1, l2;

l1.push_back ("kiwi");

l1.push_back ("Mango");

l1.push_back ("mango");

l1.push_front("gruszka");

l1.push_front("gruszka");

l2.push_front("mango");

l2.push_front("gruszka");

l2.push_back ("awokado");

l2.push_back ("morela");

l2.push_back ("zurawina");

8

background image

list<string>::iterator ils;

cout << "\nlista l1 (dostep poprzez iterator):\n";
for (ils = l1.begin(); ils != l1.end(); ils ++)

cout << *ils << endl;

cout << "\nna liscie l1 sa " << count(l1.begin(), l1.end(), "gruszka")

<< " wpisy \"gruszka\"\n";

if (find(l1.begin(), l1.end(), "kiwi") != l1.end())

cout << "\nna liscie l1 jest element \"kiwi\"\n";

else

cout << "\nna liscie l1 nie ma elementu \"kiwi\"\n";

cout << "czy na liscie l1 jest element \"kiwi\"? " << boolalpha

<< binary_search(l1.begin(), l1.end(), "kiwi") << noboolalpha << endl;

//to bedzie duzo szybsze, dla (sporej) listy posortowanej...

cout << "\nlista l2 (dostep poprzez iterator):\n";
for (ils = l2.begin(); ils != l2.end(); ils ++)

cout << *ils << endl;

l1.merge(l2);

cout << "\nlista l1 (wynik po dolaczeniu listy l2):\n";
for (ils = l1.begin(); ils != l1.end(); ils ++)

cout << *ils << endl;

cout << "\nlista l2 (wynik po dolaczeniu listy l2):\n";
for (ils = l2.begin(); ils != l2.end(); ils ++)

cout << *ils << endl;

l1.sort();

l1.unique();

cout << "\nlista l1 (wynik po wyeliminowaniu elementow zdublowanych):\n";
for (ils = l1.begin(); ils != l1.end(); ils ++)

cout << *ils << endl;

l1.sort(specialStringsCompare);

cout << "\nlista l1 (wynik po specjalnym sortowaniu)):\n";
for (ils = l1.begin(); ils != l1.end(); ils ++)

cout << *ils << endl;

l1.reverse();

cout << "\nlista l1 (wynik po odwroceniu listy):\n";
for (ils = l1.begin(); ils != l1.end(); ils ++)

cout << *ils << endl;

cout << "\nlista l1 (wypisywanie przy pomocy for_each i predykatu funkcyjnego):\n";
for_each(l1.begin(), l1.end(), printElement(cout));
//UWAGA: w funkcji for_each(,,) sa przecinki, a nie sredniki jak w instrukcji for(;;)

cout << "\nlista l1 (wypisywanie przy pomocy wskaznika do funkcji):\n";
for_each(l1.begin(), l1.end(), printElement2);

//min(class T, class T), max(class T, class T)

pairOfDoubles elem1(0.0, 1.0), elem2(2.0, 3.0);

swap(elem1, elem2);

9

background image

cout << "\nelem1.x = " << elem1.x

<< ", elem1.x = " << elem1.y

<< ", elem2.x = " << elem2.x

<< ", elem2.y = " << elem2.y << endl;

return 0;

}

Zadanie 3.2. Wykorzystując blibliotekę STL napisać program narzędziowy sort. Program powinien — tak jak

w oryginale — udostępniać opcję -n przełączającą działanie programu w tryb sortowania numerycznego.

Przykładowe rozwiązanie:

#include <fstream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

#define MAX_LINE 65536

inline bool numericStringCompare(const string &s, const string &t) {

if (s.size() == t.size())

return s < t;

else

return s.size() < t.size();

}

int main(int argc, char** argv) {

char line[MAX_LINE];
vector <string> vp, vm;

ifstream

fin(argv[2], ios_base::binary);

ofstream fout(argv[3], ios_base::binary);

fin >> noskipws;

while (!fin.eof()) {

fin.getline(line, MAX_LINE);
if (string(argv[1]) == "-n"

&& line[0] == ’-’)

vm.push_back(string(line));

else

vp.push_back(string(line));

}

fin.close();

if (string(argv[1]) == "-n") {

sort(vm.begin(), vm.end(), numericStringCompare);

sort(vp.begin(), vp.end(), numericStringCompare);

}
else

sort(vp.begin(), vp.end());

for (int i = vm.size()-1; i >= 0 ; i --)

fout << vm[i] << endl;

for (int i = 0; i < vp.size(); i ++)

fout << vp[i] << endl;

fout.close();

return 0;

}

10

background image

4. Przeciążanie funkcji

Zadanie 4.1. Przeanalizować działanie poniższego programu.

#include <iostream>
using namespace std;

void f(double x)

{ cout << "f(double x)" << endl; }

void f(int i)

{ cout << "f(int i)" << endl; }

void f(double x, double y)

{ cout << "f(double x, double y)" << endl; }

void f(int i, int j)

{ cout << "f(int i, int j)" << endl; }

void f(double x, double y=0.0) { cout << "f(double x, double y=0.0)" << endl; }

int main(int argc, char** argv) {

f(3);
f(3.0);
f((

int) 3.0);

f(3, 3);
f(3.0, 3.0);

//f(3, 3.0);

return 0;

}

5. Przeciążanie operatorów

Zadanie 5.1. Przeanalizować działanie poniższego programu.

#include <iostream>

class string {

private:

char

*p;

size_t

size;

public:

string(

const char str[]);

string(

const string &str);

˜string() {

delete[] p; }

string&

operator=(const string &str);

inline char& operator[](const int i) const { return p[i]; };
size_t length() {

return size; };

//

void toupper();

//

void tolower();

friend std::ostream& operator<<(std::ostream& os, const string& str);

};

string::string(

const char str[]) {

char *t = (char*) str;

while (*t != ’\0’)

t ++;

size = t - str;
p =

new char[size+1];

for (int i = 0; i <= size; i ++)

p[i]=str[i];

}

11

background image

string::string(

const string &str) {

size = str.size;
p =

new char[size+1];

for (int i = 0; i <= size; i ++)

p[i]=str.p[i];

}

string& string::

operator=(const string &str) {

if (this != &str) {

delete [] p;
size = str.size;
p =

new char[size+1];

for (int i = 0; i <= size; i ++)

p[i]=str.p[i];

}

return *this;

}

std::ostream&

operator<<(std::ostream& os, const string& str) {

return os << str.p;

}

int main(int argc, char** argv) {

const char a[] = "Dzien jak c++odzien ;-)";
const char b[] = "Czy dziennik w szkole wieczorowej to nocnik?";
string s(a), t(b), u = s;

std::cout << "\n" << s

<< ", " << s[3]
<< ", " << s.length()
<< "\n" << t
<< ", " << t[3]
<< ", " << t.length()
<< "\n" << u
<< ", " << u[3]
<< ", " << u.length();

return 0;

}

Zadanie 5.2. Przeanalizować działanie poniższego programu.

#include <iostream>
using namespace std;

class matrix2x2 {

private:

double m[2][2];

public:

matrix2x2(

const double M[][2]);

matrix2x2(

double m00 = 0.0, double m01 = 0.0, double m10 = 0.0, double m11 = 0.0);

matrix2x2(

const matrix2x2 &M);

matrix2x2&

operator=(const matrix2x2 &M);

matrix2x2

operator-();

double det() const;

friend matrix2x2 operator+(const matrix2x2 &M1, const matrix2x2 &M2);
friend ostream&

operator<<(ostream& os, const matrix2x2 &M);

};

inline matrix2x2::matrix2x2(const double M[][2]) {

m[0][0] = M[0][0];

12

background image

m[0][1] = M[0][1];

m[1][0] = M[1][0];

m[1][1] = M[1][1];

}

inline matrix2x2::matrix2x2(double m00, double m01, double m10, double m11) {

m[0][0] = m00;

m[0][1] = m01;

m[1][0] = m10;

m[1][1] = m11;

}

inline matrix2x2::matrix2x2(const matrix2x2 &M) {

m[0][0] = M.m[0][0];

m[0][1] = M.m[0][1];

m[1][0] = M.m[1][0];

m[1][1] = M.m[1][1];

}

inline matrix2x2& matrix2x2::operator=(const matrix2x2 &M) {

m[0][0] = M.m[0][0];

m[0][1] = M.m[0][1];

m[1][0] = M.m[1][0];

m[1][1] = M.m[1][1];
return *this;

}

inline matrix2x2 matrix2x2::operator-() {

matrix2x2 M;

M.m[0][0] = -m[0][0];

M.m[0][1] = -m[0][1];

M.m[1][0] = -m[1][0];

M.m[1][1] = -m[1][1];
return M;

}

inline double matrix2x2::det() const {

return m[0][0]*m[1][1] - m[0][1]*m[1][0];

}

inline matrix2x2 operator+(const matrix2x2 &M1, const matrix2x2 &M2) {

matrix2x2 M = M1;

M.m[0][0] += M2.m[0][0];

M.m[0][1] += M2.m[0][1];

M.m[1][0] += M2.m[1][0];

M.m[1][1] += M2.m[1][1];
return M;

}

ostream&

operator<<(ostream& os, const matrix2x2 &M) {

return os << "\n" << M.m[0][0]

<< ", " << M.m[0][1]

<< "\n" << M.m[1][0]

<< ", " << M.m[1][1]

<< "\n";

}

int main(int argc, char** argv) {

const double tab[][2]= {{1.5, 2.5}, {3.5, 4.5}};

matrix2x2 A(tab), B(1.0, 0.0, 0.0, -1.0), C = A + B, D;

D = -C;

13

background image

cout << "\nMacierz A: " << A

<< ", macierz B: " << B

<< ", macierz C: " << C

<< ", macierz D: " << D

<< ", wyznacznik macierzy A: " << A.det()

//-2.0

<< ", wyznacznik macierzy B: " << B.det()

//-1.0

<< ", wyznacznik macierzy C: " << C.det()

// 0.0

<< ", wyznacznik macierzy D: " << D.det(); // 0.0

return 0;

}

Zadanie 5.3. Utworzyć klasę matrix3x3 reprezentująca macierze kwadratowe wymiaru 3 × 3 o wyrazach rzeczy-

wistych (zob. zad. 5.2).

6. Dalej o klasach

Zadanie 6.1.

Zaobserwować, na poniższym przykładzie, jakie znaczenie w definicji klasy ma słowo kluczowe

explicit

.

#include <iostream>
using namespace std;

class test {

private:

int private_int;

public:

explicit test(

const int& = int());

test explicit_test();

test&

operator++();

test&

operator++(int);

friend test operator+(const test& a, const test& b);

};

test::test(

const int& i) : private_int(i) { }

test test::explicit_test() {

return 0; }

test& test::

operator++() {

cout << "przedrostkowy\n";

++

private_int;

return *this;

}

test& test::

operator++(int) {

cout << "przyrostkowy\n";
private_int ++;
return *this;

}

inline test operator+(const test& a, const test& b) {

test c;

c.

private_int = a.private_int + b.private_int;

return c;

}

int main(int argc, char** argv) {

test x(1), y = test(), z = x + y, t;

z ++; ++ z;

14

background image

return 0;

}

Zadanie 6.2. Zaobserwować, na poniższym przykładzie, jakie znaczenie w definicji klasy ma słowo kluczowe const.

#include <iostream>
#include <complex>
#include <cmath>
using namespace std;

int I;

class test {

private:

int i;

public:

void f1() const;
void f2() const;
void f3();

};

//void test::f0() const { i = 1; }
void test::f1() const {

}

void test::f2() const { I = 1;

}

void test::f3()

{ i = 1;

}

void f1(int i)

{ i = 1;

}

void f2(int &i)

{ i = 1;

}

void f3(int *i)

{ *i = 1; }

void f4(const int i)

{ i = 1;

}

void f5(const int &i) { i = 1;

}

void f6(const int* i) { *i = 1; } //wskaznik do stalego int-a...
void f7(int const* i) { *i = 1; } //wskaznik do stalego int-a...
void f8(int *const i) { *i = 1; } //staly wskaznik do int-a...

int main(int argc, char** argv) {

test t;

t.f1();
t.f2();
t.f3();

int k;
k = 0; f1(k);

cout << k << endl;

k = 0; f2(k);

cout << k << endl;

k = 0; f3(&k); cout << k << endl;
k = 0; f8(&k); cout << k << endl;

return 0;

}

7. Dziedziczenie klas

Zadanie 7.1. Przeanalizować działanie poniższego programu.

#include <iostream>
using namespace std;

class abstractFigure {

public:

virtual void

scale(

const double s) = 0;

15

background image

virtual double area() = 0;
virtual double length() = 0;

};

class square : public abstractFigure {

protected: //przy ‘private’ bylby blad!

double a;

public:

square(

const double &A = 0) : a(A) {}

void scale(const double s) { a *= s; }
double area()

{

return a * a; }

double length() { return 4 * a; }

};

class rectangle : public square {

protected:

double b;

public:

rectangle(

const double &A = 0, const double &B = 0) : b(B) { a = A;}

void scale(const double s) { a *= s; b *= s; }
double area()

{

return a * b; }

double length() { return 2*a + 2*b; }

};

//ROWNOLEGLOBOK
class parallelogram : public rectangle {

private:

double h;

public:

parallelogram(

const double &A = 0, const double &B = 0, const double &H = 0)

: h(H) { a = A; b = B; }

void scale(const double s) { rectangle::scale(s); h *= s; }

//wykorzystujemy skalowanie z ‘rectangle’

double area() { return a * h; }

//nie musimy pisac metody ‘length’,
//bo bylaby taka sama jak w klasie ‘rectangle’

};

int main(int argc, char** argv) {
//figure

F; //Nie mozna tworzc obiektow klas abstrakcyjnych!

//(takie klasy nie maja nawet konstruktorow)

square

S(1);

rectangle

R(1,2);

parallelogram

P(1,2,3);

cout << "\n" << S.area()

<< ", " << S.length()
<< "\n" << R.area()
<< ", " << R.length()
<< "\n" << P.area()
<< ", " << P.length();

//cout << S.a; spowoduje blad przy kompilacji
//(bo nie ma dostepu do skladowych prywatnych i chronionych)

return 0;

}

Zadanie 7.2. Przeanalizować działanie poniższego programu.

#include <iostream>
using namespace std;

16

background image

class animal {

public:

char* name() { return "animal"; }

};

class bird : public animal {

public:

char* name() { return "bird"; }

};

class hen : public bird {

public:

char* name()

{

return "hen"; }

int

numberOfHands() {

return 0; }

int

numberOfWings() {

return 2; }

int

numberOfLegs()

{

return 2; }

bool

canSwim()

{

return false; }

};

//ssak...
class mammal : public animal {

public:

char* name() { return "mammal"; }

};

class cow : public mammal {

public:

char* name()

{

return "cow"; }

int

numberOfHands() {

return 0; }

int

numberOfWings() {

return 0; }

int

numberOfLegs()

{

return 4; }

bool

canSwim()

{

return false; }

};

class cat : public mammal {

public:

char* name()

{

return "cat"; }

int

numberOfHands() {

return 0; }

int

numberOfWings() {

return 0; }

int

numberOfLegs()

{

return 4; }

bool

canSwim()

{

return false; }

};

class dog : public mammal {

public:

char* name()

{

return "dog"; }

int

numberOfHands() {

return 0; }

int

numberOfWings() {

return 0; }

int

numberOfLegs()

{

return 4; }

bool

canSwim()

{

return true; }

};

int main(int argc, char** argv) {

animal A;

bird

B;

cow

C;

dog

D;

hen

H; // kura...

cat

K;

cout << "\n" << A.name()

<< "\n" << B.name()

17

background image

<< "\n" << C.name()

<< ", " << C.numberOfHands()

<< ", " << C.numberOfWings()

<< ", " << C.numberOfLegs()

<< ", " << C.canSwim()

<< "\n" << D.name()

<< ", " << D.numberOfHands()

<< ", " << D.numberOfWings()

<< ", " << D.numberOfLegs()

<< ", " << D.canSwim()

<< "\n" << H.name()

<< ", " << H.numberOfHands()

<< ", " << H.numberOfWings()

<< ", " << H.numberOfLegs()

<< ", " << H.canSwim()

<< "\n" << K.name()

<< ", " << K.numberOfHands()

<< ", " << K.numberOfWings()

<< ", " << K.numberOfLegs()

<< ", " << K.canSwim();

return 0;

}

Zadanie 7.3. Stosując dziedziczenie klas utworzyć klasy modelujące prostą „hierarchię” pojazdów. Utworzone klasy

powinny zawierać metody zwracające nazwę pojazdu, ilość kół pojazdu, ilość drzwi pojazdu oraz rodzaj zastosowanego
napędu. Hierarchia pojazdów powinna „rozpoczynać” się od pojazdu abstrakcyjnego (zob. zad. 7.2).

8. Klasy szablonowe

Zadanie 8.1. Utworzyć klasę szablonową realizującą interfejs kolejki.

Przykładowe rozwiązanie:

#ifndef QUEUE_H
#define QUEUE
_H

template <typename Type> class queue {

public:

class queue_element {

public:
Type

elem;

queue_element *next;

queue_element *prev;

};

private:

size_t

queue_size;

queue_element *first, *last;

public:

explicit queue() { queue_size = 0; first = NULL; last = NULL; };

bool empty()

const;

size_t size()

const;

Type front()

const;

Type back()

const;

void push(const Type& elem);
void pop();
void clear(); //tego nie ma w interfejsie kolejki z STL-a

};

18

background image

template <class Type> bool queue<Type>::empty() const {

return (first == NULL);

}

template <class Type> size_t queue<Type>::size() const {

return queue_size;

}

template <class Type> Type queue<Type>::front() const {

Type elem;

if (!empty())

return first->elem;

return elem;

}

template <class Type> Type queue<Type>::back() const {

Type elem;

if (!empty())

return last->elem;

return elem;

}

template <class Type> void queue<Type>::push(const Type& elem) {

queue_element *temp =

new queue_element;

if (temp) {

queue_size ++;

temp->elem = elem;

if (empty()) {

temp->prev = temp->next = NULL;

first = last = temp;

}
else {

temp->prev = last;

temp->next = NULL;

last->next = temp;

last = temp;

}

}

}

template <class Type> void queue<Type>::pop() {

queue_element *second;

if (first != NULL) {

second = first->next;
if (second != NULL)

second->prev = NULL;

}

delete first;
queue_size --;

first = second;

}

19

background image

template <class Type> void queue<Type>::clear() {

while (!empty()) {

pop();

}

}

#endif

Zadanie 8.2. Wykorzystując utworzoną klasę szablonową kolejki napisać grę „saper”.

Przykładowe rozwiązanie:

#include <iostream>
#include <queue>
#include <cstdlib>
using namespace std;

#define X 20
#define Y 10

class miner {

public:

struct pairOfInt { //to moze sie przydac w metodzie ‘check’...

int x, y;
pairOfInt(

const int &xx = 0, const int &yy = 0) : x(xx), y(yy) {};

};
miner(

const int &nn);

void check(const int &, const int &);
const bool& solved

()

const { return s; }

const bool& finished() const { return f; }

private:

int

n, rem, board[X+2][Y+2]; //tablica z ,,zaporami’’ (z wartownikiem)...

bool s, f;

friend ostream& operator<<(ostream& os, const miner &M); //rysuje plansze...

};

miner::miner(

const int &nn) {

int x, y;

n = nn;
rem = X*Y;
s = false;
f = false;

for (y = 1; y <= Y; y ++)

for (x = 1; x <= X; x ++)

board[x][y] = -2; //puste pole...

for (y = 0; y <= Y+1; y ++)

board[0][y] = board[X+1][y] = -3; //sciana...

for (x = 0; x <= X+1; x ++)

board[x][0] = board[x][Y+1] = -3; //sciana...

while (n) {

x = (rand() % X) + 1;
y = (rand() % Y) + 1;
if (board[x][y] == -2) {

board[x][y] = -1;
n --;

}

}

n = nn;

}

20

background image

void miner::check(const int &x, const int &y) {

int xx, yy, ss;
pairOfInt

t;

queue<pairOfInt> Q;

if (board[x][y] > 0)

return;

if (board[x][y] == -1) {

s = false;

f = true;
return;

}

Q.push(pairOfInt(x,y));
while (!Q.empty()) {

t = Q.front();

Q.pop();

ss = 0;

if (board[t.x][t.y] == -2) {

for (yy = t.y-1; yy <= t.y+1; yy ++)

for (xx = t.x-1; xx <= t.x+1; xx ++)

if ((board[xx][yy] == -1)

&& ((xx != t.x) || (yy != t.y)))

ss ++;

board[t.x][t.y] = ss;
if (!ss)

for (yy = t.y-1; yy <= t.y+1; yy ++)

for (xx = t.x-1; xx <= t.x+1; xx ++)

if ((board[xx][yy] == -2) && ((xx != t.x) || (yy != t.y)))

Q.push(pairOfInt(xx,yy));

rem --;

}

}
if (rem <= n)

s = f = true;

}

ostream&

operator<<(ostream &os, const miner &M) {

int

x, y;

char c;

for (y = 1; y <= Y; y ++) {

for (x = 1; x <= X; x ++) {

c = (M.board[x][y]>=0 ? (

char)(M.board[x][y]+’0’) : ’ ’);

os << c;

}

os << ’|’ << y << endl;

}
for (x = 1; x <= X; x ++)

os << ’-’;

os << ’+’ << endl;
for (x = 1; x <= X; x ++) {

c = (

char)(x + ’a’ - 1);

os << c;

}

os << endl;
return os;

}

int main(int argc, char** argv) {

char

c;

int

i;

21

background image

cout << "Podaj ilosc bomb: ";
cin

>> i;

miner M(i);

while (!M.finished()) {

cout << M << endl << "Twoj ruch (np. e4): ";
cin

>> c >> i;

M.check((

int)(c-’a’+1), i);

}
cout << M;
if (M.solved())

cout << "Gratulacje!" << endl;

else

cout << "Buuu..." << endl;

return 0;

}

Zadanie 8.3. Przerobić klasę matrix2x2 z zadania 5.2 na klasę szablonową.

Przykładowe rozwiązanie:

#include <iostream>
using namespace std;

template <typename type> class matrix2x2 {

private:

type m[2][2];

public:

matrix2x2(

const type M[][2]);

matrix2x2(type m00 = 0.0, type m01 = 0.0, type m10 = 0.0, type m11 = 0.0);
matrix2x2(

const matrix2x2<type> &M);

matrix2x2<type>&

operator=(const matrix2x2<type> &M);

matrix2x2<type>

operator-();

type det()

const;

template <typename type_> friend matrix2x2<type_> operator+

(

const matrix2x2<type_> &M1, const matrix2x2<type_> &M2);

template <typename type_> friend ostream&

operator<<

(ostream& os,

const matrix2x2<type_> &M);

};

template <typename type> inline matrix2x2<type>::matrix2x2(const type M[][2]) {

m[0][0] = M[0][0];
m[0][1] = M[0][1];
m[1][0] = M[1][0];
m[1][1] = M[1][1];

}

template <typename type> inline matrix2x2<type>::matrix2x2(

type m00, type m01, type m10, type m11) {
m[0][0] = m00;
m[0][1] = m01;
m[1][0] = m10;
m[1][1] = m11;

}

template <typename type> inline matrix2x2<type>::matrix2x2(const matrix2x2<type> &M) {

m[0][0] = M.m[0][0];
m[0][1] = M.m[0][1];
m[1][0] = M.m[1][0];
m[1][1] = M.m[1][1];

}

22

background image

template <typename type> inline matrix2x2<type>& matrix2x2<type>::operator=(

const matrix2x2<type> &M) {

m[0][0] = M.m[0][0];

m[0][1] = M.m[0][1];

m[1][0] = M.m[1][0];

m[1][1] = M.m[1][1];

return *this;

}

template <typename type> inline matrix2x2<type> matrix2x2<type>::operator-() {

matrix2x2<type> M;

M.m[0][0] = -m[0][0];

M.m[0][1] = -m[0][1];

M.m[1][0] = -m[1][0];

M.m[1][1] = -m[1][1];

return M;

}

template <typename type> inline type matrix2x2<type>::det() const {

return m[0][0]*m[1][1] - m[0][1]*m[1][0];

}

template <typename type> inline matrix2x2<type> operator+(

const matrix2x2<type> &M1, const matrix2x2<type> &M2) {

matrix2x2<type> M = M1;

M.m[0][0] += M2.m[0][0];

M.m[0][1] += M2.m[0][1];

M.m[1][0] += M2.m[1][0];

M.m[1][1] += M2.m[1][1];

return M;

}

template <typename type> ostream& operator<<(ostream& os, const matrix2x2<type> &M) {

return os << "\n" << M.m[0][0]

<< ", " << M.m[0][1]

<< "\n" << M.m[1][0]

<< ", " << M.m[1][1]

<< "\n";

}

int main(int argc, char** argv) {

const double tab[][2]= {{1.5, 2.5}, {3.5, 4.5}};

matrix2x2<

double> A(tab), B(1.0, 0.0, 0.0, -1.0), C = A + B, D;

D = -C;

cout << "\nMacierz A: " << A

<< ", macierz B: " << B

<< ", macierz C: " << C

<< ", macierz D: " << D

<< ", wyznacznik macierzy A: " << A.det()

<< ", wyznacznik macierzy B: " << B.det()

<< ", wyznacznik macierzy C: " << C.det()

<< ", wyznacznik macierzy D: " << D.det();

return 0;

}

23

background image

9. Zręby klas

Zadanie 9.1. Utworzyć zręb umożliwiający wygodną implementację algorytmów grafowych.

Przykładowe rozwiązanie:

#ifndef GRAPH_H
#define GRAPH
_H

#include <iostream>
#include <vector>
#include <fstream>
using namespace std;

class vertice
{

public:

vector<

int> successors, predecessors;

size_t degree()

const { return successors.size()+predecessors.size(); }

size_t outDegree()

const { return successors.size(); }

size_t inDegree()

const { return predecessors.size(); }

};

class graph
{

private:

size_t _numberOfEdges;

public:

vector<vertice> vertices;
graph(size_t size = 0);
size_t numberOfVertices()

const { return vertices.size(); }

size_t numberOfEdges()

const { return _numberOfEdges; }

void insertEdge(int u, int v);

};

inline graph::graph(size_t size)
{

vertices.resize(size);
_numberOfEdges = 0;

}

inline void graph::insertEdge(int u, int v)
{

vertices[u].successors.push_back(v);
vertices[v].predecessors.push_back(u);
_numberOfEdges ++;

}

template <class type> class verticeMap
{

private:

vector<type> _map;

public:

verticeMap(

const graph& G, type value=type())

{ _map.resize(G.vertices.size(), value); }

size_t size() {

return _map.size(); }

type&

operator[](const int i) { return _map[i]; }

};

template <class type> class edgeMap
{

typedef vector<type> vectorType;

24

background image

private:

vector<vectorType> _map;

public:

edgeMap(

const graph& G, type t=type());

size_t size() {

return _map.size(); }

vectorType&

operator[](const int i) { return _map[i]; }

template <class type_>
friend void load(graph& G, edgeMap<type_>& c, char * filename);

};

template <class type> inline edgeMap<type>::edgeMap(const graph& G, type value)
{

_map.resize(G.vertices.size());
for (int v = 0; v < _map.size(); v ++)

_map[v].resize(G.vertices[v].successors.size(), value);

}

template <class type> void load(graph& G, edgeMap<type>& c, char * filename)
{

int numberOfVertices, numberOfEdges, u, v;
type t;

ifstream file(filename, ios::binary);

file >> numberOfVertices >> numberOfEdges;

G.vertices.resize(numberOfVertices);

c._map.resize(numberOfVertices);

for (v = 0; v < numberOfVertices; v ++)
{

G.vertices[v].successors.clear();

G.vertices[v].predecessors.clear();

c._map[v].clear();

}

for (int i = 0; i < numberOfEdges; i ++)
{

file >> u >> v >> t;

G.insertEdge(u, v);

c[u].push_back(t);

}

file.close();

}

#endif

Zadanie 9.2. Wykorzystać utworzony zręb do zaimplementowania programu wypisującego wszystkie ścieżki proste

w grafie.

Przykładowe rozwiązanie:

#include <iostream>
#include "graph.h"
using namespace std;

struct label
{

int _v_, u;
bool onPath;

label (

int _v__ = int(), int u_ = int(), bool onPath_ = bool()) :

_v_(_v__), u(u_), onPath(onPath_) { }

//friend istream& operator>>(istream& is, label &l);

};

25

background image

int main(int argc, char ** argv)
{

graph G;

edgeMap<

double> c(G);

load(G, c, argv[1]);

const int s = 0;
const int t = G.vertices.size()-1;

verticeMap<label> L(G, label(-1, 0, false));

L[s] = label(-1, 0, true);

int n = 0, u = s, v;
double cost;

do
{

do
{

do
{

L[u]._v_ ++;

}
while((L[u]._v_ < G.vertices[u].successors.size()) &&

L[G.vertices[u].successors[L[u]._v_]].onPath);

if ((L[u]._v_ < G.vertices[u].successors.size()) &&

!L[G.vertices[u].successors[L[u]._v_]].onPath)

{

L[G.vertices[u].successors[L[u]._v_]].onPath = true;

L[G.vertices[u].successors[L[u]._v_]].u = u;

u = G.vertices[u].successors[L[u]._v_];

}
else
{

if (L[u].u == u)

break;

L[u]._v_ = -1;

L[u].onPath = false;

u = L[u].u;

}

}
while(u != t);

if (L[u].u == u)

break;

cost = 0.0;

u = s;

n ++;
do
{

cout << u << " --> " << flush;

cost += c[u][L[u]._v_];

u = G.vertices[u].successors[L[u]._v_];

}
while(u != t);
cout << t << ": koszt = " << cost << endl;

}
while (G.vertices[s].successors[L[s]._v_] != s);

26

background image

cout << "Calkowita liczba ciezek prostych z wierzcholka zrodlowego " << s

<< " do wierzcholka docelowego " << t << ": " << n << endl;

}

10. Podstawy zrębu Qt 4.5

Zadanie 10.1. Przeanalizować działanie poniższego programu.

Plik qt.pro:

TARGET = qt

TEMPLATE = app

SOURCES += main.cpp\

widget.cpp

HEADERS

+= widget.h

FORMS

+= widget.ui

Plik widget.ui:

<?xml version="1.0" encoding="UTF-8"?>

<ui version="4.0">

<class>WidgetClass</class>

<widget class="QWidget" name="WidgetClass">

<property name="geometry">

<rect>

<x>0</x>

<y>0</y>

<width>300</width>

<height>200</height>

</rect>

</property>

<property name="sizePolicy">

<sizepolicy hsizetype="Preferred" vsizetype="Preferred">

<horstretch>0</horstretch>

<verstretch>0</verstretch>

</sizepolicy>

</property>

<property name="minimumSize">

<size>

<width>300</width>

<height>200</height>

</size>

</property>

<property name="windowTitle">

<string>Test zrebu Qt</string>

</property>

<layout class="QGridLayout" name="gridLayout">

<item row="0" column="0">

<widget class="QLabel" name="label">

<property name="text">

<string>TextLabel</string>

</property>

</widget>

</item>

<item row="1" column="0">

<widget class="QLabel" name="label_2">

<property name="text">

<string>TextLabel</string>

</property>

</widget>

27

background image

</item>

<item row="2" column="2">

<spacer name="verticalSpacer">

<property name="orientation">

<enum>Qt::Vertical</enum>

</property>

<property name="sizeHint" stdset="0">

<size>

<width>20</width>

<height>82</height>

</size>

</property>

</spacer>

</item>

<item row="3" column="0">

<spacer name="horizontalSpacer">

<property name="orientation">

<enum>Qt::Horizontal</enum>

</property>

<property name="sizeHint" stdset="0">

<size>

<width>87</width>

<height>20</height>

</size>

</property>

</spacer>

</item>

<item row="3" column="1">

<widget class="QPushButton" name="pushButton">

<property name="text">

<string>Zamknij</string>

</property>

</widget>

</item>

<item row="3" column="2">

<widget class="QPushButton" name="pushButton_2">

<property name="text">

<string>Info</string>

</property>

</widget>

</item>

</layout>

</widget>

<layoutdefault spacing="6" margin="11"/>

<resources/>

<connections>

<connection>

<sender>pushButton</sender>

<signal>clicked()</signal>

<receiver>WidgetClass</receiver>

<slot>close()</slot>

<hints>

<hint type="sourcelabel">

<x>161</x>

<y>173</y>

</hint>

<hint type="destinationlabel">

<x>108</x>

<y>94</y>

</hint>

</hints>

</connection>

</connections>

28

background image

</ui>

Plik main.cpp:

#include <QtGui/QApplication>
#include "widget.h"

int main(int argc, char *argv[]) {

QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();

}

Plik widget.h:

#ifndef WIDGET_H
#define WIDGET
_H

#include <QtGui/QWidget>
#include <QMouseEvent>
#include <QPainter>
#include <QMessageBox>

namespace Ui {

class WidgetClass;

}

class Widget : public QWidget {

Q_OBJECT

public:

Widget(QWidget *parent = 0);
˜Widget();
void paintEvent(QPaintEvent *event);

//zdarzenie odmalowania okna

void mouseMoveEvent(QMouseEvent *event);

//zdarzenie ruchu kursora myszy

void mousePressEvent(QMouseEvent *event); //zdarzenie nacisniecia przycisku myszy

private:

Ui::WidgetClass *ui;

private slots:

void on_pushButton_2_clicked();

};

#endif // WIDGET_H

Plik widget.cpp:

#include "widget.h"
#include "ui
_widget.h"

#define X_NO_SEGS 20
#define Y
_NO_SEGS 15
#define X
_OFFSET

10

#define Y_OFFSET

10

Widget::Widget(QWidget *parent) : QWidget(parent), ui(

new Ui::WidgetClass) {

ui->setupUi(

this);

this->setMouseTracking(true); //!!!

}

Widget::˜Widget() {

delete ui;

}

29

background image

void Widget::paintEvent(QPaintEvent *event) {

int windowWidth

=

this->geometry().width()

- 2*X_OFFSET;

int windowHeight = this->geometry().height() - 2*Y_OFFSET;
int min = (windowWidth > windowHeight ? windowHeight : windowWidth);
int segmentWidth = min / X_NO_SEGS, segmentHeight = min / Y_NO_SEGS;

QPainter painter(

this);

for (int y = 0; y < Y_NO_SEGS; y ++)

for (int x = 0; x < X_NO_SEGS; x ++)

painter.drawRect(X_OFFSET + (windowWidth -min) / 2 + segmentWidth*x,

Y_OFFSET + (windowHeight-min) / 2 + segmentHeight*y,

segmentWidth, segmentHeight);

}

void Widget::mouseMoveEvent(QMouseEvent *event) {

ui->label->setText(QString(

"Wspolrzedne wskaznika myszy: (%1, %2)").arg(event->x()).arg(event->y()));

}

void Widget::mousePressEvent(QMouseEvent *event) {

int windowWidth

=

this->geometry().width()

- 2*X_OFFSET;

int windowHeight = this->geometry().height() - 2*Y_OFFSET;
int min = (windowWidth > windowHeight ? windowHeight : windowWidth);
int segmentWidth = min / X_NO_SEGS, segmentHeight = min / Y_NO_SEGS;
int x = (event->x() - X_OFFSET - (windowWidth -min) / 2) / segmentWidth;
int y = (event->y() - Y_OFFSET - (windowHeight-min) / 2) / segmentHeight;

if ((x >= 0) && (x < X_NO_SEGS) && (y >= 0) && (y < Y_NO_SEGS))

ui->label_2->setText(QString("Kliknieto na polu: (%1, %2)").arg(x).arg(y));

}

void Widget::on_pushButton_2_clicked()

{

QMessageBox::information(

this, "Info",

"Moj pierwszy program wykorzystujacy zreb Qt...");

}

11. Zadania zaliczeniowe

Zadanie 11.1. Przy pomocy zrębu Qt utworzyć graficzny interfejs dla gry „kółko krzyżyk” (zob. zad. 11.8).

Zadanie 11.2. Przy pomocy zrębu Qt utworzyć graficzny interfejs dla gry „gomoku” (zob. zad. 11.9).

Zadanie 11.3. Przy pomocy zrębu Qt utworzyć graficzny interfejs dla gry „czwórki” (zob. zad. 11.10).

Zadanie 11.4. Przy pomocy zrębu Qt utworzyć graficzny interfejs dla gry „saper” (zob. zad. 8.2).

Zadanie 11.5. Przy pomocy zrębu Qt utworzyć narzędzie do wizualizacji grafów (zob. zad. 9.1).

Zadanie 11.6. Wykorzystać zaprezentowany zręb grafowy do implementacji algorytmu Belmana-Forda (zob. zad.

9.1).

Zadanie 11.7. Wykorzystując klasę kolejki priorytetowej oraz zaprezentowany zręb grafowy zaimplementować

algorytm Dijkstry (zob. zad. 11.15 i 9.1).

Zadanie 11.8. Utworzyć klasę realizującą grę „kółko–krzyżyk” z tekstowym interfejsem użytkownika (gra użyt-

kownik kontra komputer). Komputer nie powinien dać się ograć!

Zadanie 11.9. Utworzyć klasę realizującą grę „gomoku” (na obszarze wymiaru 20 × 20) z tekstowym interfejsem

użytkownika (gra użytkownik kontra komputer).

30

background image

Zadanie 11.10. Utworzyć klasę realizującą grę „czwórki” z tekstowym interfejsem użytkownika (gra użytkownik

kontra komputer).

Zadanie 11.11.

Utworzyć klasę generującą labirynty (o podanych wymiarach) oraz znajdującą przejście przez

dowolny labirynt (o ile takie przejście istnieje).

Zadanie 11.12. Utworzyć klasę macierzy wymiaru n × k (zob. zad. 5.2). Funkcje zaprzyjaźnine realizujące operacje

dodawania, odejmowania i mnożenia macierzy powinny zgłaszać odpowiednie wyjątki w przypadku, gdy dana operacja
nie jest wykonalna. Zastosować dziedziczenie klas w implementacji metody obliczającej wyznacznik macierzy oraz
w metodzie zwracającej macierz odwrotną.

Zadanie 11.13. Utworzyć klasę realizującą podstawowe działania arytmetyczne na dowolnie dużych (i dowolnie

małych) liczbach całkowitych.

Zadanie 11.14. Utworzyć klasę realizującą podstawowe działania arytmetyczne na liczbach wymiernych. Obiekty

utworzonej klasy powinny zapewniać dokładną reprezentację liczb wymiernych — wykorzystać klase liczb calkowitych
z zadania 11.13.

Zadanie 11.15. Utworzyć wydajną(!) klasę szablonową realizującą podstawowy interfejs kolejki priorytetowej (zob.

zad. 8.1).

12. Bonus

Zadanie 12.1. Przeanalizować działanie poniższego zwycięzkiego programu z roku 2005, napisanego przez Óscara

Toledo w ramach The International Obfuscated C Code Contest (w skrócie IOCCC), czyli Międzynarodowego Kon-
kursu na Najbardziej Zamroczony Kod C (zob. http://www.ioccc.org/) oraz przyjrzeć się kodowi źródłowemu
oglądanemu „do góry nogami” :-)

31

background image

#define

F getchar())

#define H(z)*n++=z;

#include

<setjmp.h>

#define v main(0,0,0

#define Z while(

#define _ if(

#define o(d)(S=63,u[l]=0,l[d]=6ˆe,q=1e4>v,0),l[d]=0,u[l]=eˆ6,S=b,q)
#define I(H,n) { _ r=l[x=H],!r|(rˆe)<-1){ _ j=u[l],-7==r|6==r\
){ n; e=˜e; return 1e5-443*f; } u[l]=0,t=j+1,i=j-1; _!i&89<\
x)i=j,t=6; _-1==t&30>x)t=j,i=-7; Z++i<t){ d =0; S&= 63; \
a=((jˆe)!=1?6!=(jˆe)?O[32+x/10]-O[u/10+32]-q:(S|=6!=j?8\
:1,2==u-x)*9+9*(x-u==2):(d=1==j?x-u:u-x)/8+!(!((x-u)%\
10)|r)*99+(j==1?90<x:29>x)*(9*O[28+i]-288))+O[r+28\
]*9-288+O[x%10+33]-f-O[33+u%10]; x[l]=i; S|=(21=\
=u|21==x)*2+(u==28|28==x)*4+(91==u|x==91)*16+32\
*(u==98|x==98)+(20==d)*64*x; a-=k>f?main(a,f+1\
,M,k):0; _ i==c&u==h&!f&N&a>-1e4&x==y)longjm\
p(z,1); S=b; _!N|f&&(a>M||!f&a==M&&1&rand()\
)){ _!f){ _ k){ c=i; h=u; y=x; } } else _ \
L-a<N){ n; e=˜e; u[l]=j; x[l]=r; return\

a; } M=a; } } x[l]=r; u[l]=j; n; } }

typedef int G; char J [ 78 ], O [ ]
=

"HRQAMS#-smaqrh[UTZYTU[|TBA("

"$#(ABT|ba‘gg‘ab8>GK[_‘fFDZXEYR"

"L\t####"

"##B#A#@#G#F#E#D#K\t\3Zlv#tjm"

"\3J#tjm\3Pwb"

"ofnbwf\3Joofdbo\3)&‘&‘.&‘&‘"

"#+&g*\t"; G y,

c,h,e,S,*s,l[149]; jmp_buf z

; G main(G L,G f,

G N,G k){ G u=99,p,q,r,j,i,x

,t,a,b=S,d,M=-1e9

; char *n; if( *l){ e=˜e; Z

u >21){ q= l[--u]ˆe;

_!-- q){ _!l[p=e?u-10:u+10]){

I(p,)_ e?u>80

& !l[p

-=10]:u<39&!l[p+=10])I(p,)} _ l[p=e?u-11:9+u]

)I(p,)

else _ u-1==S>>6){ l[u-1]=0; I(p,l[u-1]=-2ˆe);

} _ l[

p=e?u-9:11+u])I(p,)else _ S>>6==1+u){ l[1+u]=0; I(p,l
[1+u]=eˆ-2); } } _!--q){ n=O+41; Z++n<50+O)I(u+80-*n,
)} _ 0<q&4>q){

n=q==2?53+O:O+49; Z++n<O+(q!=1)*4+54

){ p=u; do I(p-=*n-80,)Z!p[l]); } } _ 4==q){ n=49+O

; Z++n<O+58)I(u-*n+80,)_ e&!(S&24)|!e&!(S&3)

&&

!l[u-2]&!l[u-1]&!l[u-3]&&o(u)&&o(u-1)){ l[u-1]=4

ˆe; l[u-4]=0; I(u-2,l[u-1]=0; l[u-4]=eˆ4); } _
e&!(S&40)|!e&!(S&5)

&&!l[u+1]&!l[2+u]&&o(u)&&

o(1+u)){ l[u+1]=eˆ4; l[3+u]=0;

I(u+2,l[1+u

]=0; l[u+3]=4ˆe); } } } e=˜e;

return M; }

Z h<130){l[h]=-(21>h|98<h|2

>(h+1 )%

10); O[h++]ˆ=3; } n=O +14;

s=20+l; Z

++s<29+l){ 10[s]=1; 70[s]=˜

( * s = *

n++ -+84); 60 [ s] =-2; } Z

n=J){ puts

(58+O); u=19; Z++u<100){ H(32)_!( u%10
))H(32)H(O[7+l[u]])_(9+u)%10>7){ H(58

-u/10)H(32)_ u&1)puts(n=J); } } puts

(O+58); _-1e4 >v , 1)){ e=˜e; puts

(O+(v,0)> 1e4?e?90:82:96)); break

; } _ 1<L&e) { d=v,2+L); printf

(O+114,h%10+64,58-h/10,y%10+64

,58 -y/10,d); } else{ putchar

(62+e); h= (95 & F-44; c=l[h

+=(56-F *10]; y=(95&F-44; y

+=(56-F*10; Z 10!=(u=(95

&F)){ c=5; Z--c>1&&u!=c

[O]); c=eˆc-7; } } _!

setjmp(z)){ v+1,1);

puts(

106+

O); }

} Z

10!=

F; }

32


Wyszukiwarka

Podobne podstrony:
Projekt Inż, Wstęp, Laboratorium programowania niskopoziomowego
GiG-laboratorium-program, IV semestr moje, elektrotechnika, Nowy folder
Laboratorium 2 Program
laboratorium 1 program
Laboratorium 1 programowanie w VBA
Laboratorium 2 programowanie w VBA
Laboratorium 3 programowanie w VBA
Laboratorium 4 programowanie w VBA
Program zajęć ED, aaa, studia 22.10.2014, Materiały od Piotra cukrownika, materialy Kamil, Szkoła, L
Laboratorium Podstaw Programowania 2
PROGRAM laboratoriów z Ekologii i ochrony przyrody na semestr zimowy 14 15
!Program ćwiczeń laboratoryjnych 2012id 602
Program Laboratorium Komputerowe systemy pomiarowe Gawędzki KSP
Fizyka 14b, AGH, agh, programinski, Laborki, Laborki, Lab, FIZYKA - Laboratorium, fiz lab, franko
Polarymetr Laurenta, AGH, agh, programinski, Laborki, Laborki, Lab, FIZYKA - Laboratorium, Polarymet
Program ćwiczeń laboratoryjnych

więcej podobnych podstron