(This answer takes into account OP's comment "I only intended %s with the modifiers and such")
Note that it is possible to build your own va_list, however the details of this are implementation-specific and extremely non-portable, so I'm not going to go down that road.
This is arguably the simplest way to do it:
if ( argc == 1 ) snprintf(buf, sizeof buf, format, argv[0]); else if ( argc == 2 ) snprintf(buf, sizeof buf, format, argv[0], argv[1]); else if ( argc == 3 ) snprintf(buf, sizeof buf, format, argv[0], argv[1], argv[2]); // ...etc, so far as you want
You work out argc by looping through argv until you find NULL (argv[argc] is guaranteed to be NULL).
This code uses a fixed buffer size char buf[MAX_LENGTH];, and then you can strdup to create your return value or whatever. If you want to avoid the MAX_LENGTH limitation then you have to call snprintf twice for each case: once to find out the length required; then malloc, then call it again to do the actual printing.
If you would prefer a less cut-and-paste'y version there is an outline of the algorithm you will need:
- Find
argc - Tokenize
format. (If you are writing the code that generates format, you could just supply a list of tokens instead of a string) - For each token, Call
snprintf(buf + upto, space_remaining, token, argv[i++]);
While doing this, you'll need to keep track of how much of buf you have used up (and realloc it at each step, if you are going to use the double-snprintf method). Also check you stop before reaching argc.
formatyourself, which is a similar amount of work to just fully implementingsprintfyourself, or doctoring a freeware implementation ofsprintf. However, if the calling function can passva_list argsinstead ofchar **args, then you can usevsprintf(or preferably,vsnprintf).%d,%f,%-20.15s, etc. (and if so, how you are going to pass the args in). If your function only expects to handle%sexactly and nothing else, then this is possible.%swith the modifiers and such.