我正在尝试使用变量模板(这是第一次)来创建一个字符串替换函数。
实际上,我想创建一个函数(我们称之为Replace),该函数接受一个键值,用于根据Replace函数中提供的附加参数搜索和修改模板字符串。模板字符串包含使用字符串“%s”的占位符。
我的问题是,我不确定如何迭代变量模板参数......下面是一些示例代码。
const std::string FindOriginal(std::string Key)
{
if(Key == "Toon")
{
return "This is example %s in my program for Mr. %s.";
}
return "";
}
std::string Replace(std::string OriginalKey) {
return "";
}
template<typename First, typename ... Strings>
std::string Replace(std::string OriginalKey, First arg, const Strings&... rest)
{
const std::string from = "%s";
std::string the_string = FindOriginal(OriginalKey);
int i = 0;
size_t start_pos = the_string.find(from);
while(start_pos != std::string::npos)
{
// Ideally here I can somehow get the parameter at index i...
the_string.replace(start_pos, from.length(), rest[i]);
start_pos = the_string.find(from, start_pos);
i++;
}
Replace(rest...);
return the_string;
}
int main()
{
std::cout << Replace("Toon", "5", "Jimmy") << std::endl;
}
3条答案
按热度按时间js4nwp541#
如果你能访问C++17或更高版本,你的逻辑最好用fold expression来表达,它可以为包中的每个参数对你的字符串应用一个函数(一元右折叠):
卿卿如是说:
Live Demo(第一个字母)
本质上,我们对字符串调用
ReplaceOne
,用下一个变量参数替换"%s"
的一个示例,如果没有找到"%s"
,我们就返回不变的字符串。我们使用一元右折叠,以便从左到右处理参数,因为顺序很重要。
这种方法(实际上就是你的答案中的方法)的缺点是,你为每个变量参数调用
std::string::find
,这可能会搜索整个字符串。在最坏的情况下,字符串中甚至没有"%s"
的示例,结果,你为每个替换都搜索整个字符串。这是低效的;O(N * M)
,其中N
是字符串的长度,M
是参数包中的参数数。如果我们从
find
的最后一个结果开始重复调用find
,我们可以将时间复杂度降低到O(N)
。(另一种方法是将替换字符串存储在临时容器中,然后在this answer(现已删除)中建议的Stack Danny循环中迭代该字符串。
aiazj4mn2#
您可以:
rest
)进行递归调用。arg
以及递归调用返回的任何内容。我已经将所有这些逻辑放入另一个函数
ReplaceImpl
中,并让Replace
执行早期检查(例如,找到原始密钥,如果没有找到原始密钥,则返回)。Demo(https://godbolt.org/z/7zfGjx1P9)
u0sqgete3#
多亏了某人对通过递归调用工作的可变模板的评论,我设法修改了解决方案以获得期望的结果。基本上,我们将参数提供给一个模板化函数(GetModifiedString),该函数调用可变模板函数(ReplaceValue)。