Sign in to follow this  
Windex

Passing file contents to a constructor

Recommended Posts

Assume I have a CSV file that loads each line into a vector. CSV Contents 1,"Super Iron",METAL,MATERIAL,29,49,192,11
Resource(int id, string name, RES_TYPE rtype, ITEM_TYPE itype, int hardness, int quality, int durability, int weight)
	{
		setID(id);
		setName(name);
		setResType(rtype);
		setItemType(itype);
		setHardness(hardness);
		setQuality(quality);
		setDurability(durability);
		setItemWeight(weight);
	}
So to create the object:
Resource* b = new Resource(1,"Super Iron",METAL,ARMOR,29,49,192,11);
Is it possible to load the first line of the csv, into the constructor to construct the object based on my csv file? Right now its not set up to work because the vector is going to store a string, and the constructor obviously takes 8 arguments. Does anyone have any insight on how I might be able to take each value of a csv record and somehow construct the resource object out of that data?

Share this post


Link to post
Share on other sites
You'll have to parse the file yourself, and decide what to do with the data:


using namespace std;

// Array of Resources (automatic memory management thanks to boost::shared_ptr)
vector<boost::shared_ptr<Resource> > resources;

// castString attempts extract a "T" from a string
template<typename T>
bool castString( const string& str, T& out ) {
stringstream ss( str );
if ( ss >> out )
return true;
return false;
}

// Input file
ifstream file( ... );
if ( !file )
/* Error handling */;

// For each line:
while ( file ) {
// Read a line:
string line;
getline( file, line );

// Prepare the line for tokenizing:
stringstream ss( line );

// params in an array of strings
vector<string> params;
while ( ss ) {
string param;
getline( ss, param, ',' ); // Tokenize by commas
params.push_back( param );
}

// Now decide what to do with the data, with its first
// parameter being the type of resource
int type;
if ( castString( params[0], type ) ) {
switch ( type ) {
case 1:
// Make sure we have enough params
int id, d, e, f, g;
if ( params.size() < 9 )
/* Error handling */;
if ( !castString( params[1], id ) ) /* Error handling */;
if ( !castString( params[5], d ) ) /* Error handling */;
if ( !castString( params[6], e ) ) /* Error handling */;
if ( !castString( params[7], f ) ) /* Error handling */;

Resource* r = new Resource( a, b, c, d, e, f, g );
resources.push_back( boost::shared_ptr( r ) );
}
} else
/* Unable to determine type; error handling */;
}



A note on enums: They are internally represented as integers, while having the look of being "strings"; you'll need to provide a map<string,enum> conversion for each enum:


enum ItemType {
WEAPON,
ARMOR,
CONSUMABLE
};

map<string, ItemType> ItemTypeMap;
ItemTypeMap["WEAPON"] = ItemType::WEAPON;
ItemTypeMap["ARMOR"] = ItemType::WEAPON;
ItemTypeMap["CONSUMABLE"] = ItemType::CONSUMABLE;


Share this post


Link to post
Share on other sites
Thanks for the reply, I don't have time to test, time for work :/. I understand most of whats going on here, the only thing I don't understand is the template. Could you explain in minor detail what the template is doing?


template<typename T>
bool castString( const string& str, T& out ) {
stringstream ss( str );
if ( ss >> out )
return true;
return false;
}

The rest is pretty self explanatory.

Share this post


Link to post
Share on other sites
It's basically a home-made boost::lexical cast; it converts a string to any type:


float myFloat = 0.f;
int myInt = 0;
double myDouble = 0.;
Foobar myFoobar; // Foobar has a operator>> overload

string someString = "1.123";

castString( someString, myFloat ); // myFloat = 1.123f
castString( someString, myInt ); // myInt = 1
castString( someString, myDouble ); // myDouble = 1.123
castString( someString, myFoobar ); // myFoobar = ...

string badString = "hello!";

castString( someString, myInt ); // myInt is unchanged, function returns false to indicate error



Also, I edited my original post to include comments

Share this post


Link to post
Share on other sites
Quote:
Original post by _fastcall
It's basically a home-made boost::lexical cast; it converts a string to any type:


If the OP is looking to cast a string into any type, he might try this:
template <typename T> std::string toString(const T& x)
{
std::ostringstream os;
if (!(os << x))
throw ; // yeah.. i forgot what you should throw here..
return os.str( );
}


// and for a string to another data type.
template <typename T> T stringTo(const std::string& str)
{
T x;
std::istringstream is(str);
if (!(is >> x))
throw ; // same as above
return x;
}

// the two templated functions above can be used like so..
std::string str = toString(1041);
int n = stringTo<int>(str); // you must be explicit with the type to convert to with this function.





I didnt read the whole question so yeah, im just putting this out there, tis quite useful.

[Edited by - CodeCriminal on February 13, 2010 10:05:51 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this