我正在研究一些规范化大量数据的代码。在处理结束时,许多key =“value”对被写出到文件中。
“值”部分可以是任何内容,因此在输出时,值必须将任何嵌入的引号转义为\“。
现在,我正在使用以下内容:
outstream << boost::regex_replace(src, rxquotesearch, quoterepl);
// (where rxquotesearch is boost::regex("\"") and quoterepl is "\\\\\"")
然而,gprof显示我将大部分执行时间花在这个方法上,因为我必须为每一行的每个值调用它。
我很好奇是否有比这更快的方法。我不能使用std :: replace,因为我用两个替换一个字符。
感谢您的任何建议。
答案 0 :(得分:6)
如果速度是一个问题,你应该使用手写功能来做到这一点。请注意使用reserve()
尝试将内存(重新)分配保持在最低限度。
string escape_quotes(const string &before)
{
string after;
after.reserve(before.length() + 4);
for (string::size_type i = 0; i < before.length(); ++i) {
switch (before[i]) {
case '"':
case '\\':
after += '\\';
// Fall through.
default:
after += before[i];
}
}
return after;
}
答案 1 :(得分:2)
我根本不接受源字符串并构建一个新的输出字符串。
我会遍历源字符串并打印每个字符,如果字符是引号,则在打印前打印“\”它
答案 2 :(得分:1)
我并不感到惊讶的是,这里的正则表达式真的很慢 - 你正在使用一把大型的通用锤子敲打一个小小的钉子。当然,如果你最终需要做一些更有趣的事情,那么正则表达式很可能会在简单性方面迅速获得优势。
对于更简单/更快速的方法,您可以尝试将转义字符串一次写入一个单独的缓冲区中。然后添加转义变得微不足道,并且您不会浪费任何时间重新分配字符串或移动字符。最大的困难是管理缓冲区的大小,但你可以只使用一个向量,并为每个字符串重复使用相同的向量,以避免重复分配。效率增益在很大程度上取决于矢量如何工作的细节,但如果需要,您可以随时将其归结为原始数组和手动内存管理。
如果您使用了vector:
,例程可能看起来像这样vector<char> buf;
for( some_iterator it = all_the_strings.begin();
it != all_the_strings.end(); ++it )
{
buf.clear();
const string & str = *it;
for( size_t i = 0; i < str.size(); ++i )
{
if( str[i] == '"' || str[i] == '\\' )
buf.push_back( '\\' );
buf.push_back( str[i] );
}
buf.push_back( '\0' );
// note: this is not guaranteed to be safe, see answer comments
const char * escaped = &buf[0];
// print escaped string to file here...
}
答案 3 :(得分:0)
这里有一个使用string :: find和string :: insert的实现,不确定它是否更快,你必须弄明白!这是:
std::string src = "hey there i have \" all \" over the f\"in pla\"ce\"";
size_t n = 0;
while ( (n=src.find("\"",n)) != std::string::npos )
{
src.insert(n,"\\");
n+=2;
}
std::cout << src << std::endl;
打印出来:
嘿,我有“全部” f \“in pla \”ce \“