Created
July 3, 2019 08:19
-
-
Save svenk/6cb0e979e4c54901f1844c375d952ffc to your computer and use it in GitHub Desktop.
Convenient C's printf in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is a buffer-overflow-safe version of sprintf | |
// source: http://stackoverflow.com/a/69911 | |
// if you need something more mature, consider https://github.com/fmtlib/fmt | |
// the advantage of this snippet is that it can be really easily added to smallish | |
// codes/libraries. Usage is like C's vprintf et al. but with a C++ std::string as a result. | |
std::string vformat (const char *fmt, va_list ap) { | |
// Allocate a buffer on the stack that's big enough for us almost | |
// all the time. Be prepared to allocate dynamically if it doesn't fit. | |
size_t size = 1024; | |
char stackbuf[1024]; | |
std::vector<char> dynamicbuf; | |
char *buf = &stackbuf[0]; | |
va_list ap_copy; | |
while (1) { | |
// Try to vsnprintf into our buffer. | |
va_copy(ap_copy, ap); | |
int needed = vsnprintf (buf, size, fmt, ap); | |
va_end(ap_copy); | |
// NB. C99 (which modern Linux and OS X follow) says vsnprintf | |
// failure returns the length it would have needed. But older | |
// glibc and current Windows return -1 for failure, i.e., not | |
// telling us how much was needed. | |
if (needed <= (int)size && needed >= 0) { | |
// It fit fine so we're done. | |
return std::string (buf, (size_t) needed); | |
} | |
// vsnprintf reported that it wanted to write more characters | |
// than we allotted. So try again using a dynamic buffer. This | |
// doesn't happen very often if we chose our initial size well. | |
size = (needed > 0) ? (needed+1) : (size*2); | |
dynamicbuf.resize (size); | |
buf = &dynamicbuf[0]; | |
} | |
} | |
std::string sformat(const char *fmt, ...) { | |
va_list ap; | |
va_start (ap, fmt); | |
std::string buf = vformat (fmt, ap); | |
va_end (ap); | |
return buf; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment