(s)printf的C ++标准替代品

时间:2013-01-02 17:01:28

标签: c++ string string-formatting iostream stdio

我正在用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"

另外,我可以直接从sscanf/sprintf返回stdio.h并插入我想要的文字 - 我只需要用正确的格式替换字符串空白(%s ),从文件中读取HTML结构,并插入我想要的任何内容。

我想在没有C库函数的C ++中这样做,但我无法弄清楚要用它来做什么。这个C ++ 标准解决方案是什么?

4 个答案:

答案 0 :(得分:4)

标准C ++没有直接等效于(s)printf - 就像(s)printf本身以外的格式一样。但是,有许多格式库可以提供此功能,例如cppformat库包含Python的str.format和安全printf的C ++实现。

那就是说,我建议改用模板引擎,参见 C++ HTML template framework, templatizing library, HTML generator library

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

答案 1 :(得分:2)

怎么样:

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);

答案 2 :(得分:2)

您可以获得如下所需的结果:

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

答案 3 :(得分:1)

如果您不想使用框架作为其他答案(正确)建议,我想您可以从这个小程序中获取灵感:

#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;
}