C++ стандартная замена для (s)printf

Я делаю серверное приложение на 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, изменятся во время выполнения. Это означает, что я не могу просто записать всю страницу в файл со строковыми значениями first, second, а также thirdпотому что эти значения будут меняться динамически.

Для первого запроса я отправлю страницу с first = "foo";тогда как во втором запросе я бы first = "anything else",

Кроме того, я мог бы просто вернуться к sscanf/sprintf от stdio.h и вставьте текст, который я хочу - мне просто нужно заменить пропуски строк на правильный формат (%s), прочитайте структуру HTML из файла и вставьте все, что я хотел.

Я хотел бы сделать это в C++, без функций библиотеки C, но я не мог понять, что использовать для этого. Каким будет стандартное решение C++ для этого?

4 ответа

Решение

Стандарт C++ не имеет прямого эквивалента (s)printfкак форматирование (s)printf сам. Тем не менее, существует множество библиотек форматирования, которые предоставляют эту функциональность, например, библиотека cppformat, которая включает в себя реализацию Python на C++. str.format и безопасно printf,

Тем не менее, я бы порекомендовал использовать вместо этого движок шаблонов, см. Фреймворк HTML C++, библиотека шаблонов, библиотека генератора HTML.

Или вы всегда можете заново изобрести колесо и написать свой собственный шаблонизатор, читая файл и заменяя некоторые заполнители аргументами.

Вы можете получить желаемый результат следующим образом:

  1. Сохраните статический HTML-файл в файле с заполнителями для динамического текста
  2. Прочитайте файл HTML в std::string
  3. Для каждого фрагмента динамического текста найдите его заполнитель в строке (std::string::find) и замените заполнитель на динамический текст (std::string::replace).
  4. Запишите измененную строку в конечный пункт назначения.

Как насчет:

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

Если вы не хотите использовать фреймворк, как подсказывают другие ответы (правильно), я думаю, вы можете черпать вдохновение из этой маленькой программы:

#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;
}
Другие вопросы по тегам