3

I've been using C# for the last few years, and right now I'm trying to write some C. I'm trying to format a string from an array of values. The "format string" and the array aren't known until runtime.

In C# I can invoke a variadic function with an array, like this:

using System;

namespace ConsoleApplication7
{
    class Program
    {
        static void Main(string[] args)
        {
            string formatString = "{0}.{1}.{2}.{3}";
            string[] formatValues = new[] { "a", "b", "c", "d" };

            string formatted = String.Format(formatString, formatValues);

            //Do something with formatted (now looks like "a.b.c.d")
        }
    }
}

In C I've got this:

#include <stdio.h>
#include <malloc.h>

    int main(int argc, char* argv[])
    {
        char *formatString = "%s.%s.%s.%s";
        char *formatValues[] = {"a","b","c","d"};

        char *buffer = (char*)malloc(100 * sizeof(char));

        //This doesn't work.....
        sprintf(buffer, formatString, formatValues);

        //... buffer is junk

        return 0;
    }

How can I do this in C?

(Is there a nice function in the C standard library I can use to help me, or perhaps, is there a way to call a varargs function with an array?)

Please note, the number of arguments will never be greater than the length of the array I have. And the types will always be strings. So I might have

char *formatString = "My Formatted String %s.%s.%s";
char *formatValues[] = {"a","b","c","d","e"};

But I'll never have too few %s.

Note: the C has to work on GCC for Linux, and Visual Studio for Windows (C90).

5
  • 2
    Take a look at vsprintf - msdn.microsoft.com/en-us/library/28d5ce15(v=vs.71).aspx Commented Feb 10, 2013 at 22:51
  • What happens when you compile and run the code you gave? Do you get any errors? Commented Feb 10, 2013 at 22:55
  • I don't think what you want is possible in one step. You might want to run a loop and sprintf() and then strcat(). Also, please use snprintf() instead of sprintf() - it somewhat decreases the possibilty of buffer overrun errors. Commented Feb 10, 2013 at 22:55
  • @Code-Guru It runs but the buffer contains junk (in the debugger it's dX¥.(null).(null).) Commented Feb 10, 2013 at 23:01
  • 1
    @LeorA Smashing, thank you, vsprintf seems to work if I cast the formatValues array to a vs_list. I'll post that as an answer and see if there's some feedback. Commented Feb 10, 2013 at 23:03

2 Answers 2

2

I don't think C provides a standardized way to do this. If you understood the internal implementation of <stdarg.h> on your system, it would probably be possible to kludge up a system-specific solution involving vprintf(3), but I have a different, conforming kludge for you...

Something that would work would involve declaring an array of some large size, set the values that you have, and then just pass every element of the array at the call site, regardless of whether they are set.

char *a[5]; // or a[50], whatever you need

// assign the elements you actually have

printf(format_string, a[0], a[1], a[2], a[3], a[4], a[5]);
Sign up to request clarification or add additional context in comments.

1 Comment

This is really clever. It's a great solution to my problem. Thanks.
0

The only type of array sprintf accepts is a null-terminated array of chars (ie a string). This should work:

#include <stdio.h>
#include <malloc.h>
int main(int argc, char* argv[])
{
    char *formatStrings[]={"%s","%s","%s","%s"};
    char *buffer= (char*)malloc(100 * sizeof(char));
    char *formatValues[]={"a","b","c","d"};
    char *endofBuffer=buffer;
    int valueCount=4;
    int i;
    for (i=0; i<valueCount; ++i)
    {
        endofBuffer+=sprintf(endofBuffer, formatStrings[i], formatValues[i]);
        if (i<valueCount-1)
            endofBuffer+=sprintf(endofBuffer, "%c", '.');
    }
    printf("%s\n",buffer);
    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.