c++中Python风格的字符串替换

Python style String replacement in C++

本文关键字:字符串 替换 风格 Python c++      更新时间:2023-10-16

在回答Python中的字符串替换是如何工作的问题时显示在这个答案中。

我相信它的工作原理是

string toSql(string table, string field, string value)
{
    string out;
    return out = "INSERT INTO %s (%s) VALUES (%s)" % (table,field,value);
}

在c++中是否有类似的方法可以在没有文件i/o的情况下做到这一点?

我正试图用这个来形成一个查询SQLite数据库。

编辑

我避免使用外部库。提高交货

同样,输入是由程序而不是用户提供的。所以我不相信我会遇到注入漏洞

为了回答所问的问题,习惯的c++方法是使用std::ostringstream。请注意,这个流类是由内存支持的,而不是磁盘上的文件。

(还有snprintf()选项,它看起来更接近Python字符串格式化,但具有C风格的接口,除非有充分的理由,否则不应该从现代c++中使用。如果你在写c++,那就写c++,而不是C)

std::string toSql(
    std::string const & table,
    std::string const & field,
    std::string const & value
) {
    std::ostringstream s;
    s << "INSERT INTO " << table
      << " (" << field << ") VALUES (" << value << ")";
    return s.str();
}

但是,要注意,如果任何参数是未经处理的用户输入,那么可能会使您的程序受到SQL注入攻击。您应该使用一个准备好的语句(sqlite3_prepare()后面跟着sqlite3_bind_...())来将value绑定到语句中——但是您仍然必须从tablefield参数中构建字符串,因为数据库对象名称不能以这种方式绑定。


您可以像这样"以c++的方式"使用预处理语句(std::unique_ptr需要c++ 11或更高版本):

#include <memory>
#include <string>
#include <sqlite3.h>
// Deleter functor to properly sqlite3_finalize() statements when we
// are done with them.
struct sqlite3_stmt_deleter
{
    void operator()(sqlite3_stmt * p) const {
        sqlite3_finalize(p);
    }
};
// Type alias for a std::unique_ptr that uses the above functor to
// clean up statements.
using sqlite3_prepared_stmt = std::unique_ptr<sqlite3_stmt, sqlite3_stmt_deleter>;
sqlite3_prepared_stmt prepare(sqlite3 * db, std::string const & sql)
{
    sqlite3_stmt * stmt = nullptr;
    // Note that we don't allow the caller to see any error information. A
    // proper wrapper will want to throw if the return isn't SQLITE3_OK.
    sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr);
    return sqlite3_prepared_stmt(stmt);
}
void example() {
    auto insert_stmt = prepare(
        your_db,
        "INSERT INTO foo (bar) VALUES (?)");
    std::string value{"baz"};
    // Bind value to the ? in the prepared statement
    sqlite3_bind_text(insert_stmt.get(), 1, value.c_str(), -1, SQLITE_TRANSIENT);
    // Execute statement.
    sqlite3_step(insert_stmt.get());
    // Reset statement so it can be used again with bind/step.
    sqlite3_reset(insert_stmt.get());
    // std::unique_ptr destructor will call sqlite3_finalize() for us.
}

使用此代码,您可以将sqlite3_prepared_stmt存储在某个地方并重用它。

看一下printf函数族。

string toSql( string table, string field, string value )
{
  char buffer[ 100 ];
  size_t length = sprintf( buffer, "INSERT INTO %s (%s) VALUES (%s)", table.data( ), field.data( ), value.data( ) );
  if ( lenght < 0 )
  {
      //increase buffer size and try again.
  }
  printf("SQL Query = '%s'n", buffer );
  return buffer
}