How to Use Std: :Stod Properly

I am working on writing a simple linear line calculator. For example, a user can enter two equations (strings) such as y=5x+3 and y=-3x+6. The most basic feature of this calculator is that it will return the intersection point of these two lines.

The obstacle I can't seem to figure out is how to parse the string into two pieces of data: the slope, and the y-intercept. This is a simple calculator, so the format of both lines will be y=mx+b, however, both the slope and/or y-intercept may be non-integer numbers (i.e. floats).

I came across a function in the string library called stod, which converts a number in a string to a numerical value (am I understanding this correctly?).

My question is, will this function do the job? If so, how exactly do I use the "idx" parameter? I don't quite understand it.

If this isn't going to work, how can I parse this user-entered data?

  • both equations are strings (y=mx+b)
  • m and b have private variables dedicated in storing the decimal value (i.e. double m_ and double b_ are private member variables)
5

2 Answers

This is how the idx parameter works:

#include <string>
#include <iostream>

int main(void)
{
    std::string data = "y=5.9568x+3.14"; //say you have a string like this..

    double y, x, m, b;
    y = 0;
    x = 0;

    std::size_t offset = 0; //offset will be set to the length of characters of the "value" - 1.
    m = std::stod(&data[2], &offset); //So we want to get the value "5.9568
    b = std::stod(&data[offset + 3]); //When we reach this line, offset has a value of 6

    std::cout<<b;
    return 0;
}

So now you're asking why does it have a value of 6? Well because:

5.9568 is exactly: 6 characters in length. Thus on the next line when we do

b = std::stod(&data[offset + 3]);

we are actually feeding it a pointer to address of x + 3.. and that turns out to be right at the beginning of the 3.14.

In other words it's equivalent to:

std::stod(&data[9]);

So that idx parameter is actually the index/length of the double in characters within the string. If the string is:

str = "3.14159"

Then std::stod(str, &idx) will make idx equal to: 6.

if the string is:

str = "y = 1024.789" then std::stod(&str[4], &idx) will make idx equal to: 8 STARTING FROM &str[4]..

1

Here's something simple with no error checking to get you started:

Assuming your input string is always exactly of the form y=mx+b and you wish to parse it to obtain the numerical values of m and b you can first tokenize the string with y, =, x, and as delimiters.

An example of a tokenizing function can be found here. Here it is reproduced:

void tokenize(const std::string &str,
              std::vector<std::string> &tokens,
              const std::string &delimiters)
{
  // Skip delimiters at beginning.
  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
  // Find first "non-delimiter".
  std::string::size_type pos     = str.find_first_of(delimiters, lastPos);

  while (std::string::npos != pos || std::string::npos != lastPos)
  {
    // Found a token, add it to the vector.
    tokens.push_back(str.substr(lastPos, pos - lastPos));
    // Skip delimiters.  Note the "not_of"
    lastPos = str.find_first_not_of(delimiters, pos);
    // Find next "non-delimiter"
    pos = str.find_first_of(delimiters, lastPos);
  }
}

The first argument is the string to tokenize, the second is a reference to a vector<string> which the function will put the tokens in, and the third argument is a string containing all the delimiter characters. You can use it with the delimiters mentioned above like this:

string s = "y=-3x + 10";
vector<string> tokens;
tokenize(s, tokens, "y=x ");

For the example string above tokens will contain the following strings: -3, +, and 10.

Now you can iterate over tokens and call stod() on each token. You can put the results of stod() in a vector<double>:

vector<double> doubles;
for (vector<string>::iterator iter = tokens.begin(); iter != tokens.end(); ++iter) {
    try {
        doubles.push_back(stod(*iter)); // size_t* idx is an optional argument
    } catch (...) {
        // handle exceptions here. stod() will throw an exception
        // on the "+" token but you can throw it away
    }
}

Now doubles should have exactly 2 elements -- one for the slope and another for the intercept. Assuming the slope came first (the string was of the form y=mx+b instead of y=b+mx) then you can extract them from doubles:

double m = doubles[0];
double b = doubles[1];

Parsing the initial string is more complicated if the user is allowed different forms like y=b+mx (in that case the intercept came first), and much more complicated if the user can enter even stranger (but valid) forms like x*m+b=y (now you can't just assume that the number before the x character is the slope). It's not clear from your question exactly what alternate forms are considered valid, but nonetheless this should get you started.

Finally, as to your question about *idx, stod() puts into it the position of the first character after the number it parsed. This allows you to easily parse multiple numbers in a single string by skipping the number that was just parsed. Using the example at your reference link with some added comments:

std::string orbits ("365.24 29.53");
std::string::size_type sz;     // alias of size_t

double earth = std::stod (orbits,&sz);
// sz now holds the position of the first character after 365.24, which is whitespace
// the next call to stod() will start from the sz position
double moon = std::stod (orbits.substr(sz));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

David Miller

David Miller

Executive Financial & Market Analyst

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.

Share this article
Twitter Facebook Pinterest