A little prototype for an idea I had to use some C++11 features to make printf a bit more safe.
#include <initializer_list> #include <stdio.h> struct val_t { enum type_t { e_int, e_float, e_cstr } type_; union { int int_; float float_; const char * cstr_; }; val_t( int v ) : type_( e_int ), int_ ( v ) {} val_t( float v ) : type_( e_float ), float_( v ) {} val_t( const char * v ) : type_( e_cstr ), cstr_ ( v ) {} }; bool print( const char * fmt, std::initializer_list<val_t> vargs ) { // itterate over the strings for ( ; *fmt;fmt++ ) { // check for format specifier if ( *fmt == '%' ) { // argument index int index = fmt[1] - '0'; if (index < 0 || index >= int(vargs.size())) return false; // access argument const val_t & v = vargs.begin()[index]; switch (v.type_) { case (val_t::e_int ): printf("%d", v.int_ ); break; case (val_t::e_float): printf("%f", v.float_ ); break; case (val_t::e_cstr ): printf("%s", v.cstr_ ); break; default: return false; } // skip argument index fmt++; } else { // output character putchar(*fmt); } } return true; } int main( void ) { print( "%0 and %1, %0, %2", { 3, 0.1f, "hello world" } ); getchar(); return 0; }
The output is:
3 and 0.100000, 3, hello world