Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по Технологии разработки ПО 2005.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
833.54 Кб
Скачать

Массивы и классы

На примере класса Tovar мы уже видели, что массивы могут быть использованы в качестве полей класса. Рассмотрим пример класса, который моделирует структуру данных – стек.

class Stack {

private:

static const int MAX=5;

int st[MAX]; // стек в виде массива

int top; // вершина стека

public:

Stack( ) { top = 0; }

void push(int a) { // поместить в стек

st[top] = a;

if(top < MAX-1) top++;

}

int pop( ) { // взять из стека

int res=st[top];

top--;

return res;

}

int max() { return MAX; }

};

//---------------------------------------------------------------------------

int main ( ) {

Stack s1;

int i;

for(i=1; i<=s1.max(); i++) s1.push(i);

for(i=0; i<s1.max(); i++) cout << s1.pop() << endl;

getch(); return 0;

}

Важным членом этого класса является массив st. Переменная top хранит индекс последнего элемента, положенного в стек. Этот элемент располагается на вершине стека.

Стандарт С++ позволяет объявлять константы внутри класса. Таким образом вместо строки enum { MAX = 5 }; мы использовали запись static const int MAX = 5; , но имейте ввиду, что некоторые компиляторы (в отличие от С++Builder) не позволяют использовать эту конструкцию.

Рассмотрим принцип работы программы. При добавлении в стек нового элемента индекс переменной top увеличивается, и она будет показывать на новую вершину стека. При извлечении (удалении) элемента из стека индекс переменной top уменьшается. В данном случае не нужно стирать старое значение из памяти при удалении элемента, оно просто становится несущественным.

Массивы объектов

На прошлых занятиях мы часто разбирали примеры класса Distance, который объединял футы и дюймы в своём объекте, представляющий собой новый тип данных. На следующем примере продемонстрируем массив таких объектов.

class Distance { //класс англиских мер длины

private:

int feet;

float inch;

public:

void getdist() { //получение информации при вводе

cout << "\nVvedi futy: "; cin >> feet;

cout << "Vvedi duimy: "; cin >> inch;

}

void showdist() const { //вывод информации

cout << feet << "'-" << inch << endl;

}

};

//------------------------------------------------------------------

int main() {

const int MAX = 100;

Distance dist[MAX]; //массив объекта

int n=0; //сч¸тчик данных

char ans; //ответ пользователя ('y' или 'n')

do {

cout << "Vvod dliny N " << n+1;

dist[n].getdist();

n++;

cout << "\nProdol. vvod (y/n)?: "; cin >> ans;

}while(ans == 'y' && n<MAX);

for(int j=0; j<n; j++) { //показать все введ¸нные значения длин

cout << "\nDlina N " << j+1 << ": ";

dist[j].showdist();

}

getch(); return 0;

}

Д/З

Измените данную программу таким образом, чтобы она позволяла вычислять сумму элементов массива dist.

Ответ

class Distance {

private:

int feet;

float inch;

public:

Distance() { feet=0; inch=0.0; }

void getdist() {

cout << "\nVvedi futy: "; cin >> feet;

cout << "Vvedi duimy: "; cin >> inch;

}

void showdist() const {

cout << feet << "'-" << inch << endl;

}

Distance plus(Distance a2) {

Distance s;

s.inch = inch + a2.inch;

s.feet = 0;

if(s.inch >= 12.0) {

s.inch = s.inch - 12.0;

s.feet++;

}

s.feet += feet + a2.feet;

return s;

}

};

//------------------------------------------------------------------

int main() {

const int MAX = 100;

Distance dist[MAX];

int n=0, j;

char ans;

do {

cout << "Vvod dliny N " << n+1;

dist[n].getdist();

n++;

cout << "\nProdol. vvod (y/n)?: "; cin >> ans;

}while(ans == 'y' && n<MAX);

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

cout << "\nDlina N " << j+1 << ": ";

dist[j].showdist();

}

cout << "\n Vychislit summu elementov(y/n): "; cin >> ans;

if(ans=='y') {

Distance sum;

for(j=0; j<n; j++)

sum = sum.plus(dist[j]);

cout << "\n Summa elementov = "; sum.showdist();

}

getch(); return 0;

}

Рассмотрим теперь класс Tovar на примере программы, позволяющей: 1) создавать динамический массив типа Tovar и дозаписывать его в бинарный файл; 2) считывать бинарный файл и динамически формировать массив типа Tovar.

const int N=30;

class Tovar {

private:

char name[N];

int number;

float cena;

public:

void getdata() {

cin.get();

cout << "\n Vvedite naimenovanie tovara: "; cin.getline(name, N);

cout << " Vvedite nomer tovara: "; cin >> number;

cout << " Vvedite stoimost tovara: "; cin >> cena;

}

void showdata() {

cout << name << " " << number << " " << cena;

cout << endl;

}

void savefile(char* fname) {

ofstream fout(fname, ios::binary | ios::app);

if(!fout) { cout << "\nOshibka zapisi faila!"; getch(); return; }

fout.write(name, N);

fout.write(reinterpret_cast<char*>(&number), sizeof(int));

fout.write(reinterpret_cast<char*>(&cena), sizeof(float));

fout.close();

}

void readfile(char* fname, int sme) {

ifstream fin(fname, ios::binary);

if(!fin) { cout << "\nOshibka chtenia faila!"; getch(); return ; }

fin.seekg(sme, ios::beg);

fin.read(name, N);

fin.read(reinterpret_cast<char*>(&number), sizeof(int));

fin.read(reinterpret_cast<char*>(&cena), sizeof(float));

}

};

//---------------------------------------------------------------------------

int main() {

int K, i, dfb, dlz, KZ, sm;

char otv, *filename="c:\\os\\tovar_class\\tovar3\\tovarbd.dat";

cout << "Skolko zapisei hotite dobavit: "; cin >> K;

Tovar *tm = new Tovar [K];

for(i=0; i<K; i++) {

cout << "\nZapis " << i+1 << ":" << endl;

tm[i].getdata();

}

cout << "\n Sohranit dannye?(y/n) "; cin >> otv;

if(otv=='y') {

for(i=0; i<K; i++) tm[i].savefile(filename);

cout << "\n Fail zapisan!" << endl;

}

delete [] tm;

ifstream fin(filename, ios::binary);

if(!fin) { cout << "\nOshibka chtenia faila!"; getch(); return 1; }

fin.seekg(0, ios::end); dfb = fin.tellg(); fin.seekg(0, ios::beg);

dlz = N + sizeof(int) + sizeof(float);

KZ=dfb/dlz;

fin.close();

Tovar *mas = new Tovar [KZ];

for(i=0; i<KZ; i++) {

sm=i*dlz; //смещение

mas[i].readfile(filename, sm);

}

cout << "\n Fail sodergit: " << endl;

for(i=0; i<KZ; i++) {

mas[i].showdata();

}

getch(); return 0;

}

На самом деле это не самый лучший способ решения данной задачи. Хотя это никем не оговаривается, но я считаю, что методы класса необходимо использовать не для обработки и модификации данных, а для доступа к данным класса. Рассмотрим альтернативный и более лаконичный вариант решения данной задачи, который в полной мере раскрывает отличие методов от функций.

const int N=30;

//---------------------------------------------------------------------------

class Tovar {

private:

char name[N];

int number;

float cena;

public:

void dobav_zap() {

cout << "\n Vvedite naimenovanie tovara: "; cin >> name;

cout << " Vvedite nomer tovara: "; cin >> number;

cout << " Vvedite stoimost tovara: "; cin >> cena;

}

void show() {

cout << name << " " << number << " " << cena << endl;

}

char pop(int i) {

return name[i];

}

char* getname() {

return name;

}

};

void sort(Tovar mas[], int R);

void redakt(Tovar ma[], int K);

void savefile(char* fname, Tovar *mm, int& K);

//---------------------------------------------------------------------------

int main() {

char ans;

char *fn = "c:\\os\\tovar_class\\tovar_cl.dat";

int KZ=0, dfb=0;

Tovar *m;

cout << "\n Dobavit zapis v fail?(y/n) "; cin >> ans;

if(ans=='y') {

Tovar a1;

a1.dobav_zap();

ofstream fout(fn, ios::binary | ios::app);

if(!fout) { cout << "\nOshibka faila!"; getch(); return 1; }

fout.write(reinterpret_cast<char*>(&a1), sizeof(Tovar));

fout.close();

}

cout << "\n Otsortirovat i pokazat zapisi?(y/n) "; cin >> ans;

if(ans=='y') {

ifstream fin(fn, ios::binary);

if(!fin) { cout << "\nOshibka faila!"; getch(); return 1; }

fin.seekg(0, ios::end); dfb=fin.tellg(); fin.seekg(0, ios::beg);

KZ = dfb/sizeof(Tovar);

m = new Tovar [KZ];

fin.read(reinterpret_cast<char*>(m), dfb);

fin.close();

sort(m, KZ);

for(int i=0; i<KZ; i++) m[i].show();

cout << "\n Budete redaktirovat zapisi?(y/n) "; cin >> ans;

if(ans=='y') {

redakt(m, KZ);

cout << "\n Sohranit dannye?(y/n) "; cin >> ans;

if(ans=='y') savefile(fn, m, KZ);

}

}

getch(); return 0;

}

//---------------------------------------------------------------------------

void sort(Tovar mas[], int R) {

int i, j;

for(i=0; i<R-1; i++) {

for(j=i+1; j<R; j++) {

if(mas[j].pop(0) < mas[i].pop(0)) {

Tovar a = mas[i]; mas[i] = mas[j]; mas[j] = a;

}

}

}

}

//---------------------------------------------------------------------------

void redakt(Tovar ma[], int K) {

char namer[N];

cout << "\n Ukagite naimenovanie tovara: "; cin >> namer;

int l = strlen(namer);

int ks=0;

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

if(strncmp(namer, ma[i].getname(), l)==NULL) {

ma[i].dobav_zap();

ks++;

}

}

if(ks==0) { cout << "\n Takogo reisa net !"; }

}

//---------------------------------------------------------------------------

void savefile(char* fname, Tovar *mm, int& K) {

ofstream fout(fname, ios::binary);

if(!fout) { cout << "\nOshibka faila!"; getch(); return ; }

fout.write(reinterpret_cast<char*>(mm), sizeof(Tovar)*K);

cout << "\n Dannye sohraneny.";

fout.close();

}