Thread: How to pass an array of strings as a function argument?

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    158

    How to pass an array of strings as a function argument?

    I'm trying to create a simple function that will draw a menu with borders around it, but the options in the menu depend on what the menu is for. I may have 3 options in one menu and I might have 10 options in a different one.

    I'm declaring an array of strings for the menu options like this:
    Code:
    char *menuops[] = {"Option 1", "Option 2"};
    Counting how many options I have like this:
    Code:
    int nOps = sizeof(menuops) / sizeof(char *);
    Then, creating a for loop and printing this menu options with the the borders is easy. Now the real problem... I want this to be in a function where I can call that function and pass as argument the variable menuops, cause in this case I have "Option 1" and "Option 2" but on a difference case I may have more options.

    How can I achieve that?

  2. #2
    Lean Mean Coding Machine KONI's Avatar
    Join Date
    Mar 2007
    Location
    Luxembourg, Europe
    Posts
    444
    Just the same way as you would pass a pointer to another variable, just that in this case, you're passing a pointer to an array. What you want is the following:

    Code:
    void testFunction(char **myOptions, int options)
    {
        int i;
        for (i =0; i < options; i++)
            printf("Option &#37;d: %s\n", i+1, myOptions[i]);
    }
    
    int main(void)
    {
        char *menuops[] = {"Option 1", "Option 2"};
        testFunction(menuops, 2);
        return 0;
    }
    Please note that I've chosen to pass the number of options as an argument to the function, since myOptions is a pointer itself, sizeof(myOptions) would only return 4 which gives no indication about the number of elements.

    You can also wrap it all into one structure, like this:
    Code:
    typedef struct {
        char **values;
        int size
    } options;
    and then only pass the structure as parameter. Unfortunately, in this case, the initialization of the structure is a little harder than what you did.

  3. #3
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    pass menuops and nOps as parameters
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  4. #4
    Lean Mean Coding Machine KONI's Avatar
    Join Date
    Mar 2007
    Location
    Luxembourg, Europe
    Posts
    444
    I was thinking that it would be nice to somehow have one function to initialize all the options and to regroup them in one structure (like the one I posted above).

    Since I never played around with variable parameter lists yet, I read up on it and came up with this little code:

    Code:
    #include <stdlib.h>
    #include <stdarg.h>
    #include <stdio.h>
    #include <string.h>
    
    typedef struct {
        char **values;
        int size;
    } options;
    
    options initOptions(int, ...);
    void printOptions(options*);
    
    main()
    {
        options myOptions = initOptions(2, "test", "test2");
        options myOptions2 = initOptions(3, "test", "test2", "test3");
    
        printOptions(&myOptions);
        printOptions(&myOptions2);
        return 0;
    }
    
    void printOptions(options* myOptions)
    {
        int i;
        for (i = 0; i < myOptions->size; i++)
            printf("%s\n", myOptions->values[i]);
    }
    
    options initOptions(int n, ...)
    {
        options myOptions;
        int i;
        va_list ap;
        char *tmp;
    
        myOptions.size = n;
        myOptions.values = malloc(n * sizeof(char *));
    
        va_start(ap, n);
        for(i = 0; i < n; i++) {
            tmp = va_arg(ap, char *);
            myOptions.values[i] = malloc((strlen(tmp)+1) * sizeof(char));
            strcpy(myOptions.values[i], tmp);
        }
    
        va_end(ap);
        return myOptions;
    }

  5. #5
    Registered User
    Join Date
    Mar 2006
    Posts
    158
    Thanks for all your help... I prefer the first way though, without the structures, it's simpler for now...

    I never exactly understood pointers totally... I've already used them before but not to complex, for instance, the "**" before the variable name, what does it mean? I was only used to use only 1 * and the &, never used ** before...

  6. #6
    Lean Mean Coding Machine KONI's Avatar
    Join Date
    Mar 2007
    Location
    Luxembourg, Europe
    Posts
    444
    Quote Originally Posted by Nazgulled View Post
    Thanks for all your help... I prefer the first way though, without the structures, it's simpler for now...

    I never exactly understood pointers totally... I've already used them before but not to complex, for instance, the "**" before the variable name, what does it mean? I was only used to use only 1 * and the &, never used ** before...
    Well, let's say that you have a variable of type int and you pass it as a pointer, you use "*" to get the address of x:

    Code:
    void myFunction(int *myNumber);
    
    int main()
    {
    int x = 10;
    myFunction(&x);
    }
    now imagine the same thing, but not with an integer but with a pointer:
    Code:
    void myFunction(int **myNumber);
    
    int main()
    {
    int x = 10;
    int *p = &x;
    myFunction(&p);
    }
    As you can see, we used &p to get the address of p, but p itself is already a pointer to the address of x, so in fact, we have &(&x) or a pointer to a pointer to x, also written "int **".

    Now, let's take the example of a C string. A string is nothing else but an char array:
    Code:
    char *myString;
    myString = malloc(6 * sizeof(char));
    strcpy(myString, "hello");
    
    OR
    
    char myString[] = "hello";
    In the code above you can see that the 2nd notation does basically nothing else than the first notation. Now, in your case, you have an array of string, or an array of arrays of char:
    Code:
    size_t stringNbr = 10;
    size_t maxStringLength = 128;
    int i;
    char **myStringArray;
    myStringArray = malloc(stringNbr * sizeof(char *));
    for (i = 0; i < stringNbr; i++)
    {
        myStringArray[i] = malloc(maxStringLength * sizeof(char));
    }
    As you can see, I first allocate space for "stringNbr" pointers to characters (or pointers to strings) and then iterate over all the strings and allocate enough memory to hold the content.

  7. #7
    Registered User
    Join Date
    Mar 2006
    Posts
    158
    Thanks for the explanation

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    There seem to be two posts discussing basically the same thing - this one is closed.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pass struct array to function
    By aditya_t90 in forum C Programming
    Replies: 4
    Last Post: 03-30-2009, 11:54 AM
  2. function passing argument..array ?
    By jochen in forum C Programming
    Replies: 2
    Last Post: 09-30-2007, 11:53 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM