Reputation: 14778
I'm doing a server application in C++, and it provides an HTML page as response to HTTP requests.
The problem is that, currently, my webpage is written as a constant string in my code, and I insert other strings using <<
operator and std::stringstream
, still during the writing of the string itself. See the example to get it clearer:
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>";
Happens though I cannot simply stuff the contents in a file, because the data mixed with the HTML structure will change during the execution. This means I can't simply write the entire page in a file, with the string values of first
, second
, and third
, because these values will change dynamically.
For the first request I'd send the page with first = "foo";
, whereas in the second request I'd have first = "anything else"
.
Also, I could simply go back to sscanf/sprintf
from stdio.h
and insert the text I want -- I'd just have to replace the string gaps with the proper format (%s
), read the HTML structure from a file, and insert whatever I wanted.
I'd like to do this in C++, without C library functions, but I couldn't figure out what to use to do this. What would be the C++ standard solution for this?
Upvotes: 2
Views: 6444
Reputation: 55605
Standard C++ doesn't have a direct equivalent to (s)printf
-like formatting other than (s)printf
itself. However, there are plenty of formatting libraries that provide this functionality, like the cppformat library that includes a C++ implementation of Python's str.format
and safe printf
.
That said, I'd recommend using a template engine instead, see C++ HTML template framework, templatizing library, HTML generator library .
Or you can always reinvent the wheel and write your own template engine by reading a file and replacing some placeholders with arguments.
Upvotes: 4
Reputation: 126502
If you don't want to use a framework as other answers (correctly) suggest, I guess you can take inspiration from this little program:
#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;
}
Upvotes: 1
Reputation: 15768
You can get the desired result like this:
std::string
std::string::find
) and replace the placeholder with the dynamic text (std::string::replace
).Upvotes: 2
Reputation: 1777
What about:
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>";
}
And you can call it like this:
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);
Upvotes: 2