Теперь вы понимаете фундаментальные идеи, положенные в основу классов С++. В остальной части книги вы увидите все новые и новые примеры применения классов.
[tip]
Упражнение 1
Определите структуру Sample, содержащую два целочисленных элемента данных. Напишите программу, которая объявит два объекта типа Sample с именами а и b. Установите значения для элементов данных, относящихся к объекту а, и затем убедитесь, что можете копировать значения объекта b простым присвоением
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <iostream> using std::cout; using std::endl; struct Sample { int n1; int n2; }; int main() { Sample a,b; a.n1=3; a.n2=4; b.n1=0; b.n2=0; cout <<"a.n1= "<<a.n1<<" a.n2= "<<a.n2<<endl; cout <<"b.n1= "<<b.n1<<" b.n2= "<<b.n2<<endl; b=a; cout <<"a.n1= "<<a.n1<<" a.n2= "<<a.n2<<endl; cout <<"b.n1= "<<b.n1<<" b.n2= "<<b.n2<<endl; return 0; } |
Вывод:
[/tip]
[tip]
Упражнение 2
Добавьте в структуру Sample из предыдущего упражнения член типа char* по имени sPtr. Когда будете заполнять данными объект а, динамически создайте буфер символов, инициализированный строкой «Hellow World!». и установите на него указатель a.sptr. Скопируйте объект а в объект b. Что произойдет, когда вы измените содержимое символьного буфера, на который указывает указатель a.sptr, а затем выдедете содержимое строки, на который указывает указатель b.sptr? Объясните, что случилось? Как это исправить?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include <iostream> using std::cout; using std::endl; #include <cstring> using std::strcpy; struct Sample { int n1; int n2; char* sPtr; }; int main() { Sample a,b; a.n1=3; a.n2=4; a.sPtr=new char[30]; strcpy(a.sPtr,"hellow world"); b.n1=0; b.n2=0; cout <<"a.n1= "<<a.n1<<" a.n2= "<<a.n2<<" a.sPtr= "<<a.sPtr<<endl; cout <<"b.n1= "<<b.n1<<" b.n2= "<<b.n2<<endl; b=a; cout <<"a.n1= "<<a.n1<<" a.n2= "<<a.n2<<" a.sPtr= "<<a.sPtr<<endl; cout <<"b.n1= "<<b.n1<<" b.n2= "<<b.n2<<" b.sPtr= "<<b.sPtr<<endl; strcpy(a.sPtr,"eb ta mazafaka bich"); cout <<"a.n1= "<<a.n1<<" a.n2= "<<a.n2<<" a.sPtr= "<<a.sPtr<<endl; cout <<"b.n1= "<<b.n1<<" b.n2= "<<b.n2<<" b.sPtr= "<<b.sPtr<<endl; return 0; } |
Вывод:
[/tip]
[tip]
Упражнение 3
Создайте функцию, получающую в качестве аргумента указатель на объект типа Sample и выводящую значения всех членов переданного ей объекта. Проверьте эту функцию, расширив программу, написанную в предыдущем упражнении.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
#include <iostream> using std::cout; using std::endl; #include <cstring> using std::strcpy; struct Sample { int n1; int n2; char* sPtr; }; void f(Sample* ptr); int main() { Sample a,b; a.n1=3; a.n2=4; a.sPtr=new char[30]; strcpy(a.sPtr,"hellow world"); b.n1=0; b.n2=0; cout <<"a.n1= "<<a.n1<<" a.n2= "<<a.n2<<" a.sPtr= "<<a.sPtr<<endl; cout <<"b.n1= "<<b.n1<<" b.n2= "<<b.n2<<endl; b=a; cout <<"a.n1= "<<a.n1<<" a.n2= "<<a.n2<<" a.sPtr= "<<a.sPtr<<endl; cout <<"b.n1= "<<b.n1<<" b.n2= "<<b.n2<<" b.sPtr= "<<b.sPtr<<endl; strcpy(a.sPtr,"eb ta mazafaka bich"); cout <<"a.n1= "<<a.n1<<" a.n2= "<<a.n2<<" a.sPtr= "<<a.sPtr<<endl; cout <<"b.n1= "<<b.n1<<" b.n2= "<<b.n2<<" b.sPtr= "<<b.sPtr<<endl; cout <<endl; f(&a); f(&b); return 0; } void f(Sample* ptr) { cout <<"n1= "<<ptr->n1<<" n2= "<<ptr->n2; if(ptr->sPtr!=0) cout <<" sPtr= "<<ptr->sPtr<<endl; else cout <<" sPtr= 0"<<endl; } |
вывод:
[/tip]
[tip]
Упражнение 4
Определите класс CRecord с двумя закрытыми переменными-членами, которые хранят имя длиной до 14 символов и целочисленный элемент. Определите функцию-член getRecord() класса CRecord, которая установит значения переменных-членов, читая ввод с клавиатуры, и функцию-член putRecord(), выводящую значения переменных-членов. Реализуйте функцию getRecord() так, чтобы вызывающая ее программа могла обнаружить, когда вводится числовой элемент с нулевым значением. Проверьте класс CRecord с помощью функции main(), которая читает и выводит объекты CRecord до тех пор, пока не будет введен числовой элемент с нулевым значением.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <iostream> using std::cout; using std::endl; using std::cin; class CRecord { public: bool getRecord() { cout <<"Enter a str... "; cin >>name; cin.clear(); cin.ignore(cin.rdbuf()->in_avail()); cout <<"Enter a n... "; cin >>n; cin.clear(); cin.ignore(cin.rdbuf()->in_avail()); if(n==0) return false; return true; } void putRecord() { cout <<"name= "<<name<<" n= "<<n<<endl; } private: char name[14]; int n; }; int main() { CRecord a; while(a.getRecord()) a.putRecord(); return 0; } |
вывод:
[/tip]
[tip]
Упражнение 5
Определите класс, представляющий стек магазинного типа (push-sown stak) целых чисел. Стек-это список элементов, который позволяет добавлять («заталкивание») или удалять («выталкивание») элементы только из одного конца и работает по принципу «последним вошел — первым вышел». Например, если стек содержит элементы [10 4 16 20], то функция pop() должна вернуть 10, после чего стек будет содержать [4 16 20]; последующий вызов push(13) должен привести к следующему содержимому стека: [12 4 16 20]. Вы не получите элемент, не находящийся в вершине стека, предварительно не получив все, что находиться после него. Ваш класс должен реализовать функцию push() и pop(), а также функцию print(), чтобы можно было проверить содержимое стека. Организуйте для начала внутреннее хранение элементов в виде массива. Напишите программу для проверки корректности всех операций вашего класса.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
#include <iostream> using std::cout; using std::endl; class Stack { public: Stack() :size(0), p(0) {} //добавить в стек элемент void push(int n) { int* temp = p; p=new int[++size]; for(int i=0;i<size-1;i++) p[i]=temp[i]; p[size-1]=n; if(temp!=0) delete[] temp; } void pop() { if(size!=0) { int* temp=p; p=new int[--size]; for(int i=0;i<size;i++) p[i]=temp[i]; delete [] temp; } } //вывести элементы стека void print() { for(int i=0;i<size;i++) cout <<p[i]<<' '; cout <<endl; cout <<"size= "<<size<<endl; } private: int* p; int size; }; int main() { Stack s; s.push(1); s.push(2); s.push(3); s.print(); s.pop(); s.print(); s.pop(); s.print(); s.pop(); s.print(); s.pop(); s.print(); return 0; } |
вывод:
[/tip]
[tip]
Упражнение 6
Что случится с вашим решением из предыдущего упражнения, если вы попытаетесь вытолкнуть функцией pop() больше элементов, чем было помещено в стек вызовом функции push()? что произойдет, если попытаться сохранить больше элементов, чем отведено места? Можете ли вы предложить устойчивый способ перехвата таких ситуаций? Иногда может понадобиться увидеть число, находящееся в вершине стека, не извлекая его оттуда; реализуйте функцию peek(), чтобы сделать это.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include <iostream> using std::cout; using std::endl; class Stack { public: Stack() :size(0), p(0) {} //добавить в стек элемент void push(int n) { int* temp = p; p=new int[++size]; for(int i=0;i<size-1;i++) p[i]=temp[i]; p[size-1]=n; if(temp!=0) delete[] temp; } void pop() { if(size!=0) { int* temp=p; p=new int[--size]; for(int i=0;i<size;i++) p[i]=temp[i]; delete [] temp; } } //вывести элементы стека void print() { for(int i=0;i<size;i++) cout <<p[i]<<' '; cout <<endl; cout <<"size= "<<size<<endl; } bool peek() { if(size!=0) return true; else return false; } private: int* p; int size; }; int main() { Stack s; s.push(1); s.push(2); s.push(3); s.print(); while(s.peek()) { s.pop(); s.print(); } return 0; } |
вывод:
[/tip]
[tip]
Упражнение 7
Повторите пример Ex7_04, но в виде консольной программы CLR, использующей ссылочные классы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
// Ex7_07.cpp: главный файл проекта. #include "stdafx.h" using namespace System; ref class CRecord { public: bool getRecord() { Console::Write("Enter a str... "); str=Console::ReadLine(); Console::Write("Enter a n... "); n=Int32::Parse(Console::ReadLine()); if(n==0)return false; else return true; } void putRecord() { Console::WriteLine("str= {0}, n= {1}",str,n); } private: int n; String^ str; }; int main(array<System::String ^> ^args) { Console::WriteLine(L"Здравствуй, мир!"); CRecord r; while(r.getRecord()) r.putRecord(); Console::ReadLine(); return 0; } |
вывод:
[/tip]