我是C ++的新手,必须处理文本文件。我决定使用Regex来做到这一点。我想出的正则表达式:
(([^\\s^=]+)\\s*=\\s*)?\"?([^\"^\\s^;]+)\"?\\s*;[!?](\\w+)\\s*
我已经根据以下帖子编写了C ++代码:
c++ regex extract all substrings using regex_search()
这是C ++代码:
#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include <chrono>
#include <iterator>
void print(std::smatch match)
{
}
int main()
{
std::ifstream file{ "D:\\File.txt" };
std::string fileData{};
file.seekg(0, std::ios::end);
fileData.reserve(file.tellg());
file.seekg(0, std::ios::beg);
fileData.assign(std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>());
static const std::string pattern{ "(([^\\s^=]+)\\s*=\\s*)?\"?
([^\"^\\s^;]+)\"?\\s*;[!?](\\w+)\\s*" };
std::regex reg{ pattern };
std::sregex_iterator iter(fileData.begin(), fileData.end(), reg);
std::sregex_iterator end;
const auto before = std::chrono::high_resolution_clock::now();
std::for_each(iter, end, print);
const auto after = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> delta = after - before;
std::cout << delta.count() << "ms\n";
file.close();
}
我正在处理的文件包含541行。上面的程序需要5秒才能获得全部507个匹配项。我以前在C#中做过这样的事情,并且从来没有这么慢的Regex。所以我在C#中尝试了同样的事情:
var filedata = File.ReadAllText("D:\\File.txt", Encoding.Default);
const string regexPattern =
"(([^\\s^=]+)\\s*=\\s*)?\"?([^\"^\\s^;]+)\"?\\s*;[!?](\\w+)\\s*";
var regex = new Regex(regexPattern, RegexOptions.Multiline |
RegexOptions.Compiled );
var matches = regex.Matches(filedata);
foreach (Match match in matches)
{
Console.WriteLine(match.Value);
}
仅需500 MILLISECONDS即可找到所有507个匹配项,并将其打印在控制台上。由于我必须使用C ++,因此我需要更快。
如何使C ++程序更快?我做错了什么?
答案 0 :(得分:0)
如您所知,我们有两种类型的字符串:C 样式字符串和 std::string
。
std::string
可以在我们编码时使用,但我们可以说它是一种沉重的东西(这就是为什么有些人不喜欢它)。首先,std::string
使用了堆内存意味着它使用了 new
或 malloc
;其次,std::string
在其大小增加的同时使用了某种特定算法(将当前大小加倍并将当前内容移动到新的内存区域并释放旧的)。这些会导致性能问题。
正则表达式显然是关于字符串的,它需要到处使用字符串。 std::regex
与 std::string
的关系很大,这就是 std::regex
的性能不佳的原因。
此外,std::string
完全是运行时的东西。例如,您可以在编译时初始化 C 样式字符串,但不能在编译时初始化 std::string
。这意味着关于 std::string
的事情很少在编译时被优化。
下面是一个关于我们如何利用编译时间在运行时获得非常好的性能的示例:Why is initialization of variable with constexpr evaluated at runtime instead of at compile time
std::regex
在编译时不能做太多事情,因为它使用了 std::string
,这也可能导致性能问题。
如果std::string_view
的源代码中可以使用std::regex
,我认为性能会更好。
总之,字符串在任何语言中都是很常见的东西,但没那么容易。