C++ 正则表达式:使用求反方法搜索C+时,搜索不包含字符的组+;
我正在使用默认的Visual Studio 2017社区版本。我刚刚完成了bignum实现的解析模型 我在向我的班级介绍公式时偶然发现了一个问题。这是一个字符串/正则表达式问题 考虑这个包含变量和常量的字符串:C++ 正则表达式:使用求反方法搜索C+时,搜索不包含字符的组+;,c++,regex,string,C++,Regex,String,我正在使用默认的Visual Studio 2017社区版本。我刚刚完成了bignum实现的解析模型 我在向我的班级介绍公式时偶然发现了一个问题。这是一个字符串/正则表达式问题 考虑这个包含变量和常量的字符串: std::string formular_str = "1 + x * y / 2"; 将此字符串传递到解析函数中还需要int类型的向量(大小为2,因为有2个变量)(在本例中) formular\u str(“1+x*y/2”)现在看起来是这样的:“1+x*y/2” 接下来,我用递增索
std::string formular_str = "1 + x * y / 2";
将此字符串传递到解析函数中还需要int类型的向量(大小为2,因为有2个变量)(在本例中)
formular\u str
(“1+x*y/2”
)现在看起来是这样的:“1+x*y/2”
接下来,我用递增索引替换所有变量(x
,y
)。
我在解析中使用#
来表示vec
的索引
std::regex reg_variable("[a-zA-Z]+[0-9]*");
unsigned ctr = 0;
while (std::regex_search(formular_str, reg_variable, std::regex_constants::format_first_only)) {
formular_str = std::regex_replace(formular_str, reg_variable, std::string("#") + std::to_string(ctr++), std::regex_constants::format_first_only);
}
formular\u str
(“1+x*y/2”
)现在看起来是这样的:“1+#0*#1/2”
模型将正确地将#0
和#1
解释为vec[0]
和vec[1]
最后,我希望我的字符串和向量如下所示:
"#2+#0*#1/#3"
{5, 4, 1, 2}
但这里是预处理失败的地方。试图向后推()常量1
和2
到向量,并将其替换为#2
和#3
,而不会陷入无休止的循环
std::regex reg_constant("[^\\+\\-\\*\\/]+");
while (std::regex_search(formular_str, matches, reg_constant, std::regex_constants::format_first_only)) {
//std::cout << "matches.str(0) = " << matches.str(0) << ", formular_str = " << formular_str << std::endl;
vec.push_back(std::atoi(matches.str(0).c_str()));
formular_str = std::regex_replace(formular_str, reg_constant, std::string("#") + std::to_string(ctr++), std::regex_constants::format_first_only);
}
第一场比赛是正确的,但它只是一直停留在第一个数字上。它甚至达不到2
。因此,一个想法是将#
视为操作符,并将其从匹配中排除:
std::regex reg_constant("[^\\+\\-\\*\\/\\#]+");
产生这种模式的原因是:
matches.str(0) = 1, formular_str = 1+#0*#1/2
matches.str(0) = 2, formular_str = #2+#0*#1/2
matches.str(0) = 3, formular_str = ##3+#0*#1/2
matches.str(0) = 4, formular_str = ###4+#0*#1/2
matches.str(0) = 5, formular_str = ####5+#0*#1/2
matches.str(0) = 6, formular_str = #####6+#0*#1/2
matches.str(0) = 7, formular_str = ######7+#0*#1/2
matches.str(0) = 8, formular_str = #######8+#0*#1/2
...
我还尝试了std::sregex_迭代器,但它也被卡住了。
我对此一无所知,我也考虑过在while循环中使用多层过滤和额外的std::regex_search
和std::regex_replace
,但它失败了,因为它不会改变公式以打破while循环。所以它必须是正则表达式来识别正确的字符串,但我似乎不能得到正确的结果。请帮帮我
完整代码(带有额外的std::couts)
#包括
#包括
#包括
int main(){
std::向量向量向量{5,4};
标准::字符串公式_str=“1+x*y/2”;
std::我建议使用不同的方法,如调车场或递归下降解析器。它们经过了很好的研究,并且很容易正确地工作(在您完成当前工作的部分后,您所采用的方法仍然需要类似的东西)。我已经完成了所有优先级规则/优先级等的解析。这只是关于字符串预处理。重点是,在解析时检索操作数并将其放在堆栈上要容易得多,而不是试图提前进行替换,并将正确的值作为参数传递。但这与此无关通过解析,它只需在字符串中替换组,而不会在需要帮助的地方卡住。也许我应该重新编写它。你是对的,但是让你的lexer检索(例如)x
,只需在你的符号表中查找x
的值,就可以轻松完成。
matches.str(0) = 1, formular_str = 1+#0*#1/2
matches.str(0) = #2, formular_str = #2+#0*#1/2
matches.str(0) = #3, formular_str = #3+#0*#1/2
matches.str(0) = #4, formular_str = #4+#0*#1/2
matches.str(0) = #5, formular_str = #5+#0*#1/2
matches.str(0) = #6, formular_str = #6+#0*#1/2
matches.str(0) = #7, formular_str = #7+#0*#1/2
matches.str(0) = #8, formular_str = #8+#0*#1/2
...
std::regex reg_constant("[^\\+\\-\\*\\/\\#]+");
matches.str(0) = 1, formular_str = 1+#0*#1/2
matches.str(0) = 2, formular_str = #2+#0*#1/2
matches.str(0) = 3, formular_str = ##3+#0*#1/2
matches.str(0) = 4, formular_str = ###4+#0*#1/2
matches.str(0) = 5, formular_str = ####5+#0*#1/2
matches.str(0) = 6, formular_str = #####6+#0*#1/2
matches.str(0) = 7, formular_str = ######7+#0*#1/2
matches.str(0) = 8, formular_str = #######8+#0*#1/2
...
#include <regex>
#include <string>
#include <iostream>
int main() {
std::vector<int> vec{ 5, 4 };
std::string formular_str = "1 + x * y / 2";
std::cout << "Starting formular: " << formular_str << std::endl;
std::smatch matches;
std::regex reg_whitespace_near_operator("[\\s]+([\\+\\-\\*\\/])[\\s]+");
while (std::regex_search(formular_str, matches, reg_whitespace_near_operator, std::regex_constants::format_first_only)) {
formular_str = std::regex_replace(formular_str, reg_whitespace_near_operator, matches.str(1), std::regex_constants::format_first_only);
}
std::cout << "Whitespace removed: " << formular_str << std::endl;
std::regex reg_variable("[a-zA-Z]+[0-9]*");
unsigned ctr = 0;
while (std::regex_search(formular_str, reg_variable, std::regex_constants::format_first_only)) {
formular_str = std::regex_replace(formular_str, reg_variable, std::string("#") + std::to_string(ctr++), std::regex_constants::format_first_only);
}
std::cout << "Variables replaced: " << formular_str << std::endl;
std::regex reg_constant("[^\\+\\-\\*\\/]+");
while (std::regex_search(formular_str, matches, reg_constant, std::regex_constants::format_first_only)) {
std::cout << "matches.str(0) = " << matches.str(0) << ", formular_str = " << formular_str << std::endl;
vec.push_back(std::atoi(matches.str(0).c_str()));
formular_str = std::regex_replace(formular_str, reg_constant, std::string("#") + std::to_string(ctr++), std::regex_constants::format_first_only);
}
std::cout << "Finished formular: " << formular_str << std::endl;
}