如何正确使用std :: stod

时间:2014-09-24 04:02:47

标签: c++

我正在写一个简单的线性线计算器。例如,用户可以输入两个等式(字符串),例如y = 5x + 3和y = -3x + 6。该计算器最基本的特征是它将返回这两条线的交点。

我似乎无法弄清楚的障碍是如何将字符串解析成两段数据:斜率和y轴截距。这是一个简单的计算器,因此两条线的格式都是y = mx + b,但是,斜率和/或y轴截距都可以是非整数(即浮点数)。

我遇到了一个名为stod的字符串库中的函数,它将字符串中的数字转换为数值(我能正确理解吗?)。

http://www.cplusplus.com/reference/string/stod/

我的问题是,这个功能能完成这项工作吗?如果是这样,我究竟如何使用“idx”参数?我不太明白。

如果这不起作用,我该如何解析这个用户输入的数据?

  • 两个方程都是字符串(y = mx + b)
  • m和b有专用于存储十进制值的私有变量(即double m_和double b_是私有成员变量)

2 个答案:

答案 0 :(得分:3)

这是idx参数的工作原理:

#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;
}

所以现在你问为什么它的值为6?好吧因为:

5.9568正好:长度为6个字符。因此,当我们做下一行时

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

我们实际上正在向它提供一个指向x + 3 ...的地址的指针,结果证明它位于3.14的开头。

换句话说,它相当于:

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

因此idx参数实际上是字符串中字符的double的索引/长度。如果字符串是:

str = "3.14159"

然后std::stod(str, &idx)会使idx等于:6。

如果字符串是:

str = "y = 1024.789"然后std::stod(&str[4], &idx)会使idx等于:8 STARTING FROM&amp; str [4] ..

答案 1 :(得分:1)

这里有一些简单的事情,没有错误检查让你入门:

假设您的输入字符串始终完全是y=mx+b形式,并且您希望解析它以获取mb的数值,您可以先用{{{{}}标记字符串。 1}},y=x作为分隔符。

可以找到标记化功能的示例here。在此重现:

第一个参数是要标记的字符串,第二个参数是函数将令牌放入的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); } } ,第三个参数是包含所有分隔符的字符串。您可以将它与上面提到的分隔符一起使用,如下所示:

vector<string>

对于上面的示例字符串,string s = "y=-3x + 10"; vector<string> tokens; tokenize(s, tokens, "y=x "); 将包含以下字符串:tokens-3+

现在,您可以迭代10并在每个令牌上调用tokens。您可以将stod()的结果放在stod()

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 } } 应该有2个元素 - 一个用于斜率,另一个用于截距。假设斜率是第一个(字符串的格式为doubles而不是y=mx+b),那么您可以从y=b+mx中提取它们:

doubles

如果允许用户使用double m = doubles[0]; double b = doubles[1]; 之类的不同形式(在这种情况下拦截首先出现),解析初始字符串会更复杂,如果用户可以输入更奇怪(但有效)的形式,则会更加复杂y=b+mx(现在你不能只假设x*m+b=y字符前的数字是斜率)。从你的问题中确切地知道哪些替代形式被认为是有效的,但是这不应该让你开始。

最后,关于x的问题,*idx将第一个字符放在其解析后的位置。这允许您通过跳过刚刚解析的数字,轻松地在单个字符串中解析多个数字。使用参考链接中的示例以及一些添加的注释:

stod()