一行中的多个字符串替换
Posted
技术标签:
【中文标题】一行中的多个字符串替换【英文标题】:Multiple string replaces in one line 【发布时间】:2018-09-13 09:58:51 【问题描述】:我有一个 sql 语句,为了调试,我想打印它。该语句包含占位符,我想在打印之前将占位符填充到一个指令行中。这是有效的还是 UB?
std::string query("SELECT A, B FROM C WHERE D = ? and E = ?;");
std::cout << query.replace(query.find("?"), 1, "123").replace(query.find("?"), 1, "234") << std::endl;
是指令的顺序
-
查找第一个问号的位置
替换查询中的第一个字符串
在第一次替换后查找第二个问号的位置
替换查询中的第二个字符串
保证或者有可能两个find
操作都可以在replace
操作之前调用
-
查找第一个问号的位置
在第一次替换之前找到第二个问号的位置
替换查询中的第一个字符串
替换查询中的第二个字符串
我问是因为:
几乎所有 C++ 运算符的操作数的求值顺序 (包括函数参数的求值顺序 函数调用表达式和计算的顺序 任何表达式中的子表达式)未指定。编译器可以 以任何顺序计算操作数,并且当 再次计算相同的表达式。
编辑: 本项目不能使用第三方依赖。
【问题讨论】:
将它包裹在 lambda 中是否仍然符合一个衬垫的条件?std::cout << [&] query.replace(query.find("?"), 1, "123"); query.replace(query.find("?"), 1, "234"); return query; () << std::endl;
@KillzoneKid:问题不在于找到一个可行的衬里,而在于了解这是否有效或 UB 并避免未来的错误。但我喜欢使用 lambdas 的想法。
【参考方案1】:
在query.replace(query.find("?"), 1, "123").replace(query.find("?"), 1, "234")
query.find("?")
彼此未排序。
所以结果在可能的序列之间是不可预测的。
【讨论】:
未排序或不确定排序? @Deduplicator:可能因编译器而异,甚至因运行不同而异。 没有。它是由标准定义的。前者比后者受限制更少,我认为是后者。两者都允许从一个运行/编译器/版本到下一个版本的变化。【参考方案2】:我在评估顺序规则中找不到任何严格指定链接函数的函数参数顺序的内容。也就是说,在您的情况下,您可以知道:
第一个replace
在第二个之前排序,因为第二个是对其返回值进行操作
每个find
调用都在使用其返回值作为参数的replace
之前排序
但是您想要的是第一个 replace
在第二个 find
之前排序,并且没有这样的保证。参考规则见here。
【讨论】:
【参考方案3】:您可以多次使用boost::algorithm::replace_first
:
#include <boost/algorithm/string/replace.hpp>
#include <iostream>
#include <string>
int main()
std::string query("SELECT A, B FROM C WHERE D = ? and E = ?;");
for(auto replacement : "123", "1")
boost::algorithm::replace_first(query, "?", replacement);
std::cout << query << '\n';
请注意,这种简单的字符串替换不适用于需要引用的替换字符串。
【讨论】:
boost
不是第三方依赖吗?
它是第三方依赖,我们不能使用boost,因为我们使用动态链接boost的库,我们不知道版本和构建标志。
@ThomasSablik boost::algorithm::replace_first
在标头中实现,不需要链接 boost 共享/静态库。尽管如此,这可能会导致您动态加载的未知增强版本违反 ODR。以上是关于一行中的多个字符串替换的主要内容,如果未能解决你的问题,请参考以下文章