C ++如何创建'bind'字符串文本替换方法?

Posted

技术标签:

【中文标题】C ++如何创建\'bind\'字符串文本替换方法?【英文标题】:C++ how to create 'bind' string text replacement method?C ++如何创建'bind'字符串文本替换方法? 【发布时间】:2011-11-02 07:42:34 【问题描述】:

所以我看sqlite3cpp wiki。他们有这么好的 API:

sqlite3pp::command cmd(db, "INSERT INTO contacts (name, phone) VALUES (:user, :phone)");
cmd.bind(":user", "Mike");
cmd.bind(":phone", "555-1234");
cmd.execute();

我想知道如何使用 boost 创建类似于常规 std::string 的 API?意思是

std::string str = "INSERT INTO contacts (name, phone) VALUES (:user, :phone)";
bind(str, ":user", "Mike");
bind(str, ":phone", "555-1234");

是否有可能用 boost 来创建这样的东西以及如何做到这一点?

【问题讨论】:

【参考方案1】:

可能:boost::algorithm::replace_all?或者boost::algorithm::replace_all_copy,如果您不想修改原始字符串。

【讨论】:

【参考方案2】:

替换字符串很容易,但执行一些类型安全且能很好地转换 SQL 的操作则略有不同。我们需要一个绑定器类,它可以通过传递的类型绑定并进行任何必要的转换。

首先,我们需要将std::type_info 包装起来,以便可以在哈希映射中使用:

class typeInfoWrapper

friend bool operator == (const typeInfoWrapper& l, const typeInfoWrapper& r);
private:
    const std::type_info& typeInfo_;

public:
    typeInfoWrapper(const std::type_info& info) : typeInfo_(info)  ;

    // hasher
    class hash
    
    public:
        size_t operator()(const typeInfoWrapper& typeInfo) const
        
            return typeInfo.typeInfo_.hash_code();
        ;
    ;  // eo class hash
;  // eo class typeInfoWrapper

bool operator == (const typeInfoWrapper& l, const typeInfoWrapper& r)

    return l.typeInfo_.hash_code() == r.typeInfo_.hash_code();
   // eo operator == 

接下来,我们需要类本身。我在这里使用 C++11,所以我将使用 lambdas。对于我们注册的每种类型,我们将注册一个函数,该函数接受一个字符串并以适合 SQL 的格式返回它。在此示例中,我为字符串注册了一个,为 int 注册了一个。字符串 one 只是将 ' 替换为 '' 并用引号本身返回它。 int 只返回自身,无需解析 SQL。

class binder

private:
    typedef std::function<std::string(std::string&)> ReplaceFunc;
    typedef std::tr1::unordered_map<typeInfoWrapper, ReplaceFunc, typeInfoWrapper::hash> ReplaceMap;
    typedef std::pair<typeInfoWrapper, ReplaceFunc> ReplacePair;
    ReplaceMap typeMap_;

public:
    binder()
    
        // add string and int for test purposes
        typeMap_.insert(ReplacePair(typeid(const char*), [](std::string& data) -> std::string
        
            // escape the "'" to prevent SQL injection
            boost::replace_all(data, "'", "''");
            return "'" + data + "'";
        ));

        typeMap_.insert(ReplacePair(typeid(int), [](std::string& data) -> std::string
        
            // for sql, this is easy, just return the value as is
            return data;
        ));
    ;


    // func
    template<class T>
    void bind(std::string& input, const std::string& expr, T data)
    
        ReplaceMap::const_iterator cit(typeMap_.find(typeid(T)));
        if(cit != typeMap_.end())
            boost::replace_all(input, expr, cit->second(boost::lexical_cast<std::string>(data)));
    ;  // eo bind
;  // eo class bind

如你所见,我们有绑定函数。

现在我们可以以类型安全的方式进行绑定了!

binder b;
std::string data = "SELECT * FROM table WHERE _user = :user AND _id = :id";
b.bind(data, ":user", "Moo-Juice");
b.bind(data, ":id", 32);

编辑:修复了一些错误。

【讨论】:

以上是关于C ++如何创建'bind'字符串文本替换方法?的主要内容,如果未能解决你的问题,请参考以下文章

在java中如何修改文本文件中的某一行的某些数据??

用C/C++实现字符串的创建,并进行查找与替换

如何创建用于写作的文本文件

c语言 如何读取中文字符串

替换函数 - 没有重载方法错误 C# - 试图删除字符串中的部分

创建 C 字符串的最佳方法