I am having some issues with this program for school. I am trying to utilize a two dimensional array and am getting some errors regarding "no conversion from int to int * and '>=' : 'int [5]' differs in levels of indirection from 'int'". I can write it for one dimensional array but am having difficulty with the syntax for the two dimensional. Can someone point me in the right direction in regards to what I may be missing? I have commented out after the btnShow_CLick and it works correctly, it is just the btnGroup_Click where I am obviously missing something.
Thanks to anyone that could possibly share some knowledge.
static const int NUMROWS = 4;
static const int NUMCOLS = 5;
int row, col;
Graphics^ g;
Brush^ redBrush;
Brush^ yellowBrush;
Brush^ greenBrush;
Pen^ blackPen;
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
g = panel1->CreateGraphics();
redBrush = gcnew SolidBrush(Color::Red);
yellowBrush = gcnew SolidBrush(Color::Yellow);
greenBrush = gcnew SolidBrush(Color::Green);
blackPen = gcnew Pen(Color::Black);
}
private: System::Void btnShow_Click(System::Object^ sender, System::EventArgs^ e) {
panel1->Refresh();
for (int row = 0; row < NUMROWS; row++)
{
for (int col = 0; col < NUMCOLS; col++)
{
Rectangle seat = Rectangle(75 + col * 75,40 + row *40,25,25);
g->DrawRectangle(blackPen, seat);
}
}
}
private: System::Void btnGroup_Click(System::Object^ sender, System::EventArgs^ e) {
int score[NUMROWS][NUMCOLS] = {{45,65,11,98,66},
{56,77,78,56,56},
{87,71,78,90,78},
{76,75,72,79,83}};
int mean;
int student;
mean = CalcMean(score[]);
txtMean->Text = mean.ToString();
for (int row = 0; row < NUMROWS; row++)
{
for (int col = 0; col < NUMCOLS; col++)
{
student = (row*NUMCOLS) + (col);
Rectangle seat = Rectangle(75 + col * 75,40 + (row * 40),25,25);
if (score[student] >= 80
g->FillRectangle(greenBrush, seat);
else if (score[student] >= mean)
g->FillRectangle(yellowBrush, seat);
else
g->FillRectangle(yellowBrush, seat);
g->DrawRectangle(blackPen, seat);
}
}
}
private: double CalcMean(int score[])
{
int sum = 0;
int students = NUMROWS * NUMCOLS;
for (int i=0; i< students; i++) sum += score[i];
return sum / students;
}
Score[student] is equivalent to *(score+student), which is a *int. Instead you should probably use score[row][col], or its equivalent **(score+student) (I strongly advise the array notation). It is also equivalent to *Score[student], but that's pretty ugly.
Plus when I say "it's equivalent", it's only because sizeof int ==sizeof (*int). If you use the pointer logic with another type inside your array you might have funky results.
Related
I've been struggling to understand how to work with pointers generally. I have in the example below a little sketch of an update function (updateGrid) for Game of life. The idea is to update the state of all cells in the grid between true and false (as you might know).
However, I'm supposed to use pointers in order to alternate between the 'previous' and 'new' state of the grid. But I don't seem to figure out how to implement this concept of alternating pointers without making a copy of the current cells grid. Any idea?
By the way, my code below works so far just fine.
// ---------- Global Variables ----------
bool cells[MAX_SIZE][MAX_SIZE];
bool cells_next[MAX_SIZE][MAX_SIZE];
bool (*ptr)[MAX_SIZE][MAX_SIZE];
bool (*ptr_next)[MAX_SIZE][MAX_SIZE];
ptr = &cells;
ptr_next = &cells_next;
// ---------- update state ----------
void updateState() {
for (int row = 0; row < MAX_SIZE; ++row) {
for (int col = 0; col < MAX_SIZE; ++col) {
if (((*ptr)[row][col]) == 1) {
if ((numAliveNeighbors(row, col) < 2)
|| (numAliveNeighbors(row, col) > 3)) {
(*ptr_next)[row][col] = 0;
} else {
(*ptr_next)[row][col] = 1;
}
} else if (((*ptr)[row][col]) == 0) {
if (numAliveNeighbors(row, col) == 3) {
(*ptr_next)[row][col] = 1;
} else {
(*ptr_next)[row][col] = 0;
}
}
}
}
for (int row = 0; row < MAX_SIZE; ++row) {
for (int col = 0; col < MAX_SIZE; ++col) {
(*ptr)[row][col] = (*ptr_next)[row][col];
(*ptr_next)[row][col] = 0;
}
}
PS: My problem explanation may seem a little bumpy so don't hesitate for further infos.
Many thanks in advance :)
Note these remarks:
You should use pointer to rows instead of pointers to 2D arrays.
You can alternate the pointers by swapping the via a temporary variable.
The code implements John Conway's famous Game of Life generations. ptr points to the current board and ptr_next points to the next generation. update() computes the new board applying the rules for cell death and birth. When the new board has been fully updated, the pointers are swapped, so ptr now points to the new board. This is faster than copying the full board from cells_next to cells.
Here is a modified version:
// ---------- Global Variables ----------
bool cells[MAX_SIZE][MAX_SIZE];
bool cells_next[MAX_SIZE][MAX_SIZE];
bool (*ptr)[MAX_SIZE] = cells;
bool (*ptr_next)[MAX_SIZE] = cells_next;
// ---------- update state ----------
void updateState() {
for (int row = 0; row < MAX_SIZE; ++row) {
for (int col = 0; col < MAX_SIZE; ++col) {
if (ptr[row][col]) {
if ((numAliveNeighbors(row, col) < 2)
|| (numAliveNeighbors(row, col) > 3)) {
ptr_next[row][col] = 0;
} else {
ptr_next[row][col] = 1;
}
} else {
if (numAliveNeighbors(row, col) == 3) {
ptr_next[row][col] = 1;
} else {
ptr_next[row][col] = 0;
}
}
}
}
// swap the pointers
bool (*tmp)[MAX_SIZE] = ptr;
ptr = ptr_next;
ptr_next = tmp;
}
Note that numAliveNeighbors should probably take ptr as an argument instead of implicitly via a global variable.
I'm building the public API for Game of Life and I don't know how to code this part.
This is a picture of "flow chart" we're suppose to follow:
Steps :
These are the public APIs we're supposed to fill out;
void gofl_get_world(int n_rows, int n_cols, cell_t world[][n_cols], double percent_alive){}
this first function should: Get the initial randomly ordered distribution of cells in the world. This is the usage: gofl_get_world(MAX_ROWS, MAX_COLS, world, 0.1)
void gofl_next_state(int n_rows, int n_cols, cell_t world[][n_cols]){}
This function does this: Calculate the next state of the world according to the rules and the actual state. I.e. this will mark all cells in the world as alive or dead.
Here are the functions we're supposed to build the public API from, I've made these myself as well so they are not pre-defined (they are tested and all returned true):
static void get_cells(cell_t arr[], int size, double percent_alive) {
int n = (int) round(percent_alive*size); //checking if cell dead or alive with size
for (int i = 0; i < size; i++){
if (i < n ){ //cell needs to be over certain thresh hold to be alive
arr[i] = 1; //alive
}
else{
arr[i] = 0; //dead
}
}
static int get_living_neighbours(int n_rows, int n_cols, const cell_t world[][n_cols], int row, int col) {
int sum = 0;
for (int r = row - 1; r <=row + 1; r++){
for(int c = col-1; c<=col +1; c++){
if(!(row == r && col == c) && is_valid_location(n_rows, n_cols, r, c)){
sum = sum + world[r][c];
}
}
}
return sum;
static void array_to_matrix(int n_rows, int n_cols, cell_t matrix[][n_cols], const cell_t arr[], int size) {
for (int i = 0; i < size; i++){
matrix[i/n_rows][i%n_cols] = arr[i];
}
static void shuffle_cells(cell_t arr[], int size) {
for(int i = size; i > 1; i--){
int j = rand()%i;
int tmp = arr[j];
arr[j] = arr[i-1];
arr[i-1] = tmp;
}
Anyone know how I can solve this? I don't know how to perform this action, thanks!
This might be considered a low-brow question. Yet, I haven't found any code, or any forums discussing how to go about this in my programming language, C. Plenty of attempt have been made, and all end up in practically "hard-coding" the new arrays.
I'm trying to vertically, then horizontally flip a 2d array.
It seemed easy enough, just went through systematically and manipulated each row and column value. But, what if I want to go about an array that isn't just a basic 3x3 array. Such as 11x11, or 15x15?
**CODE SNIPPET:**
int array[3][3]= { {1,2,3},
{4,5,6},
{7,8,9} };
int vertFlip[3][3],
horzFlip[3][3];
for(i = 0; i < rows; i++)
{
for(j = 0; j < cols; j++)
{
vertFlip[0][i]= array[2][i];
vertFlip[1][i]= array[1][i];
vertFlip[2][i]= array[0][i];
}
} //and so on for horizontal, obviously my nested for loop was different.
But, what if this array was something much larger, (123x123 sized array) does anyone know an effective way to accomplish this task?
I would start out with a simple approach. For horizontal flip:
int swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void FlipRow(int *row, int columns)
{
// A row is a simple one dimensional array
// just swap item 0 with item n-1, 1 with n-2, ...
for (int index = 0; index < columns / 2; index++)
{
swap(row+index, row+columns-1-index);
}
}
void HFlipArray(int **array, int columns, int rows)
{
for (int row = 0; row < rows; row++)
{
FlipRow(array[row], columns);
}
}
For vertical flip, use similar approach:
// Reuse swap
void FlipColumn(int **array, int column, int rows)
{
// Flip column 'column' of an array that has n rows.
for (int row = 0; row < rows/2; row++)
{
swap(array[row]+column, array[rows-1-row]+column);
}
}
void VFlipArray(int **array, int columns, int rows)
{
for (int column = 0; column < columns; column++)
{
FlipColumn(array, column, rows);
}
}
Note that the above code changes the contents of the input. If that is not desired, you can modify the code to pass in destination and source arrays and adjust your loops accordingly.
Hello there You can try a simple approach to transpose your 2d array :-
int ar[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
int i,j,ar1[3][3];
for(i = 0;i<3;i++)
{
for(j=0;j<3;j++)
{
ar1[i][j] = ar[j][i];
}
}
as you can see you just have to iterate loop to your array length and into the loop ar1[i][j] = ar[j][i] perform the flip operation.
Template solution
works for arrays of ints, floats, doubles, ...
template <class t>
void flip_horizontal(const int nrows, const int ncols, t* data) // flips left-right
{
for (int rr = 0; rr < nrows; rr++)
{
for (int cc = 0; cc < ncols/2; cc++)
{
int ccInv = ncols - 1 - cc;
std::swap<t>(data[rr * ncols + cc], data[rr * ncols + ccInv]);
}
}
}
template <class t>
void flip_vertical(const int nrows, const int ncols, t* data) // flips: bottom-up
{
for (int cc = 0; cc < ncols; cc++)
{
for (int rr = 0; rr < nrows/2; rr++)
{
int rrInv = nrows - 1 - rr;
std::swap<t>(data[rr * ncols + cc], data[rrInv * ncols + cc]);
}
}
}
I have the following function:
int* create_matrix_2(int rows, int cols)
{
double (*A)[rows][cols] = malloc(sizeof(int[rows][cols]));
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
*A[row][col] = row * cols + col;
}
}
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
printf("%lf, " , *A[row][col]);
}
printf("\n");
}
return A;
}
My question is: How do I return the VLA from that function, what is the type and how do I write that as a function signature and how do I use it where I receive the returned array?
At the moment I am trying to do it like this:
int (*matrix2)[height][width] = create_matrix_2(height, width);
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
printf("%d" , (*matrix2)[row][col]);
}
printf("\n");
}
and then run: gcc 2d_array_test.c -o 2d_array_test.out -std=c99 -O0
But this results in the following problems:
2d_array_test.c: In function ‘main’:
2d_array_test.c:35:34: warning: initialization from incompatible pointer type [enabled by default]
int (*matrix2)[height][width] = create_matrix_2(height, width);
^
2d_array_test.c: In function ‘create_matrix_2’:
2d_array_test.c:105:2: warning: return from incompatible pointer type [enabled by default]
return A;
^
EDIT#1:
I tried to use the code suggested by alk, but it gives me a lot of errors while compiling. Here is a separate programm, which contains your suggested code with a main function: http://pastebin.com/R6hKgvM0
I get the following errors:
2d_array_test_new.c: In function ‘main’:
2d_array_test_new.c:18:2: warning: passing argument 3 of ‘create_matrix’ from incompatible pointer type [enabled by default]
if (-1 == create_matrix(height, width, &matrix))
^
2d_array_test_new.c:10:5: note: expected ‘int **’ but argument is of type ‘int (**)[(sizetype)(height)][(sizetype)(width)]’
int create_matrix(size_t, size_t, int**);
^
2d_array_test_new.c: At top level:
2d_array_test_new.c:37:5: error: conflicting types for ‘create_matrix’
int create_matrix(size_t rows, size_t cols, int(**a)[rows][cols])
^
2d_array_test_new.c:10:5: note: previous declaration of ‘create_matrix’ was here
int create_matrix(size_t, size_t, int**);
^
2d_array_test_new.c: In function ‘create_matrix’:
2d_array_test_new.c:45:11: error: ‘EINVAL’ undeclared (first use in this function)
errno = EINVAL;
^
2d_array_test_new.c:45:11: note: each undeclared identifier is reported only once for each function it appears in
2d_array_test_new.c:40:6: warning: variable ‘errno’ set but not used [-Wunused-but-set-variable]
int errno;
^
The errors mainly seem to be about the return type. How do I write the type of that array correctly?
refering the 1st warning:
warning: initialization from incompatible pointer type
Here
int (*matrix2)[height][width] = create_matrix_2(height, width);
int (*matrix2)[height][width] and int * simply aren't the same.
refering the 2nd warning:
warning: return from incompatible pointer type
This dues to defining
double (*A)[rows][cols] = malloc(sizeof(int[rows][cols]));
while returning A from int * create_matrix_2().
int * and double (*A)[rows][cols] also aren't the same.
I propose you change the function like this:
#include <errno.h> /* for errno and EINVAL */
#include <stdlib.h> /* for malloc() */
int create_matrix_2(size_t rows, size_t cols, int(**a)[rows][cols])
{
int result = 0;
if (NULL == a)
{
result = -1;
errno = EINVAL;
}
else
{
(*a) = malloc(sizeof **a);
if (NULL == (*a))
{
result = -1;
}
else
{
for (size_t row = 0; row < rows; row++)
{
for (size_t col = 0; col < cols; col++)
{
(**a)[row][col] = row * cols + col;
}
}
for (size_t row = 0; row < rows; row++)
{
for (size_t col = 0; col < cols; col++)
{
printf("%d, " , (**a)[row][col]);
}
printf("\n");
}
}
}
return result;
}
and call it like this:
#include <stdlib.h>
#include <stdio.h>
int create_matrix_2(size_t rows, size_t cols, int(**a)[rows][cols]);
int main(void)
{
int result = EXIT_SUCCESS;
int (*matrix2)[height][width] = NULL;
if (-1 == create_matrix_2(height, width, &matrix2))
{
perror("create_matrix_2() failed");
result = EXIT_FAILURE;
}
else
{
for (size_t row = 0; row < height; row++)
{
for (size_t col = 0; col < width; col++)
{
printf("%d, " , (*matrix2)[row][col]);
}
printf("\n");
}
free(matrix2);
}
return result;
}
First, there are some issues with your code. You have a double array pointer pointing to a 2D array of ints, that doesn't make any sense.
Also, since A is a pointer to a 2D array, you can't do *A[row][col]. Because [] has higher precedence than *, so the code is equivalent to *(A[row][col]). Which is turn means "give me row number of 2D matrices, then...". The code will end up far out of bounds.
The trick when declaring an array pointer to a dynamically allocated multi-dimensional array is to omit the inner-most dimension. That way you can use syntax just like you would with a regular multi-dimensional array.
double (*A)[cols] = malloc(sizeof(double[rows][cols]));
...
A[x][y] = ...;
A[x][y] will then mean "In my array A, where each item is an array of size cols, access array number x and then index y in that array".
As for the question of how to return an array of this type... well you can't, because the function declaration would have to contain the dimensions of the array pointer. It would have to be a monstrosity like this:
double (*create_matrix_2(int rows, int cols))[rows][cols] // wont compile
If we ignore that the C syntax for returning array pointers (and function pointers) is completely FUBAR, the above isn't valid C. Because rows and cols would then have to be known at compile time.
The solution to clearing up the above mess and fixing the issue at the same time is to return the array pointer through a parameter:
void create_matrix_2 (int rows, int cols, double(**array)[rows][cols])
{
// omit inner-most dimension to get sane syntax:
double (*A)[cols] = malloc(sizeof(double[rows][cols]));
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
A[row][col] = row * cols + col;
}
}
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
printf("%lf, " , A[row][col]);
}
printf("\n");
}
// "brute" pointer conversion but doesn't break aliasing:
*array = (void*)A;
}
The short answer is that you can't.
The problem is that the type returned from a function must be fixed at compile time and cannot depend on the numeric value (supplied at run time) of its parameters.
What you can do, however, is change your create_matrix2() to return a void pointer. This uses the fact that, in C, (almost) any pointer can be implicitly converted to a void pointer, and vice versa.
void *create_matrix2(int rows, int columns)
{
/* as you've implemented it, except that A should be int not double */
}
int main()
{
int rows = 2, cols = 3;
int (*m)[rows][cols] = create_matrix2(rows, cols);
/* use *m as a pointer to an array with 2 rows and 3 cols */
}
It then delivers the illusion of what you seek.
The danger of this - and the reason I use the word "illusion" just now - is that the conversion to and from a void pointer prevents the compiler doing type checking. So this will sail past the compiler, but cause undefined behaviour due to falling off the end of arrays.
int main()
{
int rows = 2, cols = 3;
int (*m)[rows][cols] = create_matrix2(rows-1, cols-1); /* whoops - deliberate typos here */
/* use *m as a pointer to an array with 2 rows and 3 cols */
}
because this effectively tells the compiler to treat the dynamically allocated array as if it has more rows and columns than actually allocated in the function.
sample
#include <stdio.h>
#include <stdlib.h>
void * create_matrix_2(int rows, int cols){
int (*A)[rows][cols] = malloc(sizeof(int[rows][cols]));
for (int row = 0; row < rows; row++){
for (int col = 0; col < cols; col++){
(*A)[row][col] = row * cols + col;
}
}
for (int row = 0; row < rows; row++){
for (int col = 0; col < cols; col++){
printf("%d, " , (*A)[row][col]);
}
printf("\n");
}
return A;
}
int main(void){
int width = 5, height = 3;
int (*matrix2)[height][width] = create_matrix_2(height, width);
for (int row = 0; row < height; row++){
for (int col = 0; col < width; col++){
printf("%d " , (*matrix2)[row][col]);
}
printf("\n");
}
free(matrix2);
return 0;
}
I've got an assignment to optimize a piece of C code (a language in which I'm rather n00bish) designed to simulate rotating pixels in an image:
void naive_rotate(int dim, pixel *src, pixel *dst) {
int i, j;
for (i = 0; i < dim; i++)
for (j = 0; j < dim; j++)
dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
}
Defs for pixel and RIDX are as follows:
typedef struct {
unsigned short red;
unsigned short green;
unsigned short blue;
} pixel;
#define RIDX(i,j,n) ((i)*(n)+(j))
The instructions for the assignment contain the note, "Your task is to rewrite this code to make it run as fast as possible using techniques like code motion, loop unrolling
and blocking."
I thought I had some ideas on how to approach this. However, my attempts at loop unrolling:
void rotate_unroll(int dim, pixel *src, pixel *dst) {
int i, j;
for (i = 0; i < dim; i++) {
for (j = 0; j < dim; j+=4) {
dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
dst[RIDX(dim-1-(j+1), i, dim)] = src[RIDX(i, j+1, dim)];
dst[RIDX(dim-1-(j+2), i, dim)] = src[RIDX(i, j+2, dim)];
dst[RIDX(dim-1-(j+3), i, dim)] = src[RIDX(i, j+3, dim)];
}
}
}
and code motion (or at least reorganizing RIDX and moving around some of the calculations out of the inner loop):
void rotate_motion(int dim, pixel *src, pixel *dst) {
int i, j;
int dimsquared = dim * dim;
for (i = 0; i < dim; i++) {
int dst_temp = dimsquared - dim + i;
int src_temp = i * dim;
for (j = 0; j < dim; j++) {
dst[dst_temp - (dim * j)] = src[src_temp + j];
}
}
}
// dst[RIDX(dim-1-j, i, dim)]
// = dst[(dim-1-j)dim + i]
// = dst[(dim * dim) - dim - (dim)j + i]
// src[RIDX(i, j, dim)]
// = src[(dim)i + j]
do not seem to be working; the timer packaged with the assignment claims that my solutions are not having any impact on the CPE of the program. I suspect I am probably approaching both methods incorrectly and would greatly appreciate any guidance in the right direction. (It's a homework assignment so I'm not asking for a complete solution, just some pointers.)
My other thought was to try to add an accumulator -- something along the lines of the following:
void rotate_acc(int dim, pixel *src, pixel *dst) {
int i, j;
pixel temp = dst;
for (i = 0; i < dim; i++) {
for (j = 0; j < dim; j++) {
temp[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
}
}
dst = temp;
}
But my syntax is very wrong there and I'm not sure how one would go about constructing a temporary version of the struct in question.
Any help is much appreciated. Thanks!
You need to have a thorough understanding on pointers in C. Put it simply: pointers represent an address of where your data is stored in memory (pixel struct in your case).
In your code, the function rotate_acc takes a pixel pointer as argument: pixel *dst. At first you can be tempted to say pixel *tmp = dst, but keep in mind this is what is called shallow copy -- only the address are copied, not the data it's pointing at -- hence if you modify tmp by saying tmp->red = 0, it will modify the original data too
If you need a deep copy, you need to say pixel tmp = *dst
Try this:
void naive_rotate(int dim, pixel *src, pixel *dst) {
int dimSq = dim * dim;
int dstdIxStart = dimSq - dim;
int endIdx = dimSq - 2 * dim - 2;
int dstIdx = dimSq - dim;
for (int i = 0; int < endIdx; ++i)
{
dst[dstIdx--] = src[i];
if (0 == dstIdx)
{
dstdIxStart -= dim;
dstIdx = dstdIxStart;
}
}
}
You will have to double check the maths, but I hope you get the idea.
It removes all the multiplications. Also as src is being accessed sequentially it is good for the cache.