Страница 1 из 1

Строка как указатель на char = путаница. Помогите разобраться

Добавлено: 24 авг 2009, 14:27
fromkharkov
Всем привет!

У меня задача: создать меню, в которое можно добавлять различные блюда. Обеспечить произвольную размерность структуры за счет использования в объекте динамических структур данных. Реализовать вывод меню в файл, чтение из файла.
Создаю класс dish с полями Название, Цена и Тип. Название блюда задаю как указатель на char. Потом создаю класс menu, у него одно из полей - объект класса dish. В конструкторе класса menu создаю массив объектов dish d[num], вводя данные с клавиатуры.
Проблема: при вводе с клавиатуры Название блюда сохраняется только последнее введенное, и у всех предыдущих d название заменяется на последнее введенное. (Цена и тип сохраняются для каждого d успешно) - это я вижу при отладке.
Подскажите плиз в чем может быть проблема. (ВСЕ ВРЕМЯ ПУТАЮСЬ С УКАЗАТЕЛЯМИ НА СТРОКИ).
Всем заранее ОЧЕНЬ благодарен

Код: Выделить всё

class dish
	{
	private:
		char *name;
		double price;
		dish_typ type;
	public:
		dish();
		dish(char * name, double price, dish_typ type);
		void set(char * name, double price, dish_typ type); 
};
class menu
{
private:
	dish d;
	fstream f;
public:
	menu();
};
dish::dish()
{
	name="";
	price=0.00;
	type=cold;
}
dish::dish(char * name, double price, dish_typ type)
{
	this->name=name;
	this->price=price;
	this->type=type;	
}

void dish::set(char * name, double price, dish_typ type)
{
	this->name=name;
	this->price=price;
	this->type=type;
}
void dish::dish_prn()
{
		setlocale(LC_ALL,"Russian");
	char* s;
		if (type==cold)
			s="cold";
		if (type==hot)
			s="hot";
		if (type==sweet)
			s="sweet";
	cout<<"------------\nНазвание блюда  Тип    Цена\n";
	cout<<name<<"   "<<s<<"   $"<<price<<endl;
}
menu::menu()
{
	setlocale(LC_ALL, "Russian");
	char name[25];
	double price;
	int type;
	short num;
	f.open("menu2.txt", ios_base: :o ut|ios_base::trunc|ios_base::binary);
//использую бинарный файл
	cout<<"How many dishes do you want in the menu?\n";
	cin>>num;
	cin.get();
	//dish * d=new dish[num];
	dish d[10];
	dish k;
	for (int i=0; i<num; i++)
	{
		cout<<"Введите название блюда, его цену и тип (горячее/холодное/десерт)\n";
		cin.getline(name, 30);
		(cin>>price).get();
		(cin>>type).get();
		d[i].set(name, price, (dish_typ)type);
		f.write((char*)&d[i], sizeof d[i]);
	}
	f.close();
	f.open("menu2.txt", ios_base::in|ios_base::binary);
	f.seekg(sizeof d[0] );
	f.read( (char*)&k, sizeof d[1] );
	k.dish_prn();
	f.close();
}
void main()
{
	menu m;
}

Re: Строка как указатель на char = путаница. Помогите разобраться

Добавлено: 24 авг 2009, 15:00
Decoder
Вместо указателья char* name используй символьный массив char name[40];
Тогда в конструкторе вместо оператора присваивания нужно будет использовать функцию копирования строки, типа strncpy().

Другой вариант: вместо символьного массива использовать класс строки, типа std::string.
Тогда оператор присваивания строки в конструкторе будет работать правильно.

Re: Строка как указатель на char = путаница. Помогите разобраться

Добавлено: 25 авг 2009, 11:54
Airhand
Используй std::string и не будет путаницы.

.

Добавлено: 26 авг 2009, 14:59
BBB
Decoder писал(а):Вместо указателья char* name используй символьный массив char name[40];
Либо оставить объяление как есть, но при присвоении наименования выделять динамическую память:

Код: Выделить всё

dish::dish(char * p_name_, double p_price, dish_typ p_type)
{
    this->name = new char [lstrlen (p_name)];
    if (this->name != null)
      lstrcpy (this->name, p_name);

    this->price=p_price;
    this->type=p_type;
};

void dish::set(char * p_name, double p_price, dish_typ p_type)
{
    delete [this->name];
    this->name = new char [lstrlen (p_name)];
    if (this->name != null)
      lstrcpy (this->name, p_name);
    this->price=p_price;
    this->type=p_type;
};
А в деструкторе не забыть почистить память:

Код: Выделить всё

void dish::~dish ()
{
    delete [this->name]; this->name = null;
};

Re: Строка как указатель на char = путаница. Помогите разобраться

Добавлено: 26 авг 2009, 15:10
Romeo
&quot писал(а):

Код: Выделить всё

void dish::~dish ()
{
   delete [this->name];
   this->name = null;
};
Более правильно так:

Код: Выделить всё

void dish::~dish ()
{
   delete [] this->name;
   this->name = NULL;
}

.

Добавлено: 26 авг 2009, 17:59
BBB
Romeo писал(а):Более правильно так:

Код: Выделить всё

............
Разумеется. Бес попутал. :( Подтолкнул под руку, скобка не там и закрылась :)

Re: Строка как указатель на char = путаница. Помогите разобраться

Добавлено: 26 авг 2009, 20:18
_SG
ужос... простейшие весчи делаются немыслимо большим и запутанным кодом. ненавижу ООП и иже с ним(((

Re: Строка как указатель на char = путаница. Помогите разобраться

Добавлено: 26 авг 2009, 22:08
WinMain
Действительно, замысел хороший, но слишком громоздкая реализация.
Для этого лучше использовать функцию strdup() в консткукторе и функцию free() в деструкторе.
В методе set() сначала вызывается free(), а потом strdup().

Re: Строка как указатель на char = путаница. Помогите разобраться

Добавлено: 28 авг 2009, 12:01
Airhand
WinMain писал(а):Действительно, замысел хороший, но слишком громоздкая реализация.
Для этого лучше использовать функцию strdup() в консткукторе и функцию free() в деструкторе.
В методе set() сначала вызывается free(), а потом strdup().
Если использовать std::string, то не надо будет ничего деть в конструкторе и деструкторе. Кроме того, когда используются динамические переменные, нужно в классе определять оператор копирования. Т.к. он произодит почленное копирование, по-умолчанию, а это не подходит, т.к. там указатель.