2013-01-02 1 views
2

Я выполняю серверное приложение на C++ и предоставляет HTML-страницу в качестве ответа на запросы HTTP.Стандартная замена C++ для (ов) printf

Проблема заключается в том, что, на данный момент, моя веб-страница написана как константной строки в моем коде, и я вставлять другие строки с помощью << оператора и 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++ ?

+1

Вы перезапись на ' \ п 'часть. – chris

+0

@chris Спасибо, что указали это, но на самом деле это не влияет на проблему. Во всяком случае, я редактировал код. – Rubens

+0

@Rubens Я не уверен, что понял предложение «Случается, хотя я не могу просто заполнить содержимое в файле, потому что данные, смешанные с структурой HTML, будут меняться во время выполнения». - Не могли бы вы прояснить? Чего вы пытаетесь достичь? –

ответ

4

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

Как бы то ни было, я рекомендую использовать вместо этого шаблонный движок, см. C++ HTML template framework, templatizing library, HTML generator library.

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

+1

http://en.cppreference.com/w/cpp/io/c/fprintf - Технически стандартный C++ включает в себя такие вещи, как 'sprintf'. Тем не менее, использование шаблона является хорошим предложением. –

+0

@NateKohl Но это в 'stdio.h' или в' iostream'? – Rubens

+0

Это в (также ), а не . Но это все еще часть C++. –

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

Я думаю, что OP хочет прочитать HTML-шаблон из файла, а затем заменить аргументы. – vitaut

+0

Это то, что я делаю сейчас; Я хотел бы избавиться от этого * html-кода * на C++, в значительной степени используя * placeholders *, но я хотел иметь этот объект из некоторого стандартного метода C++ - например, стандартного 's 's printf'. – Rubens

2

Вы можете получить желаемый результат:

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

Это именно то, что я планировал делать; Я просто хотел бы знать, могу ли я просто упростить замену '% s' на' (s) printf', но, как сказал @vitaut, для него, похоже, нет * прямого эквивалента *. – Rubens

+0

@Rubens: Вы все равно можете использовать printf, если хотите. – vitaut

+0

@vitaut Да, я знаю, так же как я мог бы использовать 'printf' для некоторой работы' std :: cout'; Мне просто интересно, было ли что-то более стандартное для C++ * стандартизировано для этого. Кажется, мне придется придерживаться 'sprintf', anyway \ = – Rubens

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; 
} 
+0

Энди, я очень благодарен за вашу оперативность, но это была реализация «Барта ван Ингена Шенау»; моя воля была действительно знать, есть ли какая-то ценная функция из C++, скрытая, возможно, в 'iostream', которая будет делать то же самое, что и prints's. +1 за ваше терпение и оперативность. Извините, если я не был достаточно ясен с самого начала. – Rubens

+0

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

+1

BTW, Boost.Format может быть чем-то вроде того, что вы ищете. Это не так эффективно, как 'printf', но он делает то же самое и обеспечивает безопасность типов. –