我有一堆这样的文字:
foo
bar
baz
在C ++中,将此转换为最有效的方法是什么:
<p>foo<br />bar</p>
<p>baz</p>
用于大量(ish)数量的文本(最多8000个字符)。
我很高兴使用boost regex_replace
,但我想知道字符串搜索\n\n
是否更有效?有什么想法吗?还有其他方法吗?
在我工作的环境中,大多数第三方库都无法使用。
答案 0 :(得分:5)
我会使用一个简单的状态机。确实需要 通过循环每次比较状态,但是 它应该没关系(它可以通过一个sub来优化 循环在第三状态 - 见下文)。开始状态会 与遇到两个换行符时相同。那里 将是前一个字符的变量,一个用于 跟踪上一个换行符的位置(用于 产生输出)。
州将是:
遇到双新线。进入州时的行动:&lt; p&gt;的输出,该行和&lt; / p&gt;
遇到单个新行。进入状态时的动作:行的输出和
遇到正常字符
该程序看起来更像是一个C程序,但是......
答案 1 :(得分:2)
不要忘记为HTML实体编码文本!例如如果你有
foo&
你需要适当地翻译它:
foo&
(不知道你是否知道 - 它只是没有被提及而且经常被遗忘!)
答案 2 :(得分:1)
如果您的数据没有任何意外,您只需将\n\n
的所有实例替换为</p><p>
,然后将所有\n
替换为<br/>
。然后将结果括在<p>
和</p>
,您就完成了。这不涉及边缘情况(例如,三个分隔段落的新行),但它非常简单,而且比编写状态机更快!
更新:显然,如果您有\n\n\n
,\n\n\n\n
等,那么您也可以先用较长的序列替换</p><p>
的那些。< / p>
答案 3 :(得分:0)
紧张,快速,丑陋的状态机。处理退化的情况,例如空输入,输入开头的空白行,段落之间的长串空行以及输入结尾处缺少的换行标记。
template <typename InputIt, typename OutputIt>
void TextToHTML(InputIt begin, InputIt end, OutputIt target) {
start: if (begin == end) return;
if (*begin == '\n') { ++begin; goto start; }
*target++ = '<'; *target++ = 'p'; *target++ = '>';
para: *target++ = *begin++;
if (begin == end) goto endp;
if (*begin != '\n') goto para;
if (++begin == end) goto endp;
if (*begin == '\n') goto endp;
*target++ = '<'; *target++ = 'b'; *target++ = 'r'; *target++ = ' '; *target++ = '/'; *target++ = '>';
goto para;
endp: *target++ = '<'; *target++ = '/'; *target++ = 'p'; *target++ = '>'; *target++ = '\n';
goto start;
}
int main() {
std::string text = "foo\nbar\n\nbaz";
std::string html;
TextToHTML(text.begin(), text.end(), std::back_inserter(html));
std::cout << html << std::endl;
return 0;
}