我正在写一个简单的线性线计算器。例如,用户可以输入两个等式(字符串),例如y = 5x + 3和y = -3x + 6。该计算器最基本的特征是它将返回这两条线的交点。
我似乎无法弄清楚的障碍是如何将字符串解析成两段数据:斜率和y轴截距。这是一个简单的计算器,因此两条线的格式都是y = mx + b,但是,斜率和/或y轴截距都可以是非整数(即浮点数)。
我遇到了一个名为stod的字符串库中的函数,它将字符串中的数字转换为数值(我能正确理解吗?)。
http://www.cplusplus.com/reference/string/stod/
我的问题是,这个功能能完成这项工作吗?如果是这样,我究竟如何使用“idx”参数?我不太明白。
如果这不起作用,我该如何解析这个用户输入的数据?
答案 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
形式,并且您希望解析它以获取m
和b
的数值,您可以先用{{{{}}标记字符串。 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()