|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - [решено] Помогите дорешать задачу с созданием класса Book |
|
|
C/C++ - [решено] Помогите дорешать задачу с созданием класса Book
|
Новый участник Сообщения: 14 |
Профиль | Отправить PM | Цитировать
Здравствуйте помогите пожалуйста довести задачу до ума
Вот задание:Создать класс типа — книга. Поля — название, автор, год выпуска, вид литературы (худож., методич., справочн., ...). Класс имеет конструктор, деструктор. Методы: установки и возвращения значения полей, вычисления «возраста» книги, метод печати. Методы установки полей класса должны проверять корректность задаваемых параметров. Проверить работу этого класса. Вот исходник: #include "stdafx.h" #include "stdio.h" #include "conio.h" #include "math.h" #define _CRT_NONSTDC_NO_DEPRECATE class book{ char* avtor,*nazv,*vid; int year; public: book (int y, char* v, char* a,char* n){ avtor=a; year=y; vid=v; nazv=n; } { char *avtor = new char[strlen(a)+1]; //Выделяем память strcpy(avtor.a); char *vid = new char[strlen(v)+1]; strcpy(vid.v); char *nazv = new char[strlen(n)+1]; strcpy(nazv.n); } char *get_avtor(){return avtor;} char *get_vid(){return vid;} int get_year(){return year;} char *get_nazv(){return nazv;} ~book(){delete [avtor,vid,nazv] book;} //деструктор }; void main() { return ; } |
|
Отправлено: 04:11, 23-11-2008 |
Будем жить, Маэстро... Сообщения: 6694
|
Профиль | Сайт | Отправить PM | Цитировать В общем немного решил, но я сам запутался, знаний нехватает. Самому интересно.
У меня вопрос: 1. Как организовать ввод данных с клавиатуры? 2. И как правильно записать деструктор? Я запутался... По первому вопросу придумал так: В определении класса объявляю функцию В реализации этой функции считываю через дополнительные переменные, данные, и передаю в функции установки "set", каждое значение в свою функцию, но выпадает ошибка о том что приложение будет закрыто. Причём если только одно значение считывается и передаётся, то программа работает, а если четыре, то никак. Ошибки выскакивают при вводе символьных значений задачи. Подскажите как правильно ввести с клавиатуры значения и сохранить\присвоить полям объекта? |
------- Отправлено: 15:15, 23-11-2008 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать Деструктор:
Вопрос меня смущает: ежели используешь стандартную библиотеку, почему бы не использовать стандартные контейнеры? Например класс string легко превращается в char* при необходимости. С памятью они очень нежно обращаются. #include <iostream> #include <string> #include <stdexcept> using namespace std; class Book { public: Book(const string& au, const string& nb, const string& jr, unsigned int yr); Book(istream& input);// для ввода из потока void setAuthorBook(const string& au) {author = checkLength(au);} void setNameBook(const string& nb) {nameBook = checkLength(nb);} void setJanreBook(const string& jr) {janr = checkLength(jr);} void setYearBook(int yr) {year = checkYear(jr);} const string& getAuthorBook() { return author; } const string& getNameBook() { return nameBook; } const string& getJanreBook() { return janr; } unsigned int getYearBook() { return year; } void printBook(); void calculateYearBook(); private: string author; string nameBook; string janr; unsigned int year; static void checkLength(const string& str); static const unsigned& checkYear(const unsigned&); }; const Book::string& Book::checkLength(const string& str) { if (str.empty() || 255<=str.size()) { throw out_of_range( "Book::checkLength " "a string which is empty or greater 255 chars is not permitted"); } return str; } const unsigned& Book::checkYear(const unsigned& yr) { if (2008 <= yr) { throw out_of_range( "Book::checkYear " "year>=2008 is not permitted"); } return str; } Book::Book(const string& au, const string& nb, const string& jr, unsigned int yr) : author (checkLength(au)), nameBook(checkLength(nb)), janr (checkLength(jr)), year (yr) { } Book::Book(std::stream& input) : author (), nameBook(), janr (), year () { // использование копирования позволяет сохранить объект в целости и сохранности // в случае исключения. Например если при чтении любого поля возникнет ошибка, // то следующий код оставит книгу b1 без изменений: // Book b1(...); // b1.setAuthorBook(...); // ... // try // { // b1 = Book(cin); // произошла ошибка при чтении года!!! // } // catch(runtime_error& err) // { // clog << "error: " << err.what() << endl; // } clog << "reading data from stream\n"; if (((clog << "autor [enter]: "), getline(input, author)) && ((clog << "nameBook [enter]: "), getline(input, nameBook)) && ((clog << "janr [enter]: "), getline(input, janr)) && ((clog << "year [any space character]: "), (input >> jear))) { clog << "checking data\n"; checkLength(author); checkLength(nameBook); checkLength(janr); checkYear(yr); clog << "all ok\n"; } else { throw runtime_error("error reading from stream"); } } // Печать объекта------------------------------------------------------------- void Book::printBook() { cout<<" Author Book: "<<author<<endl; cout<<" Name Book: "<<nameBook<<endl; cout<<" Janre Book: "<<janr<<endl; cout<<" Year Book: "<<year<<endl; } //--------------------------------------------------------------------------- void main() { Book b("Servantes", "Don Kixot", "Romantic", 1550); b.printBook(); b.CalculateYearBook(); b.setAuthorBook("Pushkin"); b.setNameBook("Eugeny Onegin"); b.setJanreBook("Roman"); b.setYearBook(1834); b.printBook(); b.CalculateYearBook(); { // вариант 1 Book book_from_stream(cin); book_from_stream.printBook(); } { // вариант 2 b = Book(cin); b.printBook(); } } |
Последний раз редактировалось pva, 23-11-2008 в 17:11. Причина: неправильно обработал ошибки потока Отправлено: 17:04, 23-11-2008 | #3 |
Будем жить, Маэстро... Сообщения: 6694
|
Профиль | Сайт | Отправить PM | Цитировать pva, Спасибо за пояснения!!!
Цитата pva:
pva, У меня при компиляции вашего варианта, выскакивает несколько ошибок... Что я не так делаю? |
|
------- Отправлено: 17:31, 23-11-2008 | #4 |
Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать Цитата Drongo:
#include <iostream> #include <string> #include <stdexcept> using namespace std; /*-----------------23.11.2008 22:01----------------- * Класс Book - доступ к видимым полям, ввод-вывод * --------------------------------------------------*/ class Book { public: Book(const string& author1, const string& title1, const string& genre1, unsigned int year1); Book(); // для стандартных контейнеров книг Book(istream& input);// для ввода из потока // установка свойств void setAuthor(const string& author1) {_author = _checkLength(author1);} void setTitle(const string& title1) {_title = _checkLength(title1); } void setGenre(const string& genre1) {_genre = _checkLength(genre1); } void setYear(unsigned int year1) {_year = _checkYear (year1); } // чтение свойств const string& author() const throw() { return _author; } const string& title() const throw() { return _title; } const string& genre() const throw() { return _genre; } unsigned int year() const throw() { return _year; } // ввод-вывод friend ostream& operator<<(ostream&, const Book&); friend istream& operator>>(istream&, Book&); // разделитель полей для ввода-вывода static const char _io_field_delimiter; // ввод-вывод для пользователя. void human_read_unsafe(); void human_write(); private: string _author; string _title; string _genre; unsigned int _year; static const string& _checkLength(const string& str); static const unsigned& _checkYear(const unsigned&); }; /*-----------------23.11.2008 22:01----------------- * Функции ввода-вывода не роботу * --------------------------------------------------*/ void Book::human_write() { // просто в красивом виде cout << "Author:." << _author << "\n" << "Title:.." << _title << "\n" << "Genre:.." << _genre << "\n" << "Year:..." << _year << "\n\n"; } void Book::human_read_unsafe() { // читаем, проверяем на ошибки, но пишем сразу в книгу, // то есть портим сам объект, поэтому unsafe. // А вот если потом скопировать результат в хранилище, // получается вполне безопасно cout << "Type in book properties:\n"; // ws(istream&) - пропускает пробелы (enter тоже) между словами // getline(istream&, string&, int symbol='\n') - читает строчку до появления символа symbol cout << "Author:."; getline(ws(cin), _author, '\n'); _checkLength(_author); cout << "Title:.."; getline(ws(cin), _title, '\n'); _checkLength(_title ); cout << "Genre:.."; getline(ws(cin), _genre, '\n'); _checkLength(_genre ); cout << "Year:..."; cin >> _year; _checkYear (_year ); cout << "thank you!\n\n"; } /*-----------------23.11.2008 22:02----------------- * и как это всё делается. * --------------------------------------------------*/ // прикольно выглядит, если поставить = '|' //const char Book::_io_field_delimiter = '|'; const char Book::_io_field_delimiter = '\t'; Book::Book() : _author ("Unknown Author"), _title ("Unknown Author"), _genre ("Unknown Genre"), _year () { // не хочется, но надо... } Book::Book(const string& author1, const string& title1, const string& genre1, unsigned int year1) : _author (_checkLength(author1)), _title (_checkLength(title1 )), _genre (_checkLength(genre1 )), _year (_checkYear (year1 )) { // один из подходов последовательной проверки при построении класса. // неправильного класса не получится. } Book::Book(istream& in) : _author (), _title (), _genre (), _year () { // использование копирования позволяет сохранить объект в целости и сохранности // в случае исключения. Например если при чтении любого поля возникнет ошибка, // то следующий код оставит книгу b1 без изменений: // Book b1(...); // b1.setAuthorBook(...); // ... // try // { // b1 = Book(cin); // произошла ошибка при чтении года!!! // } // catch(runtime_error& err) // { // clog << "error: " << err.what() << endl; // } if (getline(ws(in), _author, _io_field_delimiter) && getline(ws(in), _title, _io_field_delimiter) && getline(ws(in), _genre, _io_field_delimiter) && (in >> _year)) { // проверяем только в случае, если считалось полностью. // если не полностью (поток кончился), то in.good(), // он же `operator istream::bool()` выдаст false _checkLength(_author); _checkLength(_title ); _checkLength(_genre ); _checkYear (_year ); } // чтобы отловить случаи неполного чтения, нужно установить флаг: // in.exceptions(ios::bad_bit|ios::fail_bit); } const string& Book::_checkLength(const string& str) { // вынесли отдельно, чтоб съэкономить код if (str.empty() || 255<=str.size()) { throw out_of_range( "Book::checkLength " "a string which is empty or greater 255 chars is not permitted"); } return str; } const unsigned& Book::_checkYear(const unsigned& year) { if (2008 <= year) { throw out_of_range( "Book::checkYear " "year>=2008 is not permitted"); } return year; } ostream& operator<<(ostream& out, const Book& book) { // вывод в таблицу, разделённую табуляторами и переводом строки // после вывод буфер не сбрасываем. return out << book._author << Book::_io_field_delimiter << book._title << Book::_io_field_delimiter << book._genre << Book::_io_field_delimiter << book._year << "\n"; } istream& operator>>(istream& in, Book& book) { // стараемся не запортить book если произойдёт исключение book = Book(in); return in; } /*-----------------23.11.2008 22:14----------------- * Демонстрация возможностей * --------------------------------------------------*/ #include <fstream> #include <list> #include <map> void main() { // прикольный способ создавать функции в теле функции (как в паскале) - если кто не знал ;-) // но, к сожалению, длинный код может запутать, пожтому при возможности лучше выносить наружу. class Job { private: string _cmd; list<Book> _books; // да, в C++ писанины много... // void (Job::*)() - так выглядит тип "указатель на функцию void Job::function()" map<string,pair<void (Job::*)(), const char*> > _handlers; bool enter_cmd() { cout << "Enter what to do (\"exit\" to quit or \"help\" for more info): "; _cmd.clear(); return (cin >> _cmd) && _cmd!="exit"; } public: Job() { _handlers["help" ] = make_pair(cmd_help, "brief about instructions"); _handlers["add" ] = make_pair(cmd_add, "add book to storage"); _handlers["clear" ] = make_pair(cmd_clear, "clear storage"); _handlers["save" ] = make_pair(cmd_save, "save storage to file \"storage.txt\""); _handlers["load" ] = make_pair(cmd_load, "load storage from file \"storage.txt\""); _handlers["erase" ] = make_pair(cmd_erase, "erase one book from storage"); _handlers["type" ] = make_pair(cmd_type, "display storage content"); } // так класс превращается в функциональный объект. // Job job1; // ... // job1(); void operator()() { // полезный приём для избежания break внутри цикла. Облегчает чтение кода // описание функции в теле класса даёт указание раскрывать её как inline while (enter_cmd()) { map<string,pair<void (Job::*)(), const char*> >::iterator iter = _handlers.find(_cmd); // оператор map<...>::operator[] добавляет элемент, если он не найден в списке, // а нам этого совсем не надо. Поэтому используем поиск по ключу if (iter!=_handlers.end()) { try { // програмное исключение exception не приводит к неработоспособности этого кода, // поэтому останавливаем их обработку здесь с чистым сердцем. // часто люди злоупотребляют блоками try..catch и оставляют работать // повреждённую программу. (this->*iter->second.first)(); } catch(exception& e) { clog << "runtime error: " << e.what() << endl; } } else { cout << "Unexpected command! Type \"help\" for list of avaible commands\n"; } } cout << "Bye!"; } // далее пошли наши команды void cmd_help() { // прикольно выглядит: // cout.fill('.'); cout.flags(ios::left); // map<> держит ключи в сортированном виде, поэтому вывод будет в // алфавитном порядке for (map<string,pair<void (Job::*)(), const char*> >::iterator first=_handlers.begin(), last=_handlers.end(); first!=last; ++first) { cout.width(10); cout << first->first << first->second.second << "\n"; } } void cmd_type() { // вот так просто теперь выглядит вывод // ostream_iterator<> использует оператор << для вывода в поток copy(_books.begin(), _books.end(), ostream_iterator<Book,char>(cout)); } void cmd_add() { // небезопасно читаем новую книгу // и безопасно добавляем в контейнер Book new_book; new_book.human_read_unsafe(); _books.push_back(new_book); } void cmd_clear() { _books.clear(); } void cmd_save() { // вот так просто теперь выглядит сохранение ofstream out("storage.txt"); copy(_books.begin(), _books.end(), ostream_iterator<Book,char>(out)); } void cmd_load() { // загружаем в отдельный список - безопасно при исключениях list<Book> new_list; ifstream in("storage.txt"); copy(istream_iterator<Book,char>(in), istream_iterator<Book,char>(), back_inserter(new_list)); // меняем местами содержимое списков. При чистке стека старый список удалится. new_list.swap(_books); } void cmd_erase() { // пример использования функционального класса // title_predicate(book) возвращает true если введённое название книги совпадает // иначе false struct title_predicate { string _title1; title_predicate() { cout << "Enter title to erase: "; cin >> _title1; } bool operator()(const Book& book) { return book.title()==_title1; } }; // remove_if перемещает в конец списка все элементы, которые удовлетворяют условию. // если до выполнения erase произойдёт исключение, книги не потеряются. Но правда // изменится порядок. _books.remove_if(/*это вызов конструктора*/ title_predicate()); } }; // вот теперь настал тот момент, когда непонятно, что кончилось и что началось, // если помещать описание класса внутрь функции. Job()(); } |
||
Последний раз редактировалось pva, 23-11-2008 в 22:44. Причина: у списка есть оптимизированный remove_if Отправлено: 22:30, 23-11-2008 | #5 |
Будем жить, Маэстро... Сообщения: 6694
|
Профиль | Сайт | Отправить PM | Цитировать Цитата pva:
|
|
------- Отправлено: 11:38, 24-11-2008 | #6 |
Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать Вот это обкатал на 6-м билдере. К сожалению C++ Builder - это не компилятор C++
#pragma hdrstop //------------------------------ #include <iostream> #include <string> #include <stdexcept> using namespace std; /*-----------------23.11.2008 22:01----------------- * Класс Book - доступ к видимым полям, ввод-вывод * --------------------------------------------------*/ class Book { public: Book(const string& author1, const string& title1, const string& genre1, unsigned int year1); Book(); // для стандартных контейнеров книг // установка свойств void setAuthor(const string& author1) {_author = _checkLength(author1);} void setTitle(const string& title1) {_title = _checkLength(title1); } void setGenre(const string& genre1) {_genre = _checkLength(genre1); } void setYear(unsigned int year1) {_year = _checkYear (year1); } // чтение свойств const string& author() const throw() { return _author; } const string& title() const throw() { return _title; } const string& genre() const throw() { return _genre; } unsigned int year() const throw() { return _year; } // ввод-вывод friend ostream& operator<<(ostream&, const Book&); friend istream& operator>>(istream&, Book&); // разделитель полей для ввода-вывода static const char _io_field_delimiter; // ввод-вывод для пользователя. void human_read_unsafe(); void human_write(); private: string _author; string _title; string _genre; unsigned int _year; static const string& _checkLength(const string& str); static const unsigned& _checkYear(const unsigned&); }; /*-----------------23.11.2008 22:01----------------- * Функции ввода-вывода не роботу * --------------------------------------------------*/ void Book::human_write() { // просто в красивом виде cout << "Author:." << _author << "\n" << "Title:.." << _title << "\n" << "Genre:.." << _genre << "\n" << "Year:..." << _year << "\n\n"; } void Book::human_read_unsafe() { // читаем, проверяем на ошибки, но пишем сразу в книгу, // то есть портим сам объект, поэтому unsafe. // А вот если потом скопировать результат в хранилище, // получается вполне безопасно cout << "Type in book properties:\n"; // ws(istream&) - пропускает пробелы (enter тоже) между словами // getline(istream&, string&, int symbol='\n') - читает строчку до появления символа symbol cout << "Author:."; getline(ws(cin), _author, '\n'); _checkLength(_author); cout << "Title:.."; getline(ws(cin), _title, '\n'); _checkLength(_title ); cout << "Genre:.."; getline(ws(cin), _genre, '\n'); _checkLength(_genre ); cout << "Year:..."; cin >> _year; _checkYear (_year ); cout << "thank you!\n\n"; } /*-----------------23.11.2008 22:02----------------- * и как это всё делается. * --------------------------------------------------*/ // прикольно выглядит, если поставить = '|' //const char Book::_io_field_delimiter = '|'; const char Book::_io_field_delimiter = '\t'; Book::Book() : _author ("Unknown Author"), _title ("Unknown Title"), _genre ("Unknown Genre"), _year () { // не хочется, но надо... } Book::Book(const string& author1, const string& title1, const string& genre1, unsigned int year1) : _author (_checkLength(author1)), _title (_checkLength(title1 )), _genre (_checkLength(genre1 )), _year (_checkYear (year1 )) { // один из подходов последовательной проверки при построении класса. // неправильного класса не получится. } const string& Book::_checkLength(const string& str) { // вынесли отдельно, чтоб съэкономить код if (str.empty() || 255<=str.size()) { throw out_of_range( "Book::checkLength " "a string which is empty or greater 255 chars is not permitted"); } return str; } const unsigned& Book::_checkYear(const unsigned& year) { if (2008 <= year) { throw out_of_range( "Book::checkYear " "year>=2008 is not permitted"); } return year; } ostream& operator<<(ostream& out, const Book& book) { // вывод в таблицу, разделённую табуляторами и переводом строки // после вывод буфер не сбрасываем. return out << book._author << Book::_io_field_delimiter << book._title << Book::_io_field_delimiter << book._genre << Book::_io_field_delimiter << book._year << "\n"; } istream& operator>>(istream& in, Book& book) { // немного подумав обрал коснтруктор из потока. // потому что при чтении итератором istream_iterator<Book> будет всё равно // использоваться копия Book, которая находятся в самом итераторе. // использование копирования позволяет сохранить объект в целости и сохранности // в случае исключения. Например если при чтении любого поля возникнет ошибка, // то следующий код оставит книгу b1 без изменений: // Book b1(...); // b1.setAuthorBook(...); // ... // try // { // b1 = Book(cin); // произошла ошибка при чтении года!!! // } // catch(runtime_error& err) // { // clog << "error: " << err.what() << endl; // } if (getline(ws(in), book._author, Book::_io_field_delimiter) && getline(ws(in), book._title, Book::_io_field_delimiter) && getline(ws(in), book._genre, Book::_io_field_delimiter) && (in >> book._year)) { // проверяем только в случае, если считалось полностью. // если не полностью (поток кончился), то in.good(), // он же `operator istream::bool()` выдаст false Book::_checkLength(book._author); Book::_checkLength(book._title ); Book::_checkLength(book._genre ); Book::_checkYear (book._year ); } // чтобы отловить случаи неполного чтения, нужно установить флаг: // in.exceptions(ios::badbit|ios::failbit); // но это мешает чтению из потока до его конца (в конце выйдет исключение) return in; } /*-----------------23.11.2008 22:14----------------- * Демонстрация возможностей * --------------------------------------------------*/ #include <fstream> #include <iterator> #include <list> #include <map> // пример использования функционального класса // title_predicate(book) возвращает true если введённое название книги совпадает // иначе false // используется в Job::cmd_erase(), но сюда вынесено, потому что борландовский // компилятор умеет подставлять в шаблоны только классы, видимые снаружи // (а не в текущем блоке). Дебильная урезка по-моему. struct title_predicate { string _title1; title_predicate() { cout << "Enter title to erase: "; getline(ws(cin), _title1); } bool operator()(const Book& book) { return book.title()==_title1; } }; void main() { // прикольный способ создавать функции в теле функции (как в паскале) - если кто не знал ;-) // но, к сожалению, длинный код может запутать, пожтому при возможности лучше выносить наружу. class Job { private: string _cmd; list<Book> _books; // да, в C++ писанины много... // void (Job::*)() - так выглядит тип "указатель на функцию void Job::function()" // борланд такую конструкцию не воспринимает :( ему обязательно надо typedef // и вообще у него из-за ввода __closure началась путаница с указателями на методы // я привёл к стандартному сишному вызову cdecl typedef void (cdecl Job::*handler_type)(); // без этого тоже не хотел собирать почему-то. // а всё глюкавый сборщик шаблонов виноват... typedef map<string,pair<handler_type, const char*> > handler_map_type; handler_map_type _handlers; bool enter_cmd() { cout << "Enter what to do (\"exit\" to quit or \"help\" for more info): "; _cmd.clear(); return (cin >> _cmd) && _cmd!="exit"; } public: Job() { // борландовский компилятор не по правилам делает порядок подстановки типов аргументов в шаблон // поэтому приходится указывать тип аргумента явно. // Указатель на функцию тоже почему-то стал браться с амперсандом, хотя по правилам - без... _handlers["help" ] = make_pair(static_cast<handler_type>(&Job::cmd_help), "brief about instructions"); _handlers["add" ] = make_pair(static_cast<handler_type>(&Job::cmd_add), "add book to storage"); _handlers["clear" ] = make_pair(static_cast<handler_type>(&Job::cmd_clear), "clear storage"); _handlers["save" ] = make_pair(static_cast<handler_type>(&Job::cmd_save), "save storage to file \"storage.txt\""); _handlers["load" ] = make_pair(static_cast<handler_type>(&Job::cmd_load), "load storage from file \"storage.txt\""); _handlers["erase" ] = make_pair(static_cast<handler_type>(&Job::cmd_erase), "erase one book from storage"); _handlers["list" ] = make_pair(static_cast<handler_type>(&Job::cmd_list), "display storage content"); } // так класс превращается в функциональный объект. // Job job1; // ... // job1(); void cdecl operator()() { // полезный приём для избежания break внутри цикла. Облегчает чтение кода // описание функции в теле класса даёт указание раскрывать её как inline while (enter_cmd()) { handler_map_type::iterator iter = _handlers.find(_cmd); // оператор map<...>::operator[] добавляет элемент, если он не найден в списке, // а нам этого совсем не надо. Поэтому используем поиск по ключу if (iter!=_handlers.end()) { try { // програмное исключение exception не приводит к неработоспособности этого кода, // поэтому останавливаем их обработку здесь с чистым сердцем. // часто люди злоупотребляют блоками try..catch и оставляют работать // повреждённую программу. (this->*iter->second.first)(); } catch(exception& e) { clog << "runtime error: " << e.what() << endl; } } else { cout << "Unexpected command! Type \"help\" for list of avaible commands\n"; } } cout << "Bye!"; } // далее пошли наши команды void cdecl cmd_help() { // прикольно выглядит: // cout.fill('.'); cout.flags(ios::left); // map<> держит ключи в сортированном виде, поэтому вывод будет в // алфавитном порядке for (handler_map_type::iterator first=_handlers.begin(), last=_handlers.end(); first!=last; ++first) { cout.width(10); cout << first->first << first->second.second << "\n"; } } void cdecl cmd_list() { // вот так просто теперь выглядит вывод // ostream_iterator<> использует оператор << для вывода в поток copy(_books.begin(), _books.end(), ostream_iterator<Book,char>(cout)); } void cdecl cmd_add() { // небезопасно читаем новую книгу // и безопасно добавляем в контейнер Book new_book; new_book.human_read_unsafe(); _books.push_back(new_book); } void cdecl cmd_clear() { _books.clear(); } void cmd_save() { // вот так просто теперь выглядит сохранение ofstream out("storage.txt"); copy(_books.begin(), _books.end(), ostream_iterator<Book,char>(out)); } void cdecl cmd_load() { // загружаем в отдельный список - безопасно при исключениях list<Book> new_list; ifstream in("storage.txt"); copy(istream_iterator<Book,char>(in), istream_iterator<Book,char>(), back_inserter(new_list)); if (!in.eof()) { in.clear(ios::goodbit); string error_word; getline(in, error_word); clog << "Job::cmd_load parser error before: " << error_word << endl; throw runtime_error("Job::cmd_load parser error"); } // меняем местами содержимое списков. При чистке стека старый список удалится. new_list.swap(_books); } void cdecl cmd_erase() { // remove_if перемещает в конец списка все элементы, которые удовлетворяют условию. // если до выполнения erase произойдёт исключение, книги не потеряются. Но правда // изменится порядок. _books.remove_if<title_predicate>(/*это вызов конструктора*/ title_predicate()); } }; // вот теперь настал тот момент, когда непонятно, что кончилось и что началось, // если помещать описание класса внутрь функции. Job()(); } //------------------------------ |
Отправлено: 12:50, 24-11-2008 | #7 |
Будем жить, Маэстро... Сообщения: 6694
|
Профиль | Сайт | Отправить PM | Цитировать pva, Спасибо большое!!! Хотя задача и вопрос не мой, но мне он интересен тоже! Всё компилируется и работает без нареканий.
P.S. Вот только автор темы куда-то пропал... |
------- Отправлено: 14:21, 24-11-2008 | #8 |
Новый участник Сообщения: 14
|
Профиль | Отправить PM | Цитировать Извиняюсь, что не мог ответить на ПК попал какой то странный червь(dr web его не обнаружил) пришлось сносить систему.
Огромное спасибо! В принципе мне бы хватило и маленького дописания кода без пабликов и приватов, очень благодаре, так как они как раз у меня в ледующих лабораторках будут, а теперь можно будет посмотреть принцип их работы. |
Отправлено: 00:33, 25-11-2008 | #9 |
Новый участник Сообщения: 14
|
Профиль | Отправить PM | Цитировать Еще вопрос у меня не кампилируется какой проект нужно создавать? просто нас учили создавать проект С++ win32 console aplication а в нем файл по умолчанию stdafx.h и он ругатся из - за его отсутствия
http://forum.oszone.net/attachment.p...1&d=1227631655 |
Отправлено: 19:40, 25-11-2008 | #10 |
|
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
C/C++ - Помогите решить задачу | Urann | Программирование и базы данных | 11 | 14-05-2013 11:44 | |
C/C++ - [решено] Помогите решить задачу по С++ | Spl1t | Программирование и базы данных | 301 | 21-12-2011 23:20 | |
C/C++ - Помогите решить задачу | zdughi | Программирование и базы данных | 1 | 01-05-2009 06:03 | |
помогите решить задачу | snikers | Программирование и базы данных | 2 | 27-08-2004 01:57 | |
помогите решить задачу | Guest | Программирование и базы данных | 2 | 21-05-2004 11:23 |
|