You are on page 1of 24

Vytauto Didžiojo universitetas

Informatikos fakultetas

Ataskaita
Duomenų tipai ir struktūros
4, 5, 6, 7 laboratorinių darbų

Atliko: Vaidas Šilinskis IF060034


IV 14:30-16:00
Tikrino: dėst. Rita Marčiulynienė

2008, Kaunas
Laboratorinis darbas Nr 4. Paveldimumas ir klasių šeimos
2. Pakeiskite pirmojo punkto programą taip kad ji tiktų masyvo formavimui iš tekstiniame faile įrašytų
klasių Tkontaktai ir Tasmuo reikšmių. Pirmoji failo eilutė turi nurodyti jame aprašytų objektų
skaičių, o objekto reikšmių aprašymai atskiriami eilutėmis su simoliu '* ' jų pradžioje. Kiekviena
savybė aprašoma atskiroje eilutėje. Apie objekto klasę sprendžiama iš jo aprašymui skirtų eilučių
skaičiaus: 2 eilutės - Tkontaktai, 3 eilutės – Tasmuo. Failo su 2 objektų aprašymais pavyzdys:
12
Jonas Kiškis
777777
Kaunas , Šlaito 2
*
Petras Kurmis
222222
*
Programos tekstas:
#include <iostream.h>
#include <fstream>
#include <string>
#include <cstdlib>
#include <iomanip>
//--------------------- Klasių šeimos aprašymas ------------------------
class Tkontaktai { // Bazinė klasė
char vardas[20];
char tel[12];
public:
Tkontaktai( ) {vardas[0] = tel[0] = '\0';} // konstruktorius
void saugok(char *v, char *t) {strcpy(vardas, v); strcpy(tel, t);} // pirmines f-jos perdengimas
virtual void rodyk( ) {cout << vardas << ", " << tel;} // Virtualus metodas
char *s_vardas( ) {return vardas;}
char *s_tel( ) {return tel;}
};
class Tasmuo :public Tkontaktai{ // Išvestinė klasė
char adresas[20];
public:
Tasmuo( ) {adresas[0] = '\0'; }
void saugok(char *v, char *t, char* a )
{Tkontaktai:: saugok(v,t); strcpy(adresas, a);}
virtual void rodyk( ) // Nuoroda virtual perteklin4
{Tkontaktai::rodyk(); cout << ", " << adresas << endl;}
char *s_adresas( ) {return adresas;}
};
//--------------------- Demonstracine programa ---------------------------------------------------
const size=128;
int main() {
int skaicius;
ifstream open("klases.txt"); // srautas skaitymui is failo
if (!open) {
cout<<"Klaida atidarant faila!";
exit(-1);
}
open>>skaicius;
Tkontaktai* x[10]; // Bazinės klasės rodyklių masyvas
Tasmuo a[10];
// Išvestinės klasės objektų masyvas
Tkontaktai z[10];

char temp1[size],temp2[size],temp3[size];
int xx=0, aa=0, massk=0;
open.getline(temp1, size);

while (open) { // skaitymas is txt failo


open.getline(temp1, size);
open.getline(temp2, size);
open.getline(temp3, size);

if (strlen(temp3)==1) {
z[xx].saugok(temp1, temp2);
x[massk++]= &z[xx++];
}
else {
a[aa].saugok(temp1, temp2, temp3);
x[massk++]= &a[aa++];
open.getline(temp1, size);
}
}
for(int i=0; i<skaicius; i++) // Išvedimas į ekraną virtualiais metodais
x[i]->rodyk();
open.close();
system("pause");
return 0;
}

Programa formuoja masyvą iš tekstiniame faile (klases.txt) įrašytų klasių Tkontaktai ir Tasmuo reikšmių.
Pirmoji failo eilutė nurodo jame aprašytų objektų skaičių, o objekto reikšmių aprašymai atskiriami
eilutėmis su simoliu '* ' jų pradžioje. Kiekviena savybė aprašoma atskiroje eilutėje. Apie objekto klasę
sprendžiama iš jo aprašymui skirtų eilučių skaičiaus: 2 eilutės - Tkontaktai, 3 eilutės – Tasmuo.
Tekstinio failo klases.txt turinys:
4
Jonas Kiskis
777777
Kaunas , Slaito 2
*
Petras Kurmis
222222
*
Vaidas Silinskis
555555
Kaunas, Taikos pr.
*
Jonas Jonaitis
66666
Kaunas, Liepu g.

Iš šio failo matyti, jog Petras Kurmis 222222 susideda iš 2 eilučių – Tkontaktai. Jonas Jonaitis, 66666,
Kaunas, Liepu g. – Tasmuo.
Programos darbo rezultatai:

3. Pakeiskite savo parengtą programą taip, kad klasių šeima būtų sudaroma abstrakčios klasės
pagrindu:
class Tbendra{ // Abstrakti bazinė klasė
public:
char vardas[20];
char tel[12];
virtual void rodyk()= 0; // Pirminė funkcija
void saugok(char *v, char *t) {strcpy(vardas, v); strcpy(tel, t);}
char *s_adresas( ) {return adresas;}
char *s_vardas( ) {return vardas;}
char *s_tel( )
{return tel;}
};
class Tkontaktai: public Tbendra{
public:
Tkontaktai( ) {vardas[0] = tel[0] = '\0';} // Konstruktorius

// Pirminės funkcijos perdengimas


void rodyk( ) {cout << vardas << ", " << tel;}
};
class Tasmuo :public Tbendra{
char adresas[20];
public:
Tasmuo( ) { vardas[0] = tel[0] = adresas[0] = '\0'; }
void saugok(char *v, char *t, char* a )
{Tbendra::saugok(v, t); strcpy(adresas, a);}
void rodyk( ) {cout << vardas << ", " << tel << ", " << adresas << endl;}
char *s_tel( ) {return tel;}
};
Programos tekstas:

#include <iostream.h>
#include <fstream>
#include <string>
#include <cstdlib>
#include <iomanip>
//--------------------- Klasių šeimos aprašymas ------------------------
class Tbendra{ // Abstrakti bazinė klasė
public:
char vardas[20];
char tel[12];
virtual void rodyk()= 0; // Pirminė funkcija
void saugok(char *v, char *t) {strcpy(vardas, v); strcpy(tel, t);}
//char *s_adresas( ) {return adresas;}
char *s_vardas( ) {return vardas;}
char *s_tel( ) {return tel;}
};
class Tkontaktai: public Tbendra{
public:
Tkontaktai( ) {vardas[0] = tel[0] = '\0';} // Konstruktorius
// Pirminės funkcijos
perdengimas
void rodyk( ) {cout << vardas << ", " << tel;}
};
class Tasmuo :public Tbendra{
char adresas[20];
public:
Tasmuo( ) { vardas[0] = tel[0] = adresas[0] = '\0'; }
void saugok(char *v, char *t, char* a )
{Tbendra::saugok(v, t); strcpy(adresas, a);}
void rodyk( ) {cout << vardas << ", " << tel << ", " << adresas << endl;} // pirm
char *s_tel( ) {return tel;}
};
//--------------------- Demonstracinė programa ------------------------
const size=128;
int main() {
int skaicius;
ifstream open("klases.txt");
if (!open) {
cout<<"Klaida atidarant faila!";
exit (-1);
}
open>>skaicius;

Tasmuo a[10],*tt; Tbendra * r[10];


// Išvestinės klasės objektų masyvas
Tkontaktai z[10], *t;

char temp1[size], temp2[size], temp3[size];


int xx=0, aa=0, massk=0;
open.getline(temp1, size);

while (open) {
open.getline(temp1, size);
open.getline(temp2, size);
open.getline(temp3, size);

if (strlen(temp3)==1) {
z[xx].saugok(temp1, temp2);
r[massk++]= &z[xx++];
}
else {
a[aa].saugok(temp1, temp2, temp3);
r[massk++]= &a[aa++];
open.getline(temp1, size);
}
}
for(int i=0; i<skaicius; i++) { // Išvedimas į ekraną virtualiais metodais
if (t = dynamic_cast<Tkontaktai*>(r[i])) {
t ->rodyk();
cout << endl;
}
if (tt = dynamic_cast<Tasmuo*>(r[i]))
tt ->rodyk();
}
open.close();
system("pause");
return 0;
}
Programa vėlgi formuoja masyvą iš tekstiniame faile (klases.txt) įrašytų klasių Tkontaktai ir Tasmuo
reikšmių. Šioje programoje klasių šeima sudaroma abstrakčios klasės pagrindu.

Programos darbo rezultatai:

Laboratorinis darbas Nr 5. Šabloninės klasės


1. Patikrinkite šabloninės masyvo klasės Tmasyvas savybes iliustruojančią programą ir išsiaiškinkite
šabloninių klasių naudojimo techniką. Klasėje Tmasyvas aprašytais priskyrimo operatoriumi ir
kopijų konstruktoriumi galima sukurti masyvų kopijas, o destruktoriumi – išlaisvinti masyvo
užimamą atmintinę. Klasės Tmasyvas aprašymas yra toks:
template <class T> class Tmasyvas{
T *p;
// Masyvui skiriamo lauko rodyklė
int n;
// Masyvo dydis
public:
Tmasyvas(int k=10){
// Konstruktorius
p = new T [k];
n = k;
}
Tmasyvas(Tmasyvas&);
// Kopijų konstruktorius
~Tmasyvas() {delete [] p; } // Destruktorius
int dydis () { return n; } // Dydžio patikrinimo metodas

// Kreipinys pagal indeksą


T & operator [] (int indeksas) { return p[indeksas]; }
Tmasyvas& operator = (Tmasyvas &); // Priskyrimo operatoriaus perdengimas
};
//------------------------Klasės Tmasyvas metodų realizacijos
template <class T> Tmasyvas<T> ::Tmasyvas(Tmasyvas & kitas){
n= kitas.dydis();
p= new T [n];
for (int i= 0; i<n; i++)
p[i]= kitas[i];
}
template <class T> Tmasyvas<T>& Tmasyvas<T>:: operator = (Tmasyvas & kitas){
if (this == &kitas) // Savos reikšmės perdavimas
return *this;
delete [] p;
// Atminties išlaisvinimas
n= kitas.dydis();
p= new T [n];
for (int i= 0; i<n; i++)
p[i]= kitas[i];
return *this;
}

Klasės savybių iliustravimo programa:


#include <iostream.h>
// čia reikia aprašyti šabloninę klasę Tmasyvas
//------------------ Pagrindinės funkcijos tekstas ----------------------
main(){
int i;
Tmasyvas<int> a(10); // Suderinimas sveikajam tipui
Tmasyvas<float> b(10), c; // Suderinimas float tipui
Tmasyvas<char*> e; // Suderinimas žodžių masyvui
char* duom[] = {"vienas", "du", "trys"};
for (i = 0; i<10; i++) // Atkarpos [0, 9] skaičių įrašymas
a[i]= i;
for (i = 0; i<10; i++) // Slankaus kablelio skaičių įrašymas
b[i]= i+0.1*i;
for (i = 0; i<3; i++) // Žodžių masyvo formavimas
e[i]= duom[i];
c = b;
// Masyvo perdavimas
b.Tmasyvas<float>::~Tmasyvas(); // Masyvo b pašalinimas
cout << "Sveikųjų skaičių masyvas: " << endl;
for (i = 0; i<10; i++)
cout << a[i] << '\t';
cout << endl<< "Slankaus kablelio skaičių masyvas: " << endl;
for (i = 0; i<10; i++)
cout << c[i] << '\t';
cout << endl<< "Žodžių masyvas: " << endl;
for (i = 0; i<3; i++)

cout<<e[i]<<'\t';
cout<<endl;
}

Programos darbo rezultatai:

Šablonines klasės naudojamos tada, kai pageidaujama aprašyti įvairiems duomenų tipams taikomų
veiksmų rinkinius, kaip šiuo atveju: integer, float, char. Tokių klasių antraštės papildomos duomenų tipą
perduodančio parametro aprašymu:
template <class T>

2. Pakeiskite masyvo elemento parinkimo pagal indeksą operatoriaus [ ] aprašymą taip, kad esant
indeksui už leistinų reikšmių ribų, ekrane būtų rodomas pranešimas apie klaidos pobūdį ir
programos darbas būtų nutraukiamas.
#include <iostream.h>
//--------------------------------------------------------
template <class T> class Tmasyvas{
T *p; // Masyvui
skiriamo lauko rodykle
int n; // Masyvo dydis
public:
Tmasyvas(int k = 10) { // Konstruktorius
p = new T [k];
n = k;
}
Tmasyvas(Tmasyvas&); // Kopiju
konstruktorius
~Tmasyvas() {delete [] p;} // Destruktorius
int dydis () { return n; } // Dydžio
patikrinimo metodas
T & operator [] (int indeksas) { // Kreipinys pagal
indeksa
if (indeksas >= n) {
cout << " KLAIDA! Indeksas virsyja leistinas ribas!! \n";
system("pause");
exit(-1);
}
return p[indeksas]; }
Tmasyvas& operator = (Tmasyvas &); //Priskyrimo operatoriaus
//perdengimas
};
//------------------------Klases Tmasyvas metodu realizacijos-------------------
template <class T> Tmasyvas<T> ::Tmasyvas(Tmasyvas & kitas) {
n = kitas.dydis();
p = new T [n];
for (int i= 0; i<n; i++)
p[i]= kitas[i];
}
template <class T> Tmasyvas<T>& Tmasyvas<T>:: operator = (Tmasyvas & kitas){
if (this == &kitas) // Savos reikšmes
perdavimas
return *this;
delete [] p; // Atminties
išlaisvinimas
n = kitas.dydis();
p = new T [n];
for (int i= 0; i<n; i++)
p[i]= kitas[i];
return *this;
}
//------------------ Pagrindines funkcijos tekstas -----------------------------
main() {
int i;
Tmasyvas<int> a(10); // Suderinimas
sveikajam tipui
Tmasyvas<float> b(10), c; // Suderinimas
float tipui
Tmasyvas<char*> e; // Suderinimas
žodžiu masyvui
char* duom[] = {"vienas", "du", "trys"};
for (i = 0; i < 11; i++) // Atkarpos [0, 9]
skaiciu irašymas
a[i]= i;
for (i = 0; i < 10; i++) // Slankaus
kablelio skaiciu rašymas
b[i]= i+0.1*i;
for (i = 0; i<3; i++) // Žodžiu masyvo
formavimas
e[i]= duom[i];
c = b; // Masyvo
perdavimas
b.Tmasyvas<float>::~Tmasyvas(); // Masyvo b
pašalinimas
cout << "Sveikuju skaiciu masyvas: " << endl;
for (i = 0; i < 10; i++)
cout << a[i] << '\t';
cout << endl<< "Slankaus kablelio skaiciu masyvas: " << endl;
for (i = 0; i < 10; i++)
cout << c[i] << '\t';
cout << endl<< "Zodziu masyvas: " << endl;
for (i = 0; i < 3; i++)
cout << e[i] << '\t';
cout << endl << endl;
system("pause");
}
Programos darbo rezultatai:

IF sąlygos pagalba yra tikrinamas indekso reikšmių kiekis ir esant jam didesniam už n parodomas
pranešimas apie klaidą. Programa baigia darbą. for (i = 0; i < 11; i++) cikle padidinus
reikšmę vientu, indeksas viršyja 10, programa parodo pranešimą apie klaidą ir
baigia darbą. Nepadidinus reikšmės vienetu programos darbo rezultatai išlieka
identiški aprašytiems ankstesniame punkte (5 ld.1).

3. Pakeiskite demonstracinę programą taip, kad masyvų elementų reikšmės būtų įvedamos klaviatūra.
#include <iostream.h>
#include <ctype.h>
//--------------------------------------------------------
template <class T> class Tmasyvas{
T *p; // Masyvui
skiriamo lauko rodykle
int n; // Masyvo dydis
public:
Tmasyvas(int k = 10) { // Konstruktorius
p = new T [k];
n = k;
}
Tmasyvas(Tmasyvas&); // Kopiju
konstruktorius
~Tmasyvas() {delete [] p;} // Destruktorius
int dydis () { return n; } // Dydžio
patikrinimo metodas
T & operator [] (int indeksas) { return p[indeksas]; } // Kreipinys pagal
indeksa
Tmasyvas& operator = (Tmasyvas &); // Priskyrimo operatoriaus
//perdengimas
};
//------------------------Klases Tmasyvas metodu realizacijos
template <class T> Tmasyvas<T> ::Tmasyvas(Tmasyvas & kitas) {
n = kitas.dydis();
p = new T [n];
for (int i= 0; i<n; i++)
p[i]= kitas[i];
}
template <class T> Tmasyvas<T>& Tmasyvas<T>:: operator = (Tmasyvas & kitas){
if (this == &kitas) // Savos reikšmes
perdavimas
return *this;
delete [] p; // Atminties
išlaisvinimas
n = kitas.dydis();
p = new T [n];
for (int i= 0; i<n; i++)
p[i]= kitas[i];
return *this;
}
//------------------ Pagrindines programos tekstas -----------------------------
main() {
int i;
char *rod, tmp[256];
Tmasyvas<int> a(10); // Suderinimas
sveikajam tipui
Tmasyvas<float> b(10); // Suderinimas
float tipui
Tmasyvas<char*> e; // Suderinimas
žodžiu masyvui

cout << "Iveskite penkis sveikuosius skaicius:\n"; // Sveikuju


skaiciu ivedimas
for (i = 0; i < 5; i++)
cin >> a[i];
cout << "\nSveikuju skaiciu masyvas: " << endl;
for (i = 0; i < 5; i++) //
Sveikuju skaiciu spausdinimas
cout << a[i] << " ";
cout << "\n\n";
cout << "Iveskite penkis slankaus kablelio skaicius:\n"; // Slankaus
kablelio skaiciu //ivedimas
for (i = 0; i < 5; i++)
cin >> b[i];
cout << "\nSlankaus kablelio skaiciu masyvas: " << endl;
for (i = 0; i < 5; i++) // Slankaus
kablelio skaiciu
//spausdinimas
cout << b[i] << " ";
cout << "\n\n";
cout << "Iveskite penkis zodzius skaicius:\n"; //
zodziu ivedimas
for (i = 0; i < 5; i++) {
cin >> tmp;
rod = new char [strlen(tmp) + 1];
strcpy(rod, tmp);
e[i] = rod;
}
cout << "\nSlankaus kablelio skaiciu masyvas: " << endl;
for (i = 0; i < 5; i++) // zodziu
spausdinimas
cout << e[i] << " ";
cout << "\n\n";
system("pause");
}

Reikšmės įvedamos panaudojant įvedimo ir išvedimo srautus cout<< ir cin>>:


cout << "Iveskite penkis sveikuosius skaicius:\n";
for (i = 0; i < 5; i++)
cin >> a[i];
Programos darbo rezultatai:
4. Parenkite specialią simbolių eilučių tvarkymo klasę, kuri leistų suderintas šiai klasei Tmasyvas
klasės objekto elementų reikšmes įvesti ir perduoti priskyrimo operatoriumi taip pat, kaip skaliarų
reikšmes.

#pragma hdrstop
#include <iostream.h>
class Ttekstas {
char *rod; // Rodykle
int n; // Eilutes ilgis simboliais
public:
Ttekstas (char *tekstas); // Tipines eilutes perdavimas
Ttekstas(); // Tušcios eilutes konstruktorius
Ttekstas (Ttekstas &kita); // Kopiju konstruktorius
~Ttekstas() { delete[] rod; } // Tipinis destruktorius
int ilgis() { return n; } // Ilg[io patikrinimo metodas
// Operatoriu perdengimas
Ttekstas & operator = (const Ttekstas &arg);
friend istream & operator >> (istream &, Ttekstas &);
friend ostream & operator << (ostream &, Ttekstas &);
};
//---------------Konstruktoriu realizacijos
Ttekstas::Ttekstas (char *tekstas) { // Tipines eilutes perdavimas
n=strlen(tekstas); // Perduodamos eilutes ilgis
rod=new char[n+1]; // Laukas perduodamai eilutei
strcpy(rod, tekstas); // Reikšmes kopijavimas
}
Ttekstas::Ttekstas() { // Tipinis konstruktorius
n=0;
rod=new char[1];
*rod='\0'; // Tušcia eilute
}
Ttekstas::Ttekstas(Ttekstas &kita) { // Kopiju konstruktorius
n=kita.n; // Lauko ilgis
rod=new char[n+1]; // Lauko paskyrimas
strcpy(rod, kita.rod); // Argumento lauko kopijavimas
}
Ttekstas &Ttekstas::operator = (const Ttekstas &arg) {
if (this!=&arg) {
delete []rod;
n=arg.n;
rod= new char[n+1];
strcpy(rod, arg.rod);
}
return *this;
}
istream & operator >> (istream &instr, Ttekstas &arg) {
char buf[80];
instr>>buf;
arg.n=strlen(buf);
arg.rod=new char[arg.n+1];
strcpy(arg.rod, buf);
return instr;
}
ostream & operator << (ostream &outstr, Ttekstas &arg) {
outstr<<arg.rod;
return outstr;
}
//------------------ Pagrindines funkcijos tekstas -----------------------------
main() {
int i;
Ttekstas a[4], b[4];
for (i=0; i<3; i++) {
cout<<"**********************"<<endl;
cout<<"Iveskite zodi:"<<endl;
cin>>a[i];
b[i]=a[i];
delete [] a;
}
cout<<"**********************"<<endl;
cout<<"Is zodziu sudarytas masyvas:"<<endl;
cout<<""<<endl;
for (i=0; i<3; i++)
cout<<b[i]<<endl;
cout<<""<<endl;
system("pause");
return 0;
}

Programos darbo rezultatai:

Naujos operatorių reikšmės apibrėžiamos kaip draugiškos(asocijuotos) funkcijos objektų klasei Ttekstas.
Vienas iš šių operatorių argumentų yra įvedimo srauto (istream) arba išvedimo srauto klasė (ostream).

Laboratorinis darbas Nr 6. Susieti sąrašai


Pagrindiniai sąrašų tvarkymo veiksmai, kurie naudojami įvairių tipų sąrašuose, yra tokie:
• naujo elemento sukūrimas;
• naujo elemento įtepimas už rodyklės nurodomo sąrašo elemento;
• naujo elemento įterpimas prieš rodyklės nurodomą sąrašo elementą;
• rodyklės nurodomo sąrašo elemento pašalinimas;

1. Patikrinkite programą, kuri iliustruoja anksčiau aprašytus sąrašų tvarkymo veiksmus:


#include <iostream.h>
template <class T>
struct Tnode {
T duomenys;
// Duomenų laukas
struct Tnode *kitas;
// Ryšio dalis
};
//---------------------------- Čia reikia įterpti --------------------
//--------- Funkcijų Naujas, Prijungti, Perrinkti ir Trinti aprašymai
//--------------------------------------------------------------------
main(){
Tnode<int> * vienas, *du, *trys;
vienas= Naujas<int>(1); // Sąrašo elementų kūrimas
du= Naujas<int>(2);
trys= Naujas<int>(3);
Prijungti<int>(vienas, du); // Sąrašo formavimas
Prijungti<int>(du, trys);
Perrinkti (vienas); // Sąrašo parodymas ekrane
cout<< endl;
while (vienas)
// Sąrašo naikinimas
temp= Trinti (vienas);
if(!vienas) cout<<"Sąrašas tuščias";
}

Programa atlieka tiesinio skaičių sąrašo formavimą, peržiūrą ir tvarkymą.


Programos darbo rezultatai:

2.Anksčiau parengtoje programoje sąrašo duomenų peržiūrai panaudokite rekursinę funkciją ir


išsiaiškinkite jos sudarymo principus:
void Perrinkti (Tnode<T> *x){
if (x){
// Rekursijos tęsimo sąlyga
cout<<x->duomenys<<'\t'; // Elemento parodymas ekrane
Perrinkti (x->kitas); // Rekursinis kreipinys
}
else
cout<< endl; // Baigiamasis veiksmas
}

Programos tekstas:
#include <iostream.h>
template <class T>
struct Tnode {
T duomenys; // Duomenu laukas
struct Tnode *kitas; // Ryšio dalis
};
//------------------------------------------------------------------------------------
template<class T> // Šablonine sarašo elemento sukurimo funkcija
Tnode<T> * Naujas (T x){
Tnode<T> * temp= new Tnode<T>; // Atminties lauko paskyrimas
if (temp){ // Jei atminti paskirti pavyko
temp->duomenys= x;
temp->kitas= NULL;
}
return temp; // Elemento adreso gražinimas
}
template<class T>
void Prijungti (Tnode<T> *x, Tnode<T> *y){
x->kitas = y; // Prijungiamo elemento adresas
}
template<class T>
Tnode<T>* Trinti (Tnode<T>*x){
Tnode<T> *t= x; // Pagalbine rodykle
if (x){
// Ar rodykle nera NULL
x= x ->kitas; // Paliekamos dalies adresas
delete t; // Atminties išlaisvinimas
}
return x; // Naujo sekos adreso gražinimas
}

template<class T>
void Perrinkti (Tnode<T> *x){
if (x){ // Rekursijos tesimo salyga
cout << x->duomenys << '\t'; // Elemento parodymas ekrane
Perrinkti (x->kitas); // Rekursinis kreipinys
}
else
cout<< endl; // Baigiamasis veiksmas
}
//------------------------------------------------------------------------------------
main(){
Tnode<int> * vienas, *du, *trys;
vienas = Naujas<int>(1); // Sarašo elementu kurimas
du = Naujas<int>(2);
trys = Naujas<int>(3);
Prijungti<int>(vienas, du); // Sarašo formavimas
Prijungti<int>(du, trys);
Perrinkti (vienas); // Sarašo parodymas ekrane
cout<< endl;
while (vienas) // Sarašo naikinimas
vienas = Trinti (vienas);
if(!vienas)
cout << "Sarasas tuscias \n\n";
system("pause");
}
3. Pertvarkykite rekursinę peržiūros funkciją taip, kad duomenys ekrane būtų rodomi priešinga seka.
Tam išvedimo į ekraną aprašymo sakinį reikia sukeisti vietomis su rekursinio kreipinio sakiniu.
Paaiškinkite, kodėl toks sukeitimas keičia duomenų rodymo seką.

#include <iostream.h>
template <class T>

struct Tnode {
T duomenys; // Duomenu laukas
struct Tnode *kitas; // Ryšio dalis
};
//--------------------------
template<class T> // Šablonine sarašo elemento sukurimo funkcija
Tnode<T> * Naujas (T x){
Tnode<T> * temp= new Tnode<T>; // Atminties lauko paskyrimas
if (temp){ // Jei atminti paskirti pavyko
temp->duomenys= x;
temp->kitas= NULL;
}
return temp; // Elemento adreso gražinimas
}
template<class T>
void Prijungti (Tnode<T> *x, Tnode<T> *y){
x->kitas = y; // Prijungiamo elemento adresas
}
template<class T>
Tnode<T>* Trinti (Tnode<T>*x){
Tnode<T> *t= x; // Pagalbine rodykle
if (x){ // Ar rodykle nera NULL
x= x ->kitas; // Paliekamos dalies adresas
delete t; // Atminties išlaisvinimas
}
return x; // Naujo sekos adreso gražinimas
}
template<class T>
void Perrinkti (Tnode<T> *x){
if (x){ // Rekursijos tesimo salyga
Perrinkti (x->kitas); // Rekursinis kreipinys
cout << x->duomenys << '\t'; // Elemento parodymas ekrane
}
}
main(){
Tnode<int> * vienas, *du, *trys;
vienas = Naujas<int>(1); // Sarašo elementu kurimas
du = Naujas<int>(2);
trys = Naujas<int>(3);
Prijungti<int>(vienas, du); // Sarašo formavimas
Prijungti<int>(du, trys);
Perrinkti (vienas); // Sarašo parodymas ekrane
cout<< endl;
while (vienas) // Sarašo naikinimas
vienas = Trinti (vienas);
if(!vienas)
cout << "\nSarasas tuscias\n\n";
system("pause");
}

Programos darbo rezultatai:


Duomenų išvedimo sakinį (cout << x->duomenys << '\t'; ) sukeitus vietomis su rekursinio kreipinio
sakiniu (cout << x->duomenys << '\t';), pasikeičia duomenų rodymo seka iš 1 2 3 į 3 2 1, nes rodyklė po
rekursinio sakinio būna ne pradžioje, o gale, todėl duomenys išvedami atvirkščia tvarka.

4. Pritaikykite parengtą programą klaviatūra įvedamų žodžių sąrašui sudaryti. Įvedimas turi būti
nutraukiamas įvedus žodį „q“.
#include <iostream.h>
template <class T>
struct Tnode {
T duomenys; // Duomenu laukas
struct Tnode *kitas; // Ryšio dalis
};
//------------------------------------------------------------------------------------
template<class T> // Šablonine sarašo elemento sukurimo funkcija
Tnode<T> * Naujas (T x){
Tnode<T> * temp= new Tnode<T>; // Atminties lauko paskyrimas
if (temp){ // Jei atminti paskirti pavyko
temp->duomenys = x;
temp->kitas= NULL;
}
return temp; // Elemento adreso gražinimas
}

template<class T>
void Prijungti (Tnode<T> *x, Tnode<T> *y){
x->kitas = y; // Prijungiamo elemento adresas
}

template<class T>
Tnode<T>* Trinti (Tnode<T>*x){
Tnode<T> *t= x; // Pagalbine rodykle
if (x){ // Ar rodykle nera NULL
x= x ->kitas; // Paliekamos dalies adresas
delete t; // Atminties išlaisvinimas
}
return x; // Naujo sekos adreso gražinimas
}
template<class T>
void Perrinkti (Tnode<T> *x){
if (x){ // Rekursijos tesimo salyga
cout << x->duomenys << " "; // Elemento parodymas ekrane
Perrinkti (x->kitas); // Rekursinis kreipinys
}
}

main(){
char *tmp, eil[256];
cout << "Iveskite zodzius (pabaigai q):\n";
cin >> eil;
tmp = new char [strlen(eil) + 1];
strcpy(tmp, eil);
Tnode<char*> *sarasas, *zodis, *pradzia;
sarasas = Naujas<char*>(tmp);
pradzia = sarasas;
while (strcmp(tmp, "q") != 0) {
cin >> eil;
tmp = new char [strlen(eil) + 1];
strcpy(tmp, eil);
if (strcmp(tmp, "q") != 0) {
zodis = Naujas<char*>(tmp);
Prijungti<char*>(sarasas, zodis);
sarasas = sarasas->kitas;
}
}
cout << "\nVisas masyvas:\n";
Perrinkti(pradzia);
cout << endl << endl;
system("pause");
}

Programos darbo rezultatai:

5. Patikrinkite programą, kurioje sąrašo tvarkymui naudojama speciali jų elementų tvarkymui


pritaikyta šabloninė klasė:

#include <iostream.h>
#include <fstream.h>
//---------------------------------------------------------------------------
template <class T>
struct Tnode {
T duomenys; // Duomenu laukas
struct Tnode *kitas; // Ryšio dalis
};
//------------------------------------------------------------------------------------
template<class T> // Šablonine sarašo
elemento //sukurimo funkcija
Tnode<T> * Naujas (T x){
Tnode<T> * temp= new Tnode<T>; // Atminties lauko paskyrimas
if (temp){ // Jei atminti
paskirti pavyko
temp->duomenys = x;
temp->kitas= NULL;
}
return temp; // Elemento
adreso gražinimas
}
template<class T>
void Prijungti (Tnode<T> *x, Tnode<T> *y){
x->kitas = y; // Prijungiamo
elemento adresas
}
template<class T>
Tnode<T>* Trinti (Tnode<T>*x){
Tnode<T> *t= x; // Pagalbine
rodykle
if (x){ // Ar rodykle nera NULL
x= x ->kitas; // Paliekamos
dalies adresas
delete t; // Atminties
išlaisvinimas
}
return x; // Naujo sekos adreso
gražinimas
}
template<class T>
void Perrinkti (Tnode<T> *x){
if (x){ // Rekursijos
tesimo salyga
cout << x->duomenys << " "; // Elemento
parodymas ekrane
Perrinkti (x->kitas); // Rekursinis kreipinys
}
}
//------------------------------------------------------------------------------------
main(){
ifstream skaityti("duomenys.txt");
char *tmp, eil[256];
skaityti >> eil;
tmp = new char [strlen(eil) + 1];
strcpy(tmp, eil);
Tnode<char*> *sarasas, *zodis, *pradzia;
sarasas = Naujas<char*>(tmp);
pradzia = sarasas;
while (!skaityti.eof()) {
skaityti >> eil;
tmp = new char [strlen(eil) + 1];
strcpy(tmp, eil);
zodis = Naujas<char*>(tmp);
Prijungti<char*>(sarasas, zodis);
sarasas = sarasas->kitas;
}
cout << "Is failo nuskaityti zodziai:\n";
Perrinkti(pradzia);
cout << endl << endl;
system("pause");
}

Programos darbo rezultatai:


5. Pritaikykite 4 punkte aprašytą programą iš tekstinio failo skaitomų žodžių sąrašui parengti.

#include <iostream.h>
#include <fstream.h>
//---------------------------------------------------------------------------
template <class T>
struct Tnode {
T duomenys; // Duomenu laukas
struct Tnode *kitas; // Ryšio dalis
};
//---------------------------------------------------------------------------
template<class T> // Šablonine sarašo elemento sukurimo funkcija
Tnode<T> * Naujas (T x){
Tnode<T> * temp= new Tnode<T>; // Atminties lauko paskyrimas
if (temp){ // Jei atminti paskirti pavyko
temp->duomenys = x;
temp->kitas= NULL;
}
return temp; // Elemento adreso gražinimas
}
template<class T>
void Prijungti (Tnode<T> *x, Tnode<T> *y){
x->kitas = y; // Prijungiamo elemento adresas
}
template<class T>
Tnode<T>* Trinti (Tnode<T>*x){
Tnode<T> *t= x; // Pagalbine rodykle
if (x){ // Ar rodykle nera NULL
x= x ->kitas; // Paliekamos dalies adresas
delete t; // Atminties išlaisvinimas
}
return x; // Naujo sekos adreso gražinimas
}
template<class T>
void Perrinkti (Tnode<T> *x){
if (x){ // Rekursijos tesimo salyga
cout << x->duomenys << " "; // Elemento parodymas ekrane
Perrinkti (x->kitas); // Rekursinis kreipinys
}
}
//------------------------------------------------------------------------------------
main(){
ifstream skaityti("duom.txt");
char *tmp, eil[256];
skaityti >> eil;
tmp = new char [strlen(eil) + 1];
strcpy(tmp, eil);
Tnode<char*> *sarasas, *zodis, *pradzia;
sarasas = Naujas<char*>(tmp);
pradzia = sarasas;
while (!skaityti.eof()) {
skaityti >> eil;
tmp = new char [strlen(eil) + 1];
strcpy(tmp, eil);
zodis = Naujas<char*>(tmp);
Prijungti<char*>(sarasas, zodis);
sarasas = sarasas->kitas;
}
cout << "Is failo nuskaitytas tekstas:\n";
cout<<""<<endl;
Perrinkti(pradzia);
cout << endl << endl;
system("pause");
}

Programos darbo rezultatai:

Aprašymuose šabloninės klasės viduje suderinimo parametras <T> nenaudojamas, o metodų realizacijų
aprašymuose šabloninės klasės išorėje šį parametrą nurodyti būtina.

Laboratorinis darbas Nr 7. Šabloninės steko ir eilės klasės


Siekiant sugriežtinti sąrašams taikomus veiksmus ir supaprastinti jų tvarkymą, sudaromos specialios
šabloninės konteinerių klasės. Pavyzdžiui, eilių aprašymui skirto konteinerio uždaroje dalyje saugomi
eilės pradžios ir pabaigos adresai (1 pav.), o sąsajos dalyje aprašomi eilės tvarkymo metodai.

1. Parenkite ir patikrinkite programą, kuri iliustruoja klasės Tque tvarkymo veiksmus:


// ------ Klasės Tque patikrinimo programa -----------------------
#include <iostream.h>
//-------------- Čia reikia įterpti klasių Tnode ir Tque
aprašymus--------------------
main(){
Tque<int> x;
// Tuščios eilės sukūrimas
for (int i = 0; i<10; i++) // Skaičių eilės
formavimas
x.Add(i);
cout<< "Eilėje buvo šie skaičiai:"<< endl;
while (!(x.Empty()))
cout<<x.Pop()<< endl;
}
Programos tekstas:
#include <iostream.h>
#include <stdlib.h>
template <class T>
// ----------------------- Saraso elementu klase -------------
class Tnode {
Tnode *kitas;
public:
T duomenys;
Tnode (T re, Tnode * rod = NULL): // Konstruktorius
duomenys(re), kitas (rod) { };
void Prijungti (Tnode *y){
kitas= y;
}
Tnode * Rkitas () {return kitas; } // Kreipinys ? ryšio dal?
};
template <class T>
class Tque {
Tnode<T> *head;
Tnode<T> *tail;
public:
Tque () {head= NULL; tail= NULL; }
T Pop (){
Tnode<T> *temp= head;
T re= head->duomenys;
head = head->Rkitas();
delete temp;
return re;
}
void Add (T y){
Tnode<T> * temp= new Tnode<T> (y); // Naujo elemento suk?rimas
if(head){
tail->Prijungti(temp);
tail=tail->Rkitas();
}
else
head= tail= temp;
}
~Tque<T>();
int Empty(){
if(head)
return 0;
else
return 1;
}
};
template <class T>
Tque<T>::~Tque<T>() {
Tnode<T> *temp;
while (head){
temp = head;
head = head->Rkitas();
delete temp;
}
}
main(){
Tque<int> x;
// Tuš?ios eil?s suk?rimas
for (int i = 0; i<10; i++) // Skai?i? eil?s formavimas
x.Add(i);
cout<< "Eileje buvo sie skaiciai:"<< endl;
while (!(x.Empty()))
cout<<x.Pop()<< endl;
system("pause");
}

Programos darbo rezultatai:


2. Pritaikykite 1 punkto programą klasei Tstack ir patikrinkite pertvarkytos programos darbą.
#include <iostream.h>
#include <stdlib.h>
#pragma hdrstop
#pragma argsused
template <class T>
// ----------------------- Saraso elementu klase -------------
class Tnode {
Tnode *kitas; // Ryšio dalis
public:
T duomenys; // Duomenų laukas
Tnode (T re, Tnode * rod = NULL): // Konstruktorius
duomenys(re), kitas (rod) { };
Tnode * Paimti (); // Prijungto elemento pašalinimas
void Prijungti (Tnode *y){ // Prijungimo metodas
kitas= y;
}
Tnode *Papildyti (Tnode *y){ // Papildymo metodas
y->kitas = this; // Aktyvaus objekto rodyklė
return y; // Junginio adresas
}
Tnode * Rkitas () {return kitas; } // Kreipinys į ryšio dalį
};
//--------------------- Metodo Paimti realizacija --------------------------
template <class T>
Tnode<T>* Tnode<T>:: Paimti (){ // Pašalinimo metodo realizacija
Tnode<T> *t= kitas; // Pagalbinė rodyklė
if (kitas) // Ar rodyklė nėra NULL
kitas= t ->kitas; // Paliekamos dalies adresas
return t; // Pašalinto elemento adresas
}
//------------------------------------------------------------------------------
template <class T>
class Tstack {
Tnode<T> *head; // Eilės pradžia (galva)
public: // Metodų prototipai
Tstack () {head= NULL; } // Tuščio steko konstruktorius
// Pradinio elemento skaitymas
T Pop (){ // Elemento pašalinimo metodas
Tnode<T> *temp= head; // Šalinamo elemento adresas
T re= head->duomenys; // Šalinamo elemento duomenys
head = head->Rkitas(); // Elemento pašalinimas
delete temp; // Atminties išlaisvinimas
return re; // Reikšmes gražinimas
}
void Push (T y);
~Tstack<T>();
int Empty(){if(head)return 0; else return 1;}
};
//------------------------Metodo Push realizacija-----------------------------
template <class T>
void Tstack<T> :: Push (T y){
Tnode<T> * temp= new Tnode<T> (y,head); // Naujas elementas pradžioje
head= temp; // Naujas pradžios adresas
}
//---------------------Destruktoriaus realizavimas----------------------------
template <class T>
Tstack<T>::~Tstack<T>() {
Tnode<T> *temp;
while (head){
temp = head;
head = head->Rkitas();
delete temp;
}
}
//-----------------------Demonstracinė programa-------------------------------
main(){
Tstack<int> x; // Tuščios eilės sukurimas
for (int i = 0; i<10; i++) // Skaičiu eilės formavimas
x.Push(i);
cout<< "Eileje buvo sie skaiciai:"<< endl;
while (!(x.Empty()))
cout<<x.Pop()<< endl;
system ("pause");
}
Programos darbo rezultatai: