2

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

问题是,目前,我的网页在我的代码中被写为一个常量字符串,我使用<<运算符 and插入其他字符串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/sprintffromstdio.h并插入我想要的文本——我只需要用正确的格式 ( %s) 替换字符串间隙,从文件中读取 HTML 结构,然后插入我想要的任何内容。

我想用 C++ 做这个,没有 C 库函数,但我不知道用什么来做这个。对此的 C++标准解决方案是什么?

4

4 回答 4

4

标准 C++ 除了自身之外,没有直接等效于(s)printf-like 的格式。(s)printf但是,有很多格式库提供此功能,例如cppformat库,其中包含 Python 的 C++ 实现str.format和安全的printf.

也就是说,我建议改用模板引擎,请参阅 C++ HTML 模板框架、模板化库、HTML 生成器库

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

于 2013-01-02T17:17:22.183 回答
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);
于 2013-01-02T17:19:29.437 回答
2

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

  1. 将静态 HTML 存储在一个文件中,其中包含动态文本的占位符
  2. 将 HTML 文件读入std::string
  3. 对于每段动态文本,在字符串 ( std::string::find) 中找到其占位符,并将占位符替换为动态文本 ( std::string::replace)。
  4. 将修改后的字符串写入最终目的地。
于 2013-01-02T17:20:01.917 回答
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;
}
于 2013-01-02T17:38:36.963 回答