tags:

views:

752

answers:

3

I need to perform 9 different operations on a coordinate, depending on the position of the coordinate. I have a function that returns the coordinates of a position around the given coordinate (down, up, left, right or diagonals). The 9 different operations are the different possible 'types' of coordinate; if I'm dealing with coordinate (0, 0), the only valid operations are right, down-right and down.

I have a structure where I store the directions that are valid for each type of coordinate. 4 for the corner coordinates, 1 for all the inner coordinates, and 4 for the non-corner columns of the edge-rows.

The field in the structure where I store all the directions is a dynamic two-dimensional array called 'library'. Each row of library would correspond to a type of coordinate, containing all the valid directions for that type of coordinate. I haven't found a way to assign the values one row at a time though, and I can't assign them individually with a loop.

What I have tried is:

searches->library[0][0] = {2, 3, 4, -1};
searches->library[1][0] = {4, 5, 6, -1};
searches->library[2][0] = {2, 3, 4, 5, 6, -1};
searches->library[3][0] = {0, 1, 2, 3, 4, 5, 6, 7, -1};
searches->library[4][0] = {0, 1, 2, -1};
searches->library[5][0] = {0, 6, 7, -1};
searches->library[6][0] = {0, 1, 2, 6, 7, -1};
searches->library[7][0] = {0, 1, 2, 3, 4, -1};
searches->library[8][0] = {0, 4, 5, 6, 7, -1};

But this gives me p2AdjacencyMatrix.c:179: error: parse error before '{' token for each line.

I have also tried:

searches->library[][9] = {{2, 3, 4, -1},
       {4, 5, 6, -1},
       {2, 3, 4, 5, 6, -1},
       {0, 1, 2, 3, 4, 5, 6, 7, -1},
       {0, 1, 2, -1},
       {0, 6, 7, -1},
       {0, 1, 2, 6, 7, -1},
       {0, 1, 2, 3, 4, -1},
       {0, 4, 5, 6, 7, -1}};

And the result it p2AdjacencyMatrix.c:189: error: parse error before ']' token

Here is the structure definition:

typedef struct{
    int active_length; // Size of active array of searches
    int* active;  // Active array of searches
    int** library; // Library of array of searches
} SearchLibrary;

And the memory allocation for the dynamic array:

SearchLibrary* searches;
searches = (SearchLibrary *) malloc(sizeof(SearchLibrary*));
int search_cases = 9, search_directions = 9;
searches->library = (int **) malloc(search_cases * sizeof(int *));
searches->active = (int *) malloc(search_directions * sizeof(int));

int i;
for(i = 0; i < search_cases; i++){
    searches->library[i] = (int *) malloc(search_directions * sizeof(int));
}

How can I add these values to each row of the array? I tried changing my structure definition to a static array, but that didn't work either. Is this happening because I'm using a pointer to a structure?

A: 

You can't do this, in C. There are no array literals for you to assign, there are only array initialization expressions.

I think the solution is to simply compute the required value from the coordinates and the size of the field, from my understanding that should be simple.

Besides, having a constant-sized literal initialization value seems to go against the point of allocating all of this dynamically.

Also:

  • Don't cast the return value of malloc() in C
  • Don't use sizeof on types when you don't have to, do e.g. searches = malloc(sizeof *searches); and so on
unwind
Yes, cast the return value of malloc() -- it is usually required.Yes, use sizeof even when you don't have to -- it makes your code much easier to maintain.
Die in Sente
in C, you don't have to cast the return of malloc. doing that usually adds useless redundancy (knowledge of what the type is that you assign to) to your code. i agree that omitting sizeof is a bad idea though
Johannes Schaub - litb
No, don't cast malloc in C: it returns a void *, which can be converted to a pointer of any (non-function) type implicitly
Christoph
wait, he didn't recommend to omit sizeof. he just recommend omitting the type, and replacing it with an expression. i think that is a Good Recommendation.
Johannes Schaub - litb
You're right, Christoph, I was thinking in C++.
Die in Sente
I read a few questions yesterday while trying to solve this problem and saw a few comments on not casting the return of malloc, I'll keep this in mind thanks. I'll need to give your solution some more thought tomorrow, the structure was supposedly to not have to compute directions based on coord
bob esponja
A: 
static const int Library0[] = {2, 3, 4, -1};
static const int Library1[] = {4, 5, 6, -1};
static const int Library2[] = {2, 3, 4, 5, 6, -1};
static const int Library3[] = {0, 1, 2, 3, 4, 5, 6, 7, -1};
static const int Library4[] = {0, 1, 2, -1};
static const int Library5[] = {0, 6, 7, -1};
static const int Library6[] = {0, 1, 2, 6, 7, -1};
static const int Library7[] = {0, 1, 2, 3, 4, -1};
static const int Library8[] = {0, 4, 5, 6, 7, -1};

static const int * Library[] = { 
    Library0, Library1, Library2,
    Library3, Library4, Library5,
    Library6, Library7, Library8,
};

typedef struct{
    int active_length;  // Size of active array of searches
    const int* active;                // Active array of searches
    const int** library;      // Library of array of searches
} SearchLibrary;

searches->library = Library;

EDIT: fixed syntax error.

Die in Sente
do you miss some [] anywhere?
Christoph
Oops, thanks Christoph! -- edited to fix.
Die in Sente
I'm probably missing some const qualifiers, too.
Die in Sente
I get the same error as with the other solution, so I must be missing something: warning: excess elements in scalar initializerwarning: (near initialization for `Library')
bob esponja
There's still a pair of `[]` missing behind `int * Library`
Christoph
Thanks Christoph, it now works perfectly
bob esponja
Thanks for finding my syntax errors, Chistoph -- I should not have done this before my morning caffine.
Die in Sente
+3  A: 

Assuming C99, you can use a compound literal and memcpy() it over your row. For the k-th row, this could look like this:

#define SEARCH_DIRECTIONS 9

memcpy(searches->library[k], ((int [SEARCH_DIRECTIONS]){ 1, 2, 3 }),
    sizeof(int) * SEARCH_DIRECTIONS);
Christoph
i didn't notice the numbers represent up to maximal 9 directions. i think your answer is better considering that (so you don't have to do dynamic allocation). +1
Johannes Schaub - litb
I'll have to read up on compound literals to see if I'm missing something obvious, but using this line in my code yields this:warning: excess elements in array initializerwarning: (near initialization for `(anonymous)')for each element in the compound literal. I'll try some more tomorrow.
bob esponja
Which compiler are you using? If gcc, did you specify the -std=c99 (or -std=gnu99) options?
Christoph
Yes, I'm using gcc and tried specifying -std=c99, but it still didn't like it. I think c99 might be the default standard, because I tried with c89 and it threw tonnes more errors. As the other solution works, I'm happy to leave it at this unless it's something really simple that I'm missing. Thanks
bob esponja
hm - compiles here... With this solution, the contents of the rows will be computed at run-time, whereas with Die in Sente's solution, they must be known at compile-time.
Christoph
To clarify: If the values are known at compile time, use Die in Sente's solution for performance reasons. But beware that then, all structs will share the same library!
Christoph
Yes, the values are known at compile time, they in fact never change. And there is only one struct that uses the library, so no problem there. I'm not even sure if a structure was what I really needed, I'm pretty new to C and programming. It works though, so I'm happy. Thanks for your comments.
bob esponja
If the values are compile-time *and* the pointers are properly const-typed, the data can be used by any number of objects or even threads.
Die in Sente