Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Vectoriin tallentaminen

Lahha [09.07.2010 18:11:22]

#

Ongelmana siis kun tallennettava objekti sisältää dynaamisesti varatun stringin ja kun alkuperäinen tuhotaan katoa vectoriin tallennettu stringi myös.

Stringi ei ilmeisesti kopioidu oikein vaan vectorissa oleva objekti osoittaa edelleen vanhaan stringiin.

enum TYPES{UNDEF = 0, INT = 1, FLOAT, STRING};

class VarContainer
{
	union {
		int   _int;
		float _float;
		std::string * _string;
	}data;

	TYPES type;

	std::string name;

public:
	VarContainer();
	VarContainer(const char *);
	~VarContainer();

	void release();

	void setName(const std::string &);
	void setName(const char *);

	bool assign(const VarContainer &);
	bool assign(int);
	bool assign(float);
	bool assign(const std::string &);
	bool assign(const char *);

	const std::string * getName() const;
	int getType() const;

	int getInt() const;
	float getFloat() const;
	const std::string * getString() const;

	bool convert(int);
	void print() const;

	VarContainer & operator = (const VarContainer &);
};
VarContainer::VarContainer()
{
	type = UNDEF;
	data._string = NULL;
}

VarContainer::VarContainer(const char *_name)
{
	type = UNDEF;
	data._string = NULL;

	setName(_name);
}

VarContainer::~VarContainer()
{
	release();
}

void VarContainer::release()
{
	if(type == STRING)
	{
		if(data._string)
			delete data._string;
	}

	data._string = NULL;
	type = UNDEF;
}

void VarContainer::setName(const std::string &v)
{
	name = v;
}

void VarContainer::setName(const char *v)
{
	if(v)
		name = v;
}

bool VarContainer::assign(const VarContainer &v)
{
	if(this == &v)
		return true;

	switch(v.getType())
	{
	case INT:
		return assign(v.getInt());
	case FLOAT:
		return assign(v.getFloat());
	case STRING:
		return assign(*v.getString());
	default:
		break;
	}

	return false;
}

bool VarContainer::assign(int v)
{
	release();

	type = INT;
	data._int = v;

	return true;
}

bool VarContainer::assign(float v)
{
	release();

	type = FLOAT;
	data._float = v;

	return true;
}

bool VarContainer::assign(const std::string &v)
{
	release();

	data._string = new std::string;

	if(!data._string)
		return false;

	type = STRING;
	data._string->assign(v);

	return true;
}

bool VarContainer::assign(const char *v)
{
	release();

	data._string = new std::string;

	if(!data._string)
		return false;

	type = STRING;
	data._string->assign(v);

	return true;
}

const std::string * VarContainer::getName() const
{
	return &name;
}

int VarContainer::getType() const
{
	if(type == STRING)
		if(!data._string)
			return UNDEF;

	return type;
}

int VarContainer::getInt() const
{
	if(type == INT)
		return data._int;

	if(type == FLOAT)
		return (int)data._float;

	return 0;
}

float VarContainer::getFloat() const
{
	if(type == FLOAT)
		return data._float;

	if(type == INT)
		return (float)data._int;

	return 0;
}

const std::string * VarContainer::getString() const
{
	if(type != STRING)
		return NULL;

	return data._string;
}

bool VarContainer::convert(int _type)
{
	if(type == _type)
		return true;

	if(type == UNDEF )
	{
		switch(_type)
		{
		case INT:
			return assign(0);
		case FLOAT:
			return assign(0.0f);
		case STRING:
			return assign("");
		default:
			break;
		}

		return false;
	}
	else if(_type == INT)
	{
		if(type == FLOAT)
			return assign((int)data._float);
		else if(type == STRING)
		{
			if(data._string)
				return assign(atoi(data._string->c_str()));
			else
				return false;
		}
	}
	else if(_type == FLOAT)
	{
		if(type == INT)
			return assign((float)data._int);
		else if(type == STRING)
		{
			if(data._string)
			{
				int x = data._string->find(",");

				if(x != std::string::npos)
					data._string->at(x) = '.';

				return assign((float)atof(data._string->c_str()));
			}
			else
				return false;
		}

	}
	else if(_type == STRING)
	{
		char * tmp = new char[30];
		bool ret = false;

		if(!tmp)
			return false;

		if(type == INT)
		{
			sprintf_s(tmp, 29, "%d", data._int);
			ret = assign(tmp);
		}
		else if(type == FLOAT)
		{
			sprintf_s(tmp, 29, "%.3f", data._float);
			ret = assign(tmp);
		}

		delete [] tmp;
		tmp = NULL;

		return ret;
	}

	return false;
}

void VarContainer::print() const
{
	std::cout << name << "; (" << type << ") ";

	switch(type)
	{
	case INT:
		std::cout << data._int ;
		break;
	case FLOAT:
		std::cout << data._float ;
		break;
	case STRING:
		std::cout << *data._string ;
	}

	std::cout << std::endl;
}

VarContainer & VarContainer::operator = (const VarContainer & v)
{
	assign(v);
	setName(*v.getName());
	return *this;
}

Megant [09.07.2010 18:23:07]

#

Kun kopioit olion vektoriin, kontruktoidaan uusi olio kutsumalla tämän konstruktoria VarContainer::VarContainer(const VarContainer&). Kun kerta et ole määritellyt sitä, kääntäjä tarjoaa sinulle oman toteutuksensa, joka vaan raa'asti kopioi datat ja pointteri pysyy tietenkin samana. Eli sinun pitäisi toteuttaa kopiokonstruktori samalla tavalla kuin olet toteuttanut operator=:n.

Lahha [09.07.2010 18:27:22]

#

Kiitti, nyt toimii.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta