#include <stdio.h>
#include <stdarg.h>
#include <string>
std::string format_arg_list(const char *fmt, va_list args)
{
if (!fmt) return "";
int result = -1, length = 256;
char *buffer = 0;
while (result == -1)
{
if (buffer) delete [] buffer;
buffer = new char [length + 1];
memset(buffer, 0, length + 1);
result = _vsnprintf(buffer, length, fmt, args);
length *= 2;
}
std::string s(buffer);
delete [] buffer;
return s;
}
std::string format(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
std::string s = format_arg_list(fmt, args);
va_end(args);
return s;
}
Paul Senzee on iOS/Android App and Game Development, Technology and sometimes Life
Thursday, May 18, 2006
Formatting std::string
The following snippet has been a part of my personal code library for years. It is useful for formatting a std::string in a traditional printf() way. For all its ills, printf/sprintf() is incredibly convenient. This code is for Win32. Minor modification is required for Unix.
Subscribe to:
Post Comments (Atom)
16 comments:
Very nice piece of code. Saved me some time. Many thanks!
Thanks, not exactly how I thought it would be solved. But it works. Thanks.
cool, but it seems that doest not support UNICODE.
std::string s(buffer); delete [] buffer; return s;
}
Won't that give problems? Isn't "s" created on the heap and no longer guaranteed when the function returns (although it will _probably_ be there , just cos it isn't overwritten yet (espeically in non-threaded programs))?
Does your compiler give warnigs? Did you run Lint on it?
Because the return type is [std::string] and not [std::string &] (or [std::string *]), it is return by value. So, upon return, it will create a copy of the stack variable s in the caller's scope.
So it's completely safe.
Keep in mind however, that this is not an efficient piece of code. It's brute force and requires a number of allocations. Still, it's convenient, and that's often more important than efficiency.
Regarding the earlier comment about not supporting unicode - that's true, but little modification is required for unicode support, such as using std::basic_string<wchar_t> instead of std::string and using the appropriate wide character formatting function.
Thanks. What a nice!
In visual Studio 2005, this code meets deprecate warning.
So, I replace _vsnprintf to _vsprintf_s
code :
result = _vsnprintf_s(buffer, length, _TRUNCATE, fmt, args);
As you say, it's not the most efficient piece of code, but it is just in turn of a very nice and simple usage, just what I was looking for...
Thank you very much!!
Thanks! This is great!
Exactly what I was looking for ...
Thank you !
Thanks a million!!
it's gcc ver..
http://blog.yurihan.net/entry/stdstring%EC%9D%98-formating-%EC%8B%9C%EB%B0%9C-%EB%82%9A%EC%98%80%EB%8B%A4
It's so great that std::string doesn't have formatting. Just another evidence that c++ designers hadn't coded a single line in ten years.
My expectation level for tr1 is even higher, it so promising that I'll probably change C++ for cobol, or something worse.
If you are using VC, the _vsctprintf function will give you the length need to store the resulting string, and you can get rid of the loop.
thanks a lot!
i'd just like to add one function to pass the first length of result to try :)
std::string format_arg_list(DWORD dwdResLenToTryFirst,const char *fmt, va_list args)
{
if(!fmt)return"";
int result=-1;
int length=dwdResLenToTryFirst;
char *buffer=0;
while(result==-1)
{
if(buffer)delete[]buffer;
buffer=new char[length+1];
memset(buffer,0,length+1);
result=_vsnprintf(buffer,length,fmt,args);
length *= 2;
}
std::string s(buffer);
delete[]buffer;
return s;
}
std::string format(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
std::string s=format_arg_list(256,fmt,args);
va_end(args);
return s;
}
std::string formatLen(DWORD dwdResLenToTryFirst,const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
std::string s=format_arg_list(dwdResLenToTryFirst,fmt,args);
va_end(args);
return s;
}
Thank you so much to Senzee and Sean - your code / comments have helped me solve my evil problem!! There is very little on the web about getting va_list into std::string (or about getting the length of string returned from va_list), so this code is soooooooo helpful - thank you thank you, thank you!!!!
Hey, thank you a lot for sharing this article with us. I can’t say, how grateful we are to read this. Also, I would love to check out other articles
Post a Comment