-1

Long story short, I am trying to process some arrays for various things. during debugging, I need to print the arrays. I'd like to have just one function that will print whatever array is passed to it. I can fairly easily pass the dimensions of the array as well. Let's assume for now, I'm only using a two-dimensional array.
Believe me; I have reviewed every similar question asked here and attempted to implement the suggested solutions to no avail. I have tried using pointer and the like. In particular, I tried all four solutions in this post: https://stackoverflow.com/a/17569578/4641918, and I still get a myriad of errors depending on the method. I'm not new to programming, but I am new to C++. Here is a very simplified example of what I'm trying to do:

//  Array Failures
#define FIRSTWIDTH 6        //Number of Columns in First Array
#define FIRSTHEIGHT 5       //Number of Rows in First Array
#define SECONDWIDTH 4       //Number of Columns in Second Array
#define SECONDHEIGHT 2      //Number of Rows in Second Array


//  An couple of arrays are declared with dimensions WIDTH X HEIGHT
int firstArray[FIRSTWIDTH][FIRSTHEIGHT];
int secondArray[SECONDWIDTH][SECONDHEIGHT];

void setup()
{
Serial.begin(57600);
fillXXArray(FIRSTWIDTH, FIRSTHEIGHT, firstArray);
fillXXArray(SECONDWIDTH, SECONDHEIGHT, secondArray);  //GENERATES ERROR 1
Serial.println("Program Initialized");
printANYArray(FIRSTWIDTH, FIRSTHEIGHT, firstArray); 
}

void loop(){return;}

void fillXXArray(int width, int height, int myArray[][FIRSTHEIGHT]){
// Fills an array with values that is WIDTH X HEIGHT
// Inner Subset is the sum of its coordinates
for (int w = 0; w < width - 1; w++){
    for (int h = 0; h < height - 1; h++){
        myArray[w][h] = w + h;
    }
}

// Loop across the bottom row and set them to the sum of the column.
for (int w = 0; w < width - 1; w++){
    for (int h = 0; h < height - 1; h++){
        myArray[w][height - 1] = myArray[w][height - 1] + myArray[w][h];
    }
 }

// Loop down the last column and set it to the product of the values in row.
for (int h = 0; h < height - 1; h++){
    myArray[width - 1][h] = myArray[0][h];
    for (int w = 1; w < width - 1; w++){
        myArray[width-1][h] = myArray[width-1][h] * myArray[w][h];
    }
}
myArray[width - 1][height - 1] = width * height;

//  The final array is populated like this.
//
//            0     1     2    ...         w
//    0    [  0     1     2    ...   (Product of Row)  ]
//    1    |  1     2     3    ...   (Product of Row)  |
//    2    |  2     3     4    ...   (Product of Row)  |
//   ...   | ...   ...   ...   ...   (Product or ...)  |
//    h    [(Sum) (Sum) (Sum)  ...       (h*W)         ]
//
}

void printANYArray(size_t width, size_t height, int myArray[][height]){  //GENERATES ERROR 2
Serial.println("printXXArray: ");
for (int h = 0; h < height; h++){
    for (int w = 0; w < width; w++){
        Serial.print(myArray[w][h]); Serial.print("\t\t");
    } Serial.println();
} Serial.println();
}

ERROR 1: (VS2013 highlights "secondArray") Error: argument of type "int()[2]" is incompatible with parameter of type "int()[5]." That pretty obvious and hence what I'm trying to avoid. So I remove the constant from the function definition and get the second error.

ERROR 2: :"height" highlighted) Error: a parameter is not allowed.

END OF PRIMARY SOLUTION.

NEXT SOLUTION: Passing the array as a pointer. I changed the function declaration to:

void printANYArray(size_t width, size_t height, int **myArray){

but which doesn't raise a flag in the function, but then the function call fails with:

 printANYArray(FIRSTWIDTH, FIRSTHEIGHT, firstArray);

"firstArray" Error: argument of type "int(8)[5]" is incompatible with parameter type "int **"

NEXT SOLUTION: "The function is using a pointer, so shouldn't I send it an address?" I changed the function call to:

printANYArray(FIRSTWIDTH, FIRSTHEIGHT, &firstArray);

Just the "&" gets highlighted, ERROR: argument of type "int (*)[6][5]" is incompatible with parameter type "int **" Wait... what?!? I thought I was just sending the address.

NEXT GUESS ('cuz that's what I'm doing now): I removed one of the *'s in the declaration. That just removes one of the stars from the error message. Well at least that's understandable.

So... any help you can provide would be helpful. Again, this is for an Arduino maybe that has something to do with it, because I can't seem to get any solutions from examples to work - even when I copy and paste the whole source.

Community
  • 1
  • 1
Brandon L
  • 13
  • 3

1 Answers1

0

I would avoid templates, because on an Arduino you want to keep the compiled code small. I would instead revert to old-style 1D arrays:

int firstArray[FIRSTHEIGHT * FIRSTWIDTH];
int secondArray[SECONDHEIGHT * SECONDWIDTH];

The usual convention in the C family of languages is to store the matrix by rows, and to have the first index be the row index. Per this convention, the cell at row i column j would be arr[i][j] for a “real” 2D array, and arr[width * i + j] for these “faked” 2D arrays. Here is how you fill them:

void fillXXArray(int *myArray, int height, int width) {

    // Inner Subset is the sum of its coordinates
    for (int h = 0; h < height - 1; h++) {
        for (int w = 0; w < width - 1; w++) {
            myArray[width * h + w] = h + w;
        }
    }

    // Bottom row has the sums of the columns.
    for (int w = 0; w < width - 1; w++) {
        myArray[width * (height - 1) + w] = 0;
        for (int h = 0; h < height - 1; h++) {
            myArray[width * (height - 1) + w] += myArray[width * h + w];
        }
     }

    // Last column has the product of the rows.
    for (int h = 0; h < height - 1; h++) {
        myArray[width * h + (width - 1)] = myArray[width * h + 0];
        for (int w = 1; w < width - 1; w++) {
            myArray[width * h + (width - 1)] *= myArray[width * h + w];
        }
    }

    // Last cell.
    myArray[width * (height - 1) + (width - 1)] = width * height;
}

I took the liberty of putting the array as the first parameter. This is an informal convention: whenever you pass a pointer together with size information, the pointer generally comes first. C.f. snprintf() and strncpy() for example.

If you do not mind the extra memory cost, then you can use an extra array of pointers to store the starting address of every row. This way you can access the array elements with the simpler syntax arr[i][j], where arr is now the auxiliary array. This would normally be done through dynamic allocation in a constructor, but since your data is all static, we can avoid dynamic allocation:

int firstArrayData[FIRSTHEIGHT * FIRSTWIDTH];       // actual data
int *firstArray[FIRSTHEIGHT] = { firstArrayData };  // pointers to rows

Here, only the first pointer of firstArray[] is correctly initialized. You will have to initialize the rest at runtime, for example in fillXXArray():

void fillXXArray(int **myArray, int height, int width) {

    // Initialize the pointers to the start of the rows.
    for (int h = 1; h < height; h++) {
        myArray[h] = myArray[0] + width * h;
    }

    // Inner Subset is the sum of its coordinates
    for (int h = 0; h < height - 1; h++) {
        for (int w = 0; w < width - 1; w++) {
            myArray[h][w] = h + w;      // <-- syntax like 2D arrays
        }
    }

    // etc...
Edgar Bonet
  • 3,116
  • 12
  • 18
  • Thanks a lot Edgar. Not what I'd hoped, but that will definitely work! I appreciate your thorough response! – Brandon L Mar 14 '15 at 15:16