IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным. В описании темы указываем язык!!!

> STL, Итераторы C++
ammaximus
сообщение 11.02.2009 10:08
Сообщение #1


Ночной волк
**

Группа: Пользователи
Сообщений: 103
Пол: Мужской

Репутация: -  1  +


Работа с библиотекой STL. Требуется создать вектор указателей на объекты типа алкогольные напитки. Программа должна уметь добавлять новый элемент, удалять элемент, сортировать по убыванию названия, находить первое включение указанного напитка.
1. В чем ошибки? Нерабочие участки программы закомментированы.
2. Как реализовать по убыванию с помощью итератора? Что за итератор возвращает обратное значение
3. Как присвоить значение итератору? У меня что то = не работает.
 #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#define n 5
using namespace std;
///////////////////////////////////////
class liquido{
protected:
	string name;
	double ro;
public:
	liquido(){
		name="acqua";
		ro=0;
	}

	liquido(string str){
		name=str;
		ro=0;
	}

	liquido(string str, double p){
		name=str;
		ro=p;
	}


	void print(){
		cout << "Liquido " << name << endl;;
		cout << "R\'o " << ro << endl;;
	}

	void set_ro(double p){
		ro=p;
	}

	void set_name(string str){
		name=str;
	}



};
/////////////////////////////////////////////
class alcohol:public liquido{
	float carico;
public:
	alcohol(){
		name="acqua";
		ro=0;
		carico=0;
	}

	alcohol(string str){
		name=str;
		ro=0;
	}

	alcohol(string str, double p){
		name=str;
		ro=p;
		carico=0;
	}

	alcohol(string str, double p, float c){
		name=str;
		ro=p;
		carico=c;
	}
	void set_c(float c){
		carico=c;
	}
	
	void print(){
		cout << "\nLiquido " << name << endl;;
		cout << "R\'o " << ro << ";  Carico " << carico << endl;
	}

	friend bool operator==(const alcohol& a1, const alcohol& a2){
		return (a1.name==a2.name);
	}

	friend bool operator<(const alcohol& a1, const alcohol& a2){
		return (a1.name<a2.name);
	}




};
//////////////////////////////////////////////
////Function objects//////////////////////////
//////////////////////////////////////////////
class compareAlcohol{
public:
	bool operator()(const alcohol* a1, alcohol* a2){
		return *a1<*a2;
	}
};
//////////////////////////////////////////////
//class printAlcohol{
//public:
//	void operator() (const alcohol* a){
//		*a->print();
//	}
//};
/////////////////////////////////////////////
/////////MAIN////////////////////////////////
/////////////////////////////////////////////


int main(){
	alcohol Martini("Martini Bianco 1863", 986.5, 18.5f);
	alcohol Martini2("Martini Bianco 1863", 986.5, 18.5f);
	Martini.print();
	Martini.set_c(19.5f);
	Martini.set_ro(987.);
	Martini.print();
////////////////////////////////
	alcohol* temp;
	string gen;
	vector<alcohol*> MyVector;
	vector<alcohol*>::iterator MyIterator;
	for (int i=0; i<n; i++){
		gen= "Alcohol"+i;
		cout << gen << endl;
		temp = new alcohol(gen, i+10, i);
		MyVector.push_back(temp);
	}
	cout << MyVector.size()<<endl;
//	for_each(MyVector.begin(), MyVector.end(), printAlcohol);//output
//	sort(MyVector.begin(), MyVector.end(), compareAlcohol);

/////////////////
	///////////////
//////////ADD ELEMENT///////////
////////////////////////////////

	temp = new alcohol("NEW ALCOHOL", 893.7, 39.4f);
//	MyIterator=3;
//	MyVector.insert(temp,MyIterator);
//	for_each(MyVector.begin(), MyVector.end(), printAlcohol);//output

////////////////////////////////
////////DELETE ELEMENT//////////
////////////////////////////////
	cout << "Which element delete?";
	cin >> i;
	delete MyVector[i];
//	MyIterator = i;
//	MyVector.erase(MyIterator,MyIterator);
//	for_each(MyVector.begin(), MyVector.end(), printAlcohol);//output
////FIND ELEMENT/////
	string sname;
	cout << "Put Name for search";
	cin >> sname;
//	MyIterator=find(MyVector.begin(), MyVector.end(), sname);
//	cout << MyIterator;
	
	
	
////////////CLEAR///////////////////////////////	
	while (!MyVector.empty()){
		delete MyVector.back();
		MyVector.pop_back();
	}
return 0;
}



--------------------
Не думай о белой обезьяне.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов(1 - 5)
volvo
сообщение 11.02.2009 23:41
Сообщение #2


Гость






Цитата
1. В чем ошибки? Нерабочие участки программы закомментированы.
А у тебя ошибки начинаются еще ДО того, как что-то закомментировано... Ну, например, ты в конструкторе класса alcohol зачем-то присваиваешь значения унаследованным полям сам, хотя для этого есть конструктор предка... Кстати, конструктор предка ты должен вызывать в конструкторе потомка, ты этого не делаешь... + к этому, есть такое понятие, как значения по умолчанию, то есть, вместо трех перегрузок конструктора liquido, достаточно:

class liquido {
	liquido(string s = "acqua", double d = 0.0) {
		name = s; ro = d;
	}

// ...

class alcohol: public liquido {
	alcohol(string s = "acqua", double d = 0.0, float f = 0.0): liquido(s, d) {
	    carico = f;
	}
// ...
, это перекрывает все возможные комбинации, которые ты реализовывал вручную.

2) Инициализация:
Цитата
	for (int i=0; i<n; i++){
		gen= "Alcohol"+i;
		cout << gen << endl;
		temp = new alcohol(gen, i+10, i);
		MyVector.push_back(temp);
	}
делает совсем не то, что ты подразумевал. В частности, "Alcohol" + 1 = "lcohol", а +2 = "cohol", ты сложением просто задаешь смещение от начала строки... Ты же хотел добавлять цифру в конец? Ну, так добавляй:
	char gen[20] = {0};
	for (int i=0; i<n; i++){
		sprintf(gen, "Alcohol%d", i);
		cout << gen << endl;
		temp = new alcohol(gen, i+10, i);
		MyVector.push_back(temp);
	}

3) Попытка печати вектора: ошибка, потому что printAlcohol должен быть не классом, а функцией:
void print_alcohol(alcohol *a) {
    a->print();
}
// ...
for_each(MyVector.begin(), MyVector.end(), print_alcohol);
, а вот дальше, при попытке отсортировать вектор, ты делаешь обратную ошибку... У тебя есть класс, в котором который ввел предикат сравнения, но передавать-то тебе в std::sort надо не класс, а сам предикат:
sort(MyVector.begin(), MyVector.end(), compareAlcohol()); // вот так - правильно 


4) Добавление элемента в вектор:
	temp = new alcohol("NEW ALCOHOL", 893.7, 39.4f);
	MyIterator=MyVector.begin() + 3; // Все очень просто, не число, а смещение от начала
	MyVector.insert(MyIterator, temp); // сначала - итератор, потом - элемент


5) Удаление элемента... Я бы сделал это вот так:
	cout << "Which element delete?";
	cin >> i;
	delete (temp = MyVector[i]);
	MyVector.erase(MyVector.begin() + i);


По-моему ничего не забыл...
 К началу страницы 
+ Ответить 
ammaximus
сообщение 18.02.2009 18:39
Сообщение #3


Ночной волк
**

Группа: Пользователи
Сообщений: 103
Пол: Мужской

Репутация: -  1  +


Спасибо огрмное Volvo. Все исправил.
Только не выходит Find

MyIterator = find(MyVector.begin(), MyVector.end(), Martini);


Этот код должен найти в векторе элемент равный Мартини, только не работает. И еще, можно использовать find, чтобы найти по параметру объекта, не используя лишние объекты. т.е.


MyIterator = find(MyVector.begin(), MyVector.end(), Martini.carico);

или просто

MyIterator = find(MyVector.begin(), MyVector.end(), "Alcohol2");


Два учебника уже прочитал, нигде нет подробного описания этой функции.


--------------------
Не думай о белой обезьяне.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
volvo
сообщение 18.02.2009 19:54
Сообщение #4


Гость






Цитата
И еще, можно использовать find, чтобы найти по параметру объекта, не используя лишние объекты
Используй find_if:

// пишешь свой функтор
struct finder : std::binary_function<alcohol*, string, bool>
{
    bool operator()(alcohol* const& in, string id) const
    {
        return (id == in->get_name());
    }
};

// и запускаешь поиск:
	MyIterator = find_if(MyVector.begin(), MyVector.end(), bind2nd(finder(), "Alcohol3"));
	(*MyIterator)->print();
, но для того, чтобы это работало, придется в классе liquido сделать геттер get_name(), иначе к полю name нет доступа, оно защищенное, а не общее...

Цитата
Два учебника уже прочитал, нигде нет подробного описания этой функции.
Какие учебники ты читал?
 К началу страницы 
+ Ответить 
ammaximus
сообщение 19.02.2009 17:48
Сообщение #5


Ночной волк
**

Группа: Пользователи
Сообщений: 103
Пол: Мужской

Репутация: -  1  +


Т.Павловская, методичку свою, еще какие-то документы без названия..
Можешь что-нибудь посоветовать по STL? У меня очень дорогой hsdpa интернет, я не могу позволить себе скачивать все подряд, а потом разбираться.

Кстати я не понял вот это

finder : std::binary_function<alcohol*, string, bool>
и это
bind2nd



--------------------
Не думай о белой обезьяне.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
volvo
сообщение 19.02.2009 18:35
Сообщение #6


Гость






Цитата
finder : std::binary_function<alcohol*, string, bool>
Хм... Ну, смотри... Создаем свой функтор - наследник от класса std::binary_function, то есть, функтор (так же как делает это binary_function) будет принимать 2 аргумента: первый - типа alcohol*, второй - типа string... А возвращать функтор будет значение типа bool (именно в таком порядке конкретизируется binary_function<>: тип первого параметра, тип второго параметра, и тип результата, обрати внимание).

А теперь - суть этого метода: при проходе по вектору КАЖДЫЙ его элемент передается в созданный функтор, и там сравнивается с заданной строкой... Причем, поскольку использована bind2nd, то доп. аргумент(строка в нашем случае) передается вторым параметром, а итератор - первым. Если надо, чтобы сначала передавался доп. аргумент, а потом - итератор, то используется bind1st... Ну, к примеру, можно было бы переписать функтор с другим порядком аргументов:
struct id_finder : std::binary_function<string, alcohol*, bool>
{
    bool operator()(string id, alcohol* const& in) const
    {
        return (id == in->get_name());
    }
};

, и вызвать
MyIterator = find_if(MyVector.begin(), MyVector.end(), bind1st(finder(), "Alcohol3"));
, тоже было бы корректно...

Цитата
Можешь что-нибудь посоветовать по STL?
Я пользуюсь книгой Николай Джосьютис, С++ Стандартная библиотека для профессионалов, ISBN: 5-94723-635-4 (английский вариант: "The C++ Standard Library: A Tutorial and Reference" Nicolai M. Josuttis, ISBN: 0-201-37926-0) и Scott Meyers: Effective STL
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

- Текстовая версия 29.07.2025 16:49
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"