当我在 C++ 中使用正则表达式时,我注意到 g++ (MinGW) 和 Visual Studio 14 2015 编译器(均在 Windows 上)之间存在一些不规则之处。这是我尝试过的代码:
#include <iostream>
#include <vector>
#include <string>
#include <regex>
static const std::string data = "\n a = 10\n b = 20\n";
int main(int argc, char* argv[])
{
auto strIt = data.begin();
while (strIt != data.end())
{
std::regex e("^[ \t\n\r]");
std::smatch m;
std::string s(strIt, data.end());
if (std::regex_search(s, m, e))
{
strIt += m[0].str().size();
}
else
{
std::cout << "s = \"" << s << "\"" << '\n';
break;
}
}
}
当使用 g++ 编译时,我得到了预期的输出
s = "a = 10\n b = 20\n"
但是当使用Visual Studio编译器时,它会吐出
s = "b = 20\n"
忽略整个“a = 10”部分。通过调试功能在 Visual Studio 中进一步调查后,我发现 m 变量保留了“a = 10”部分之后的空间。
你知道它为什么会这样吗?我是否在某个地方犯了一个大错误却没有注意到?请帮忙。
最佳答案
首先,一个简化的示例:
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main() {
const string data = "abc\nXabc";
regex re("^X");
smatch match;
if (regex_search(data, match, re))
cout << "match: " << match.str() << endl;
else
cout << "no match" << endl;
return 0;
}
Visual Studio 2015 输出:
match: X
MinGW 7.1.0 输出:
no match
因此,区别在于正则表达式中的 ^
是匹配行的开头还是仅匹配字符串的开头。在 C++ 17 中,它由传递给 regex
构造函数的 regex::flag_type
参数确定。
31.5.1 Bitmask type syntax_option_type :
The type syntax_option_type is an implementation-defined bitmask type. Setting its elements has the effects listed in Table 130. A valid value of type syntax_option_type shall have at most one of the grammar elements ECMAScript, basic, extended, awk, grep, egrep, set. If no grammar element is set, the default grammar is ECMAScript.
Table 130 — syntax_option_type effects
...
multiline — Specifies that ^ shall match the beginning of a line and $ shall match the end of a line, if the ECMAScript engine is selected.
为了使 ^
匹配行的开头,regex
对象需要像这样初始化:
regex re("^X", regex_constants::multiline);
总之,MinGW 的行为在 C++ 17 标准下是正确的。
关于c++ - 在 C++ 中使用带有正则表达式的 g++ 和 Visual Studio 14 2015 编译器时的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45909196/