0

I need some ideas on my array of struct implementation. This is what I have in my structs. I plan on making SHAPES an array because I will have multiple SHAPES. Each shape will have multiple x and y coordinates. Because of this I'm not sure if should make a linked list or not. The purpose of the start and finish is I will eventually be running a search algorithm after I get my shapes right.

struct START
{
    int x; 
    int y;
};
struct END
{
    int x; 
    int y;
};
struct SHAPES
{
    int x [100]; 
    int y [100];
    int *link;
};
struct DISTANCE
{
    int distance_traveled; 
    int distance_to_finish;
};

I was reading this and was wondering if I needed to malloc or calloc my structs as I create them. If so why and if not why? Malloc and calloc are always confusing to me.

How do you make an array of structs in C?

int main(int argc, char *argv[])
{

    //Is it better to make these pointers? 
    struct START start;
    struct END end;
    struct SHAPES shapes[100];

    while(fgets(line, 80, fp) != NULL)
    {
        //I have a very annoying issue here, I don't know the size of the lines. 
        //If there are more values I want to increment the x[] and y[] array but NOT the 
        //shapes array. I can only think of one way to deal with this by putting a bunch of 
        //variables in the sscanf. I discovered putting sscanf on the next line didn't do what 
        //I was hoping for. 
        sscanf(line, "%d%*c %d%*c ", &shapes[i].x[i] , &shapes[i].y[i] );
        printf(" line is: %s \n", line);
        sscanf(line, "%d%*c %d%*c ", &x1_main , &y1_main );
        printf(" line is: %s \n", line);
        printf(" shapes[i].x[i] is: %d \n", shapes[i].x[i]);
        printf(" shapes[i].y[i] is: %d \n", shapes[i].y[i]);
        printf(" x1_main is: %d \n", x1_main);
        printf(" y1_main is: %d \n", y1_main);
        i++;
        memset(line, 0, 80);
    }

}

This is what my file looks like. Adding the %*c seemed to handle the commas and semicolons appropriately.

10, 4
22, 37
22, 8; 2, 0; 3, 6; 7, 8; 5, 10; 25, 2
1, 2

I got that idea from here.

https://www.daniweb.com/software-development/c/threads/334515/reading-comma-separated-values-with-fscanf

Community
  • 1
  • 1
cokedude
  • 379
  • 1
  • 11
  • 21
  • It is not clear why you have separate types for `START` and `END` (or why you like shouting; normally, reserve all upper-case names for macros, not for types — the standard `FILE *` and POSIX `DIR *` notwithstanding). Surely, you could call this 'Position', and then your `Shape` should contain an array of `Position` values. There's no self-evident reason to create a linked list of shapes. If you use C99 or C11, you might consider using a flexible array member, but that might also be pushing you too hard as yet. – Jonathan Leffler Oct 13 '14 at 07:29
  • To deal with unknown numbers of entries in a line, consider [How to use `sscanf()` in loops?](http://stackoverflow.com/questions/3975236/how-to-use-sscanf-in-loops/3975254#3975254) – Jonathan Leffler Oct 13 '14 at 07:33
  • I have a strong suspicion that your use of 100 shapes in an array when each shape can hold one hundred points is misguided. You should fill up the first 100 points in one shape before moving to another entry in the array, I think. – Jonathan Leffler Oct 13 '14 at 07:38
  • As to `malloc()` etc: you use those when either the array will be too big to allocate on the stack or its size won't be known until run-time and any pre-allocation may be too small (or will need to use too much space to be sensible). Use arrays when you can; use lists when you must. Arrays give you easy access to any element, but it is hard to remove or add an element in the middle of an array. Lists are flexible (it is easy to add and possible to remove from the middle of a list), but finding a particular element in the list is typically slow compared to using an array. – Jonathan Leffler Oct 13 '14 at 07:40
  • @JonathanLeffler The purpose for the start and end is because I will be running a search algorithm after I properly build my shapes. I need the Start and End to properly run the algorithm. – cokedude Oct 13 '14 at 07:55
  • I guess I don't understand your problem well enough then. I'm confident that I would not need the separate Start and End types for what I understood of what you're trying to do, but clearly you know more about your situation than I do. I observe that the code you show does not actually use either Start or End (though a Start and an End variable are defined), so they really shouldn't be part of the question. There's no use of Distance, either. (FWIW, I can't criticize code you don't show.) – Jonathan Leffler Oct 13 '14 at 07:59
  • @JonathanLeffler The purpose of my 100 shapes is I don't know how many shapes I will be dealing with. I sure hope 100 is enough. Each shape can have many points. A shape can be something like a simple square or rectangle, or it can be complicated like a star polygon where it has many points. I would rather be more thorough than I need to be than not thorough enough. The shapes are are then gonna form obstacles in between the start and end. My algorithm needs to find a way through this. – cokedude Oct 13 '14 at 08:11

2 Answers2

1

First of all, you might want to consider something like this:

struct point {
      int x;
      int y;
};

so you can use a struct point data structure (array) instead of two separate data structures for x and y. Using it like this should also speed up access to the points, since their coordinates are next to each other in memory. Otherwise you will have x somewhere in the x array and y somewhere in the y array.

The choice of the data structure to store the points depends on your usage. If you need to address points directly, a linked list may be a bad choice. If you always access all points in a linear order, it is fine. However, consider that a singly linked list will add 8 bytes per point for the next pointer. A doubly linked list will use another 8 bytes for prev (assuming 64-bit arch that is; sizeof(pointer) in general). I assume, that you create x[100] and y[100] to make sure you have enough space. You might be better off using a dynamic array (the ADT) e.g. glib's GArray after all. It will grow as big as you need it without you doing anything.

For malloc vs calloc: it doesn't really matter. A call to calloc is basically a malloc followed by a

memset(ptr, 0, sizeof(mallocd area);

i.e. the memory is zeroed; cf manpage calloc. If you initialize the memory directly you may not need to do this.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
midor
  • 5,487
  • 2
  • 23
  • 52
0

A struct with no pointer members
If your struct has no pointer members, such as:

typedef struct {
    int a;
    int b;

} DEMO;  

Then you can simply declare an array instance of a typedef struct like this:

DEMO demo[10];// instance of array of 10 DEMO

Example, struct with Pointer members
If you have a pointer in the list of members:

#define SIZE_STR 20

typedef struct {
    int a;
    int b;
    char *str;//pointer, will require memory allocation
} DEMO;

DEMO demo[10];// instance of array of 10 DEMO

int main(void)
{
    int i;

    for(i=0;i<10;i++)//create memory for each instance of char * in array of DEMO
    {   
        demo[i].str = malloc(SIZE_STR); 
    }
    return 0;
}  

Don't forget to free() all instances of malloc'ed memory.

Dynamically allocate array of struct
If you need to dynamically allocate memory for a struct:

typedef struct {
    int a;
    int b;
} DEMO;  
DEMO demo, *pDemo;// create a pointer to DEMO

In a function, main() for example:

int main(void)
{
    pDemo = &demo;  
    pDemo = malloc(sizeof(DEMO)*10);//provides an array of 10 DEMO
    return 0;
}  

Again, don't forget to free() all instances of malloc'ed memory.

ryyker
  • 22,849
  • 3
  • 43
  • 87