logeyg
logeyg

Reputation: 559

Converting/parsing pointer strings and doubles

Assignment:

  1. Read in info from text file (done)

  2. Retrieve only parts of text file using substr method (done)

  3. Store info into instance variables (need help)

Here is the code I am having trouble with:

string* lati;
lati = new string(data.substr(0, data.find_first_of(",")));

double* latDub;
latDub = new double(atof((char *)lati));

this->latitude = *latDub;
  1. I need to store the latitude into the instance variable latitude.

  2. The variable data is the read-in text file.

  3. this->latitude is declared as a double.

I have tested and the variable lati is the correct value, but once I try to convert it into a double the value changes to 0 for some reason. I am specifically supposed to use the atof method when converting!

Upvotes: 0

Views: 182

Answers (2)

sbi
sbi

Reputation: 224069

Why your code compiles, but gives meaningless results has already been explained by adpalumbo. There are two fundamental problems in your code leading to that error, on which I want to expand here.

One is that you use a C-style cast: (T)obj. Basically, that just tells the compiler to shut up, you know what you are doing. That is rarely ever a good idea, because when you do know what you are doing, you can usually do without such casts.

The other one is that you are using objects allocated dynamically on the heap. In C++, objects should be created on the stack, unless you have very good reasons for using dynamic objects. And dynamic objects are usually hidden inside objects on the stack. So your code should read like this:

string lati(data.substr(0, data.find_first_of(",")));
double latDub = /* somehow create double from lati */;
this->latitude = latDub;

Of course, latDub is completely unnecessary, you could just as well write to this->latitude directly.

Now, the common way to convert a string into some other type would be streaming it through a string stream. Removing the unnecessary variables you introduced, your code would then look like this:

std::istringstream iss(data.substr(0, data.find_first_of(",")));
if( !iss >> this->latitude ) throw "Dude, you need error handling here!";

Usually you want to pack that conversion from a string into a utility function which you could reuse throughout your code:

inline double convert3double(const std::string& str)
{
  std::istringstream iss(str);
  double result;
  if( !iss >> result )
    throw std::exception("Dang!");
  return result;
}

However, since the very same algorithm can be used for all types (for which operator>> is overloaded meaningfully with an input stream as the left operand), just make this a template:

template< typename T >
inline T convert3double(const std::string& str)
{
  std::istringstream iss(str);
  T result;               // presumes default constructor
  if( !iss >> result )    // presumes operator>>
    throw std::exception("Dang!");
  return result;
}

Upvotes: 0

adpalumbo
adpalumbo

Reputation: 3031

(char *)lati doesn't do what you think it does. What you're clearly trying to do there is get the char sequence associated with lati, but what you're actually doing is just squeezing a string* into a char* which is all kinds of bad.

There's a member function on std::string that will give you exactly what you want. You should review the documentation for string, and replace (char *)lati with a call to that function.

Upvotes: 2

Related Questions