printf的c++标准替换

C++ standard replacement for (s)printf

本文关键字:替换 标准 c++ printf      更新时间:2023-10-16

我正在用c++做一个服务器应用程序,它提供了一个HTML页面作为对HTTP请求的响应。

问题是,目前,我的网页在我的代码中被写为常量字符串,我使用<<操作符和std::stringstream插入其他字符串,仍然在编写字符串本身。下面的例子更清楚:

std::string first("foo");
std::string second("bar");
std::string third("foobar");
std::stringstream ss;
ss << "<html>n"
    "<head>n"
    "<title>Bitches Brew</title>n"
    "</head>n"
    "<body>n"
    "First string: "
    << first << "n"
    "Second string: "
    << second << "n"
    "Third string: "
    << third << "n"
    "</body>n"
    "</html>";

发生了,尽管我不能简单地将内容塞进文件中,因为与HTML结构混合的数据在执行过程中会发生变化。这意味着我不能简单地用firstsecondthird的字符串值将整个页面写入一个文件中,因为这些值会动态变化。

对于第一个请求,我将使用first = "foo";发送页面,而在第二个请求中,我将使用first = "anything else"

同样,我可以简单地从stdio.h回到sscanf/sprintf并插入我想要的文本——我只需要用适当的格式(%s)替换字符串空白,从文件中读取HTML结构,然后插入我想要的任何内容。

我想在c++中做到这一点,没有C库函数,但我不知道该用什么来做到这一点。c++ 标准解决方案是什么?

标准c++除了(s)printf本身没有直接等价于(s)printf的格式。但是,有很多格式化库提供此功能,例如cppformat库包含Python的str.format和安全的printf的c++实现。

也就是说,我建议使用模板引擎c++ HTML模板框架,模板库,HTML生成器库。

或者你可以重新发明轮子,通过读取文件并用参数替换一些占位符来编写自己的模板引擎。

怎么样:

void RenderWebPage(std::stringstream& ss, std::string& first, std::string& second, std::string& third)
{
    ss << "<html>n"
        "<head>n"
        "<title>Bitches Brew</title>n"
        "</head>n"
        "<body>n"
        "First string: "
        << first << "n"
        "Second string: "
        << second << "n"
        "Third string: "
        << third << "n"
        "</body>n"
        "</html>";
}

你可以这样命名它:

std::stringstream ss;
std::string first("foo");
std::string second("bar");
std::string third("foobar");
RenderWebPage(ss, first, second, third);
first = "anything else";
RenderWebPage(ss, first, second, third);
second = "seconds too";
RenderWebPage(ss, first, second, third);

您可以像这样得到想要的结果:

  1. 将静态HTML存储在一个文件中,为动态文本使用占位符
  2. 读取HTML文件到std::string
  3. 对于每一个动态文本,在字符串(std::string::find)中找到它的占位符,并用动态文本(std::string::replace)替换占位符。
  4. 将修改后的字符串写入最终目标。

如果你不想像其他答案(正确)建议的那样使用框架,我想你可以从这个小程序中获得灵感:

#include <iostream>
#include <map>
using namespace std;
string instantiate_html(string const& templateHTML, map<string, string> const& replacements)
{
    string outputHTML = templateHTML;
    for (auto& entry : replacements)
    {
        string placeholder = "<$" + entry.first + "$>";
        size_t it = outputHTML.find(placeholder);
        if (it != string::npos)
        {
            outputHTML.replace(it, placeholder.size(), entry.second);
        }
    }
    return outputHTML;
}
int main()
{
    map<string, string> replacements;
    replacements["name"] = "Mark";
    replacements["surname"] = "Brown";
    // Normally you would read this string from your template file
    string templateHTML = "<html><body><$name$><$surname$></body></html>";
    string outputHTML = instantiate_html(templateHTML, replacements);
    cout << outputHTML;
    return 0;
}