首頁 > 軟體

更優雅的C++字串格式化實現方法詳解

2023-10-16 22:01:02

背景

在用C++編寫程式碼時,經常需要用到字串拼接及格式化,尤其是在拼寫sql語句時,目前大部分sql拼接方式都是通過ostringstream流一點一點拼接的,程式碼可讀性很差而且很容易拼接錯誤

    ostringstream sqlstr;
    sqlstr << "insert into virtual_item_info(id, platform, typeid, name, icon_url, act_url, "
              "desc_text, vm_typeid, vm_price, val_typeid, val_count, priority, show_type, param, "
              "combo, area, "
              "onshelf_time, offshelf_time, status, show_url, svga_url, mp4_url, remarks_info, "
              "shading_url, utime, has_green_dot, act_id, "
              "act_name, act_icon, act_name_lang_id, act_start_time, act_end_time, item_level, "
              "distribute_src, buy_to_use_duration, noble_lvl, name_lang_id, desc_lang_id, "
              "target_whitelist_id, target_whitelist_type, is_cp_shareable, act_link_type, "
              "act_show_type, item_lang_code)"
           << "values(" << item.id << "," << item.platform << "," << item.atypeid << ",'"
           << EscapeString(item.name) << "','" << EscapeString(item.iconurl) << "','"
           << EscapeString(item.actUrl) << "','" << EscapeString(item.desctext) << "',"
           << item.vmtypeid << "," << item.vmprice << "," << item.valtypeid << "," << item.valcount
           << "," << item.priority << "," << item.showType << ",'" << EscapeString(item.param)
           << "'," << item.isCombo << ",'" << EscapeString(item.area) << "',"
           << item.onshelftime << "," << item.offshelftime << "," << item.status << ",'"
           << EscapeString(item.showUrl) << "','" << EscapeString(item.svgaUrl) << "','"
           << EscapeString(item.mp4Url) << "','" << EscapeString(item.remarksInfo)
           << "', '" << EscapeString(item.shadingUrl) << "', " << butil::gettimeofday_s()
           << "," << item.hasGreenDot << ",'" << EscapeString(item.actId) << "','"
           << EscapeString(item.actName) << "','" << EscapeString(item.actIcon) << "','"
           << EscapeString(item.actNameLangId) << "'," << item.actStartTime << ","
           << item.actEndTime << "," << item.itemLevel << "," << item.distributeSrc << ","
           << item.buyToUseDuration << "," << item.nobleLevel << ",'"
           << EscapeString(item.nameLangId) << "','" << EscapeString(item.descLangId)
           << "','" << EscapeString(item.targetGroupWhiteListId) << "',"
           << item.targetGroupWhiteListType << "," << item.isCpShareable << "," << item.actLinkType
           << "," << item.actShowType << ",'" << EscapeString(item.itemLangCode) << "')";

優化

參考python字串格式化方式

"{} {}".format("hello", "world")

先寫出完整的字串,在需要替換的位置通過預留位置{}保留, 最後將預留位置替換為指定的引數

實現

本質是基於遞迴依次將字元轉中的預留位置{}替換為對應的引數

class StringUtil {
private:
    // 遞迴出口
    static void BuildFormatString(std::ostringstream& builder,
                                  const std::string& fmt_spec,
                                  std::string::size_type idx) {
        builder.write(fmt_spec.data() + idx, fmt_spec.size() - idx);
    }


    template <typename T, typename... Types>
    static void BuildFormatString(std::ostringstream& builder,
                                  const std::string& fmt_spec,
                                  std::string::size_type idx,
                                  const T& first,
                                  const Types&... args) {
        auto pos = fmt_spec.find_first_of("{}", idx);a
        if (pos == std::string::npos) {
            builder.write(fmt_spec.data() + idx, fmt_spec.size() - idx);
            return;
        }

        builder.write(fmt_spec.data() + idx, pos - idx);
        builder << first;
        BuildFormatString(builder, fmt_spec, pos + 2, args...);
    }

public:
    /**
    * C++實現python風格字串格式化
    */
    template <typename... Types>
    static std::string FormatString(const std::string& fmt_spec, const Types&... args) {
        std::ostringstream builder;
        BuildFormatString(builder, fmt_spec, 0, args...);
        return builder.str();
    }
};

使用

uint32_t ts = butil::gettimeofday_s();
string sql_formattor =
        "insert into tbl_user_relation_info(uid, gift_id, batch_id, relation_id, crc32_relation_id, status, peer_uid, relation_create_time, create_time, update_time, order_id) values({}, {}, {}, '', 0, 0, 0, 0, {}, {}, '{}')";
string sql = StringUtil::FormatString(sql_formattor, uid, giftId, batchId, ts, ts, orderId);

到此這篇關於更優雅的C++字串格式化實現方法詳解的文章就介紹到這了,更多相關C++字串格式化內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com