c++ regex,传递等价的字符串参数,但接收不同的输出
c++ regex, passing equivalent string parameters, but receiving different outputs
我们收到一个非常不寻常的错误。我们的程序尝试使用正则表达式和递归计算导数。
从我们的文件输入,我们使用regex来确定我们需要应用的派生规则。使用smatch,我们能够解析字符串方程的不同部分。
程序试图计算"(x^2)+(x)"的导数时出现错误。Smatch从这个方程中解析"x^2"answers"x",并使用这两个字符串作为参数递归地调用导数函数。然而,我们的输出缺少x的导数。
输入:(x^2)+(x)
调用:
return derivative(s[1].str()) + "+" + derivative(s[2].str());
输出:2x^1*1+
然而,如果我们传递:
return derivative(s[1].str()) + "+" + derivative("x");
则输出为:
2x^1*1+1
我们也检查了if (s[2].str() == "x"),这是真的。为什么我们从相同的输入得到不同的输出?
Equations.txt:
7
x
5x
x^3
(x^2)+(x)
main.cpp:
#include <iostream>
#include <fstream>
#include <cmath>
#include <queue>
#include <stack>
#include <regex>
#include <vector>
#include <iterator>
#include <map>
#include <string>
using namespace std;
/*****************************************************************/
class ReadFile
{
private:
ifstream infile;
queue<string> input;
public:
ReadFile(string filename)
{
infile.open(filename);
if(!infile)
cerr << "Unable to open filen";
string temp;
while(!infile.eof())
{
getline(infile, temp);
input.push(temp);
}
}
string getFront()
{
string temp = input.front();
input.pop();
return temp;
}
bool isEmpty() { return input.empty(); }
};
/*****************************************************************/
class Simplifier
{
private:
string exp;
public:
Simplifier(string ex): exp(ex) {}
};
/*****************************************************************/
class ExpressionAnalyzer
{
string expression;
map<string, regex> rules;
smatch s;
public:
ExpressionAnalyzer()
{
rules["con"] = "([[:d:]]+)";
rules["xxx"] = "(x|\(x\))";
rules["cof"] = "([[:d:]]+)(.*)";
rules["pow"] = "(.*)[^]([[:d:]]+)";
rules["add"] = "\((.*)\)[+]\((.*)\)";
}
string derivative(string str)
{
s = generateSmatch(str);
if(regex_match(str, rules["con"]))
return "0";
else if (regex_match(str, rules["xxx"]))
return "1";
else if (regex_match(str, rules["cof"]))
return s[1].str() + "*" + derivative(s[2].str());
else if (regex_match(str, rules["pow"]))
return s[2].str() + s[1].str() + "^" + to_string(stoi(s[2].str()) - 1) + "*" + derivative(s[1].str());
else if (regex_match(str, rules["add"])) {
cout << "s[1]: " << s[1].str() << ", s[2]: " << s[2].str() << endl;
return derivative(s[1].str()) + "+" + derivative(s[2].str());}
return "";
}
smatch generateSmatch(string str)
{
smatch s;
map<string, regex>::iterator it;
for(it = rules.begin(); it != rules.end(); it++)
{
if(regex_match(str, s, it->second))
{
return s;
}
}
return s;
}
};
/*****************************************************************/
int main()
{
ReadFile test("Equations.txt");
string s = test.getFront();
ExpressionAnalyzer e;
cout << e.derivative(s) << endl;
}
我仍然不确定这里到底发生了什么。要了解更多信息,请使用调试器,逐步执行程序并在每个步骤后检查每个变量。或者添加更多的调试输出,以确保您知道您的程序在递归的哪个点失败。
然而,通过去掉循环(和整个generateSmatch()
-函数),我能够让你的代码工作(几乎,见下文)。请注意,可能有一个更简洁的解决方案,因为在if语句中重复了很多代码,但是这个解决方案可以工作,我将把美化留给您。还要注意,这可能只是部分解决方案,因为我没有测试文件加载部分。因此,在调用此函数之前,请确保去掉额外的n
和类似的内容。
#include <iostream>
#include <fstream>
#include <cmath>
#include <queue>
#include <stack>
#include <regex>
#include <vector>
#include <iterator>
#include <map>
#include <string>
using namespace std;
/*****************************************************************/
class ExpressionAnalyzer
{
string expression;
map<string, regex> rules;
public:
ExpressionAnalyzer()
{
rules["con"] = "([[:d:]]+)";
rules["xxx"] = "(x|\(x\))";
rules["cof"] = "([[:d:]]+)(.*)";
rules["pow"] = "(.*)[^]([[:d:]]+)";
rules["add"] = "\((.*)\)[+]\((.*)\)";
}
string derivative(string str)
{
cout << "call with: " << str << endl;
if(regex_match(str, rules["con"])){
cout << "const!" << endl;
return "0";
}
else if (regex_match(str, rules["xxx"])){
cout << "xxx!" << endl;
return "1";
}
else if (regex_match(str, rules["cof"])){
cout << "cof!" << endl;
smatch s;
regex_match(str, s, rules["cof"]);
cout << "s[1]: " << s[1].str() << ", s[2]: " << s[2].str() << endl;
return s[1].str() + "*" + derivative(s[2].str());
}
else if (regex_match(str, rules["pow"])){
cout << "pow!" << endl;
smatch s;
regex_match(str, s, rules["pow"]);
cout << "s[1]: " << s[1].str() << ", s[2]: " << s[2].str() << endl;
return s[2].str() + s[1].str() + "^" + to_string(stoi(s[2].str()) - 1) + "*" + derivative(s[1].str());
}
else if (regex_match(str, rules["add"])) {
cout << "add!" << endl;
smatch s;
regex_match(str, s, rules["add"]);
cout << "s[1]: " << s[1].str() << ", s[2]: " << s[2].str() << endl;
return derivative(s[1].str()) + "+" + derivative(s[2].str());}
else{
cout << "not recognized!" << endl;
return "";
}
}
};
/*****************************************************************/
int main()
{
ExpressionAnalyzer e;
cout << e.derivative("(x)") << endl;
cout << e.derivative("(x^2)") << endl;
cout << e.derivative("x^2") << endl;
cout << e.derivative("(x^2)+(x)") << endl;
}
输出:call with: (x)
xxx!
1 <-result
call with: (x^2)
not recognized!
<-result (parantheses were not simplified away yet)
call with: x^2
pow!
s[1]: x, s[2]: 2
call with: x <- recursion
xxx!
2x^1*1 <-result (without parantheses: working)
call with: (x^2)+(x)
add!
s[1]: x^2, s[2]: x
call with: x <- recursion
xxx!
call with: x^2 <- recursion
pow!
s[1]: x, s[2]: 2
call with: x <- recursion lvl 2
xxx!
2x^1*1+1 <- result (YAY!)
我故意留下调试输出,也许它有助于看到,有时更详细的输出有助于看到内部发生了什么。
s
是一个成员,在你的递归函数中你改变了它
s = generateSmatch(str);
将其转换为局部变量以获得预期结果:
string derivative(string str)
{
smatch s;
if(regex_match(str, s, rules["con"]))
return "0";
else if (regex_match(str, s, rules["xxx"]))
return "1";
else if (regex_match(str, s, rules["cof"]))
return s[1].str() + "*" + derivative(s[2].str());
else if (regex_match(str, s, rules["pow"]))
return s[2].str() + s[1].str() + "^" + to_string(stoi(s[2].str()) - 1) + "*" + derivative(s[1].str());
else if (regex_match(str, s, rules["add"])) {
cout << "s[1]: " << s[1].str() << ", s[2]: " << s[2].str() << endl;
return derivative(s[1].str()) + "+" + derivative(s[2].str());}
return "";
}
相关文章:
- C++输出参数与返回值
- C++函子作为函数的输出参数
- 将ctypes c_void_p强制转换为c输出参数
- 用输出参数包装一个c++函数,以便在javascript/node中使用
- 我可以将函数的输出参数存储到unique_ptr中吗?
- 在存在错误代码的情况下输出参数与 NRVO
- 具有输出参数的QT InvoKeMethod调用函数
- 将具有std ::向量的C 函数称为Julia的输入和输出参数
- jni jiniArray 作为输出参数不会更改参数的值
- 返回容器时删除输出参数
- 通过 API 填写"std::optional"<T>,获取输出"T*"参数
- 指针或局部变量,用于函数的输出参数
- 如何在输出参数中使用基类
- 值语义与具有大数据结构的输出参数
- 当输出参数是类时,如何在C++中调用COM方法
- 如何在不破坏现有代码的情况下将输出参数添加到功能
- stl数据结构的堆栈上输出参数与返回值的效率
- C# P/调用:本机输出参数值不会到达托管代码
- 在 C++11 中将结构作为输出参数传递
- 将字符串从 C# 方法返回到输出参数中的C++函数