Thread: I want a dynamic array.

  1. #1
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Arrow I want a dynamic array.

    Based on my last series of posts which you needn't read, I now need a new method of creating a dynamicly expanding global array. I suspect I won't get one, which would be COMPLETELY RIDICULOUS and makes me wonder how anyone has managed to do anything significant in C at all.

    Here's the issue: I want to read in a text file consisting of lines like this
    bob 3874 habit
    scram 9984 sweater
    flux 12 then

    so each line ends up in a struct like this:
    Code:
    struct info {
         char *name;
         int *num;
         char *also;
    } ray[3];
    However, the number of such lines is indeterminate, so "ray[3]" won't work. This must be a common task. How can I create an array of structs that will grow when I add a new entry, so to speak? Or do I have to (COMPLETELY RIDICULOUS) have to just set ray[10000] or something, to make sure I have enough space?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by mk27 View Post
    COMPLETELY RIDICULOUS

    Don't blame the language, blame yourself
    Just wanted to point that out for comic relief.

    Anyway, have you ever seen malloc and realloc before?

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    How can I create an array of structs that will grow when I add a new entry, so to speak?
    Use malloc() and free() from <stdlib.h>, e.g.,
    Code:
    #include <stdlib.h>
    
    struct info {
        char *name;
        int *num;
        char *also;
    };
    
    int main(void) {
        struct info *ray;
        ray = malloc(3 * sizeof(*ray));
        /* Use ray[0], ray[1] and ray[2] here. */
        free(ray);
        return 0;
    }
    Though in the above example we do not actually expand the array, but that can be done with realloc(), also declared in <stdlib.h>.

    Or do I have to (COMPLETELY RIDICULOUS) have to just set ray[10000] or something, to make sure I have enough space?
    That is actually an option: if you have a small enough upper limit of the number of elements, then you might decide to create an array of that size and just use as much of it as is needed.

    EDIT:
    Gah, it looks like the tutorials and FAQs here only touch on dynamic memory allocation with respect to C++. Anyway, search the Web and you will find more info. Also, you might note that my example does not include checking the return value of malloc() for NULL, but checking whether the allocation failed is good practice.
    Last edited by laserlight; 08-27-2008 at 10:43 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Switch to C++ and use a vector which is like an array and it can grow.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    malloc and realloc will do! I just didn't see how to use them with an array...thanks.

    phew! I thot i was crazy.
    Last edited by MK27; 08-27-2008 at 10:46 AM. Reason: phew! I thot I was crazy.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Registered User
    Join Date
    Aug 2008
    Posts
    67
    Quote Originally Posted by MK27 View Post
    malloc and realloc will do! I just didn't see how to use them with an array...thanks.

    phew! I thot i was crazy.
    This may be of use to you: http://www.macs.hw.ac.uk/~rjp/Course.../linklist.html
    http://cslibrary.stanford.edu/103/LinkedListBasics.pdf

  7. #7
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    The STL vector idea isn't a horrible one, but I wouldn't tell someone who says "How much is gas, my Tahoe is a gas guzzler" "Oh the Toyota dealership is down the road to sell you a more fuel efficient vehicle."

    So in the spirit of answering the question without intense sarcasm: The linked list thing may be a better solution since it can be cheaper than resizing. On the other hand, for what you are doing, since you can just resize by a large factor, you may find it no more expensive to just use malloc() and realloc().

  8. #8
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    I gave a link to a nice reference to dynamic memory allocation in the other thread.

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    hmmm...what's "fuel efficiency" about here: the awkwardness of having to use realloc, or the expense of learning C++ when I just rolled C off the lot last month...

    I gotta thank kpreston, actually, as I have saved his refs for later. But right now a simple malloc suffices (the array doesn't really need to grow, but its initial size is a variable, and the struct must be global).

    It didn't occur to me to use sizeof that way; up to now the only (error checked) malloc calls I've made have been simple character arrays, and multipying by 1 is easy.

    I think the reason I started to write this was that I thot master5001 might have some deeper performance issues in mind. Now I'm not so sure.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I gotta thank kpreston, actually, as I have saved his refs for later.
    Be warned that the first article may appear much simpler than the second, but the example given fails to free the memory allocated. The second article is much more comprehensive, but perhaps a little more intimidating.

    I think the reason I started to write this was that I thot master5001 might have some deeper performance issues in mind. Now I'm not so sure.
    Do you need to quickly add elements in the middle? If so, consider a linked list. Do you need to quickly access elements anywhere? If so, consider an array-like structure like a vector. Expanding a linked list from the middle (assuming that you already have a pointer to the insertion point) takes constant time, but expanding a dynamic array from the middle takes linear time (but expanding it from the end also takes constant time, in the long run, if you double the allocation whenever you need to expand). On the other hand, accessing the middle of a linked list takes linear time if you start from the head, while arrays have random access.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Realloc example:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define LINE_BUF_SZ 1024
    static const unsigned int RAY_CHUNK_SIZE = 10;
    
    typedef struct _info
    {
       char *name;
       int num;
       char *also;
    } info;
    
    void print_data(const info **data, const unsigned int count)
    {
       unsigned int i = 0;
       for ( ; i < count; ++i)
       {
          printf("Entry %u: %s %d %s\n", i,
                data[i]->name, data[i]->num, data[i]->also);
       }
    }
    
    void free_data(info **data, const unsigned int count)
    {
       unsigned int i = 0;
       for ( ; i < count; ++i)
       {
          free(data[i]->name);
          free(data[i]->also);
          free(data[i]);
       }
    }
    
    int main()
    {
       char line[LINE_BUF_SZ];
       char temp_name_buf[LINE_BUF_SZ], temp_also_buf[LINE_BUF_SZ];
       FILE *fp = fopen("dyndata.txt", "r");
       if (!fp)
          return -1;
    
       unsigned int ray_count = RAY_CHUNK_SIZE;
       info **ray = calloc(ray_count, sizeof(*ray));
       if (!ray)
          return -1;
    
       unsigned int line_count = 0;
       while(NULL != (fgets(line, sizeof(line), fp)))
       {
          if (line_count + 1 == ray_count)
          {
             // Need realloc                                                         
             info ** temp = realloc(ray, (ray_count += RAY_CHUNK_SIZE) * sizeof(*ray));
             if (!temp)
             {
                free_data(ray, line_count);
                free(ray);
                return -1;
             }
             ray = temp;
          }
    
          ray[line_count] = calloc(1, sizeof(info));
          if (!ray[line_count])
             return -1;
    
          if (3 != sscanf(line,
                          "%s %d %s",
                          temp_name_buf,
                          &ray[line_count]->num,
                          temp_also_buf))
          {
             return -1;
          }
    
          ray[line_count]->name = strdup(temp_name_buf);
          ray[line_count]->also = strdup(temp_also_buf);
          ++line_count;
       }
    
       print_data((const info **)ray, line_count);
    
       free_data(ray, line_count);
       free(ray);
    
       fclose(fp);
    
       return 0;
    }
    Last edited by rags_to_riches; 08-27-2008 at 11:51 PM. Reason: Consistency

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dynamic Array Resizing
    By dld333 in forum C++ Programming
    Replies: 13
    Last Post: 11-04-2005, 12:13 AM
  2. need help with dynamic array syntax
    By soldyne in forum C Programming
    Replies: 3
    Last Post: 10-11-2005, 01:59 PM
  3. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  4. 2D dynamic array problem
    By scsullivan in forum C Programming
    Replies: 3
    Last Post: 12-30-2002, 10:02 PM
  5. Dynamic array allocation and reallocation
    By purple in forum C Programming
    Replies: 13
    Last Post: 08-01-2002, 11:48 AM

Tags for this Thread