Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

How to Format a String

3.20/5 (21 votes)
9 Aug 2006CPOL1 min read 1   623  
This article illustrates how to format a std::string using a variable argument list similar to CString's Format.

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:

C++
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):

C++
std::string format(const char *fmt, ...) 
{ 
   using std::string;
   using std::vector;

   string retStr("");

   if (NULL != fmt)
   {
      va_list marker = NULL; 

      // initialize variable arguments
      va_start(marker, fmt); 
      
      // Get formatted string length adding one for NULL
      size_t len = _vscprintf(fmt, marker) + 1;
               
      // Create a char vector to hold the formatted string.
      vector<char> buffer(len, '\0');
      int nWritten = _vsnprintf_s(&buffer[0], buffer.size(), len, fmt, marker);    

      if (nWritten > 0)
      {
         retStr = &buffer[0];
      }
            
      // Reset variable arguments
      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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)