我想要简单的基于C ++字符串的模板库来在运行时替换字符串。
例如,我将使用
string template = "My name is {{name}}";
在运行时,我希望根据实际名称更改名称。
我找到了一个例子,www.stringtemplate.org,但是在讨论antlr等时我有点害怕。
答案 0 :(得分:14)
更新:项目已移至Github并重命名为CTemplate:https://github.com/OlafvdSpek/ctemplate
从新项目页面:
最初被称为Google模板,因为它起源于用于Google搜索结果页面的模板系统。现在它有一个更符合社区所有性的通用名称。
您是否尝试过Google的CTemplate库?它似乎正是您所寻找的:http://code.google.com/p/google-ctemplate/
您的示例将如下实现:
在example.tpl中:
我的名字是{{name}}
在example.cc中:
#include <stdlib.h>
#include <string>
#include <iostream>
#include <google/template.h>
int main(int argc, char** argv)
{
google::TemplateDictionary dict("example");
dict.SetValue("name", "John Smith");
google::Template* tpl = google::Template::GetTemplate("example.tpl",
google::DO_NOT_STRIP);
std::string output;
tpl->Expand(&output, &dict);
std::cout << output;
return 0;
}
然后:
$ gcc example.cc -lctemplate -pthread
$ ./a.out
我的名字是John Smith
请注意,如果您不想在单独的文件中写入模板,还可以将模板编写为常量字符串。
答案 1 :(得分:6)
您可以使用sprintf
吗?
如果你想包括提升,还有boost::format
。
答案 2 :(得分:4)
如果你有一个函数用一个字符串替换所有出现的字符串:
std::string replace_all(std::string str, const std::string &remove, const std::string &insert)
{
std::string::size_type pos = 0;
while ((pos = str.find(remove, pos)) != std::string::npos)
{
str.replace(pos, remove.size(), insert);
pos++;
}
return str;
}
然后你可以这样做:
std::string pattern = "My name is {{first_name}} {{last_name}} and I live in {{location}}";
std::string str = replace_all(replace_all(replace_all(pattern,
"{{first_name}}", "Homer"),
"{{last_name}}", "Simpson"),
"{{location}}", "Springfield");
答案 3 :(得分:3)
如果您不熟悉C ++,在安装中添加新库(模板或其他)只会增加学习曲线。这是您可以使用内置功能简单,优雅,高效地完成的任务。
与类似的答案不同,此代码只对输入进行一次传递,并且可以很好地扩展到大型词典:
// header
#include <map>
#include <sstream>
typedef std::map< std::string, std::string > subst_map;
// implementation
using namespace std;
string do_substitutions( string const &in, subst_map const &subst ) {
ostringstream out;
size_t pos = 0;
for (;;) {
size_t subst_pos = in.find( "{{", pos );
size_t end_pos = in.find( "}}", subst_pos );
if ( end_pos == string::npos ) break;
out.write( &* in.begin() + pos, subst_pos - pos );
subst_pos += strlen( "{{" );
subst_map::const_iterator subst_it
= subst.find( in.substr( subst_pos, end_pos - subst_pos ) );
if ( subst_it == subst.end() ) throw runtime_error( "undefined substitution" );
out << subst_it->second;
pos = end_pos + strlen( "}}" );
}
out << in.substr( pos, string::npos );
return out.str();
}
// usage
pair< string, string > substitutions_init[] = {
make_pair( "firstname", "homer" ),
make_pair( "lastname", "simpson" )
};
subst_map substitutions
( substitutions_init, substitutions_init + sizeof(substitutions_init)/sizeof(*substitutions_init) );
int main() {
cerr << do_substitutions( "Mr. {{lastname}}, {{firstname}} esquire", substitutions ) << endl;
}
答案 4 :(得分:1)
您是否考虑过使用ostringstram而不是“string templates”的一组内联函数?
inline std::string name_template(const std::string& name)
{
std::ostringstream os;
os << "My name is " << name;
return os.str();
}
如果您需要更多的一般性,还有其他替代方法。例如,一个类层次结构,其中基类提供“格式”接口,子类使用适当的变化实现来实现它。
答案 5 :(得分:1)
您可以查看Inja。它是一个简单的,仅限标题的模板引擎,可以满足您的需求。在那里你可以打电话
data["name"] = "world";
inja::render("Hello {{ name }}!", data); // Returns "Hello world!"
答案 6 :(得分:0)
string skeleton = "My name is {{name}}";
string placeholder = "{{name}}";
string::size_type pos = skeleton.find(placeholder);
while( pos != string::npos ) {
skeleton.replace(pos, placeholder.length(), "Gopalakrishnan");
pos = skeleton.find(placeholder, ++pos);
}
答案 7 :(得分:0)
这可能有点矫枉过正,但您也可以查看boost::spirit,更具体地说,看一下作为文本生成器的“业力”部分。
答案 8 :(得分:0)
如果您有许多占位符,例如,如果您希望自动展开字母的宏模板,则稍后将更容易维护,实施和扩展一些基本标记。 E.g
//pseudocode
foreach word in line
{
if word=={{name}} print getFromDB(name,entry)
else if word=={{address}} print getFromDB(address,entry)
..
..
else print word
/*
* to get rid of if-else-if tree, you can just check if starts with {{ and ends with }} and directly query the string against a db/map/hash
*/
}
但是,如果问题很简单,并且模板足够小,那就去找上面提到的答案之一。
答案 9 :(得分:0)
我为那些仍在寻找这样一个库的人创建了一个https://github.com/lexxmark/string_template。
stpl::string_template st("Hello {{name}}!");
st.set_arg("name", "World");
auto r = st.render();
EXPECT(r, "Hello World!");
它也有一些不错的自定义项。