Introduction
I've never been a big fan of variable argument lists for functions, if only for testing and verification's sake, and I'm still not quite sure where exactly I stand on the issue, but it's hard to argue that these functions don't come in handy when your only debugger is a hyperterm.
I recently had a need to send formatted text to both a terminal window and a log file while performing some integration tasks. This was previously done by formatting a string
(using sprintf
) and sending that string
(via printf
) to a terminal and then logging the string
to a file. OK, no big deal on the surface, but when you're doing this:
char buff[256] = {'\0'};
sprintf(buff, "test: %d %s\n", nTest, szTest);
printf(buff);
_log << buff;
for the 30th time, it gets annoying. (Not to mention there is absolutely no guarantee against buffer overruns... nothing like introducing bugs into the system with your debugging code!)
The Solution
So I decided to come up with a solution to my ordeal, and here is the result (with some necessary changes courtesy of George's comments below):
std::string format(const char *fmt, ...)
{
using std::string;
using std::vector;
string retStr("");
if (NULL != fmt)
{
va_list marker = NULL;
va_start(marker, fmt);
size_t len = _vscprintf(fmt, marker) + 1;
vector<char> buffer(len, '\0');
int nWritten = _vsnprintf_s(&buffer[0], buffer.size(), len, fmt, marker);
if (nWritten > 0)
{
retStr = &buffer[0];
}
va_end(marker);
}
return retStr;
}
Conclusion
Well, that's really all there is to it. Nothing very elaborate, but it does make for cleaner (and safer) code (compared to the first example anyway). Perhaps it can be of some value in your next project.
History
- 9th August, 2006: Initial post