This question has been answered here but for me some things are still left open and the discussion is too old for anyone to reply to comments, besides I wanted to ask what was wrong in my implementation.
Anyway, the problem setting. I want to allocate space for a 3D array of dimensions 3, h, w. What I am doing:
int ***a = (int***)malloc(3 * sizeof(int*));
for (int i = 0; i < 3; i++)
{
a[i] = (int **) malloc(height * sizeof(int*));
}
I understand this as creating first space for three 3 int** and then allocating height int**;
Then :
for (int i = 0; i < 3; i++)
{
a[i][0] = (int *) malloc(height * width * sizeof(int *));
for (int j = 1; j < height; j++)
{
a[i][j] = a[i][j-1] + width;
}
}
So now I think that each a[i][0] is basically space for a 2D array of sizes height and width; furthermore the rest of a[i][j] for j != 0 is initialized to the j th row of a[i][0];
then I initialize values by:
for (int c = 0; c < 3; c++){
for (int i = 0; i < height; i++){
for (int j = 0; j < width; j++){
a[c][i][j] = i+j+c;
This however is incorrect. I wanted to do this as an extension exercise to allocating a 2D array in the following way:
int *a[height];
a[0] = (int*)malloc(height * width * sizeof(int));
for (int i = 1; i < height; i++){
a[i] = a[i-1] + widht;
}
This way a is an array of pointers of length height, a[0] is allocated for the whole 2D array and the consequent pointers point to their respective rows and I can write to them simply by calling a[i][j] = some number;
What I want to do is extend this 2D idea to the 3D case, but I am sadly failing.
int ***a = (int***)malloc(3 * sizeof(int*));
This doesn't allocate anything meaningful. In particular, it does not allocate a 3D array, or even a part of a 3D array. It allocates space for 3 integer pointers, which doesn't make any sense. Neither does a int*** make any sense.
Instead, allocate a 3D array:
int (*a)[y][z] = malloc( sizeof(int[x][y][z]) );
for(int i=0; i<x; i++)
for(int j=0; j<y; j++)
for(int k=0; k<z; k++)
a[i][j][k] = something;
free(a);
EDIT (any sarcastic tone in the below text is fully intentional)
For the benefit of the three-star programmers who refuse to accept any solution with less than three levels of indirection, here is an example of how to properly do three-star programming.
Unfortunately it does not yet contain non-conditional branching upwards, memory leaks or complex pointer arithmetic. But for a three-star programmer, such joyful things are of course trivial to add later. It does however guarantee data cache misses, so that the program will run with equal performance as a system without any data cache.
One may also consider to pass the allocated pointer-to-pointer-to-pointer as a parameter, thus achieving 4 stars!!!
[As in, the pointer-to-pointer method is very bad practice, but if you for reasons unknown insist on using it, you might as well do it proper.]
#include <stdlib.h>
#include <stdio.h>
void free_int_3d (int*** ppp, size_t X, size_t Y, size_t Z)
{
(void)Z;
if(ppp == NULL)
{
return ;
}
for(size_t x=0; x < X; x++)
{
if(ppp[x] != NULL)
{
for(size_t y=0; y < Y; y++)
{
if(ppp[x][y] != NULL)
{
free(ppp[x][y]);
}
}
free(ppp[x]);
}
}
free(ppp);
}
#define malloc_with_cleanup(ptr, size) \
ptr = malloc(size); \
if(ptr == NULL) \
{ \
free_int_3d(result, X, Y, Z); \
return NULL; \
}
int*** int_alloc_3d (size_t X, size_t Y, size_t Z)
{
int*** result = NULL;
malloc_with_cleanup(result, sizeof(int**[X]));
for(size_t x=0; x<X; x++)
{
malloc_with_cleanup(result[x], sizeof(int*[Y]));
for(size_t y=0; y<Y; y++)
{
malloc_with_cleanup(result[x][y], sizeof(int[Z]));
}
}
return result;
}
int main (void)
{
const size_t X = 5;
const size_t Y = 3;
const size_t Z = 4;
int*** ppp = int_alloc_3d(X, Y, Z);
for(size_t i=0; i<X; i++)
{
for(size_t j=0; j<Y; j++)
{
for(size_t k=0; k<Z; k++)
{
ppp[i][j][k] = (int)k;
printf("%d ", ppp[i][j][k]);
}
printf("\n");
}
printf("\n");
}
free_int_3d(ppp, X, Y, Z);
return 0;
}
Output:
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
Let's visualize what you're trying to do first, and then I'll show the code to get there:
int *** int ** int * int
+---+ +---+ +---+ +---+
a | | ---> a[0] | | ------> a[0][0] | | ----> a[0][0][0] | |
+---+ +---+ +---+ +---+
a[1] | | ----+ a[0][1] | | -+ a[0][0][1] | |
+---+ | +---+ | +---+
a[2] | | | ... | ...
+---+ | +---+ | +---+
| a[0][h-1] | | | a[0][0][w-1] | |
| +---+ | +---+
| |
| +---+ | +---+
+-> a[1][0] | | +--> a[0][1][0] | |
+---+ +---+
a[1][1] | | a[0][1][1] | |
+---+ +---+
... ...
+---+ +---+
a[1][h-1] | | a[0][1][w-1] | |
+---+ +---+
Types:
Each a[i][j][k] has type int;
Each a[i][j] points to the first element of a sequence of int objects, so it must have type int *;
Each a[i] points to the first element of a sequence of int * objects, so it must have type int **;
a points to the first element of a sequence of int ** objects, so it must have type int ***.
Since you're doing a piecemeal nested allocation, you need to check the result of each malloc call, and if there's an error, you will want to clean up any previously allocated memory before bailing out, otherwise you risk memory leaks. Unfortunately, there's no really clean or elegant way to do that - you either carry a flag around and do a bunch of extra tests, or you throw in a couple of gotos. I'm going to show two different approaches, neither of which is all that pretty.
First method - as we allocate each a[i], we also allocate each a[i][j] (a "depth-first" approach) and initialize each a[i][j][k]. If an allocation on a[i][j] fails, we must deallocate all of a[i][0] through a[i][j-1], then deallocate a[i], then repeat the process for each of a[0] through a[i-1]:
/**
* Depth-first approach: allocate each a[i][j] with each a[i]
*/
int ***alloc1( size_t pages, size_t height, size_t width )
{
size_t i, j, k;
int ***a = malloc( sizeof *a * pages ); // allocate space for N int **
// objects, where N == pages
if ( !a )
return NULL;
for ( i = 0; i < pages; i++ )
{
a[i] = malloc( sizeof *a[i] * height ); // for each a[i], allocate space for
if ( !a[i] ) // N int * objects, where N == height
goto cleanup_1;
for ( j = 0; j < height; j++ )
{
a[i][j] = malloc( sizeof *a[i][j] * width ); // for each a[i][j], allocate
if ( !a[i][j] ) // space for N int objects,
goto cleanup_2; // where N == w
for ( k = 0; k < width; k++ )
a[i][j][k] = initial_value( i, j, k );
}
}
goto done;
/**
* Free all of a[i][0] through a[i][j-1], then free a[i]
*/
cleanup_2:
while ( j-- )
free( a[i][j] );
free( a[i] );
/**
* Free all of a[0] through a[i-1], then free a
*/
cleanup_1:
while ( i-- )
{
j = height;
goto cleanup_2;
}
free( a );
a = NULL;
done:
return a; // at this point, a is either a valid pointer or NULL.
}
Yes, this code contains gotos, and it violates one of my pet rules (never branch backwards). But, there's a fairly clean separation between the allocation code and the cleanup code, and we don't repeat ourselves in the cleanup sections. cleanup_2 deallocates all the rows within a page, along with the page itself; cleanup_1 deallocates all of the pages. cleanup_2 "falls through" into cleanup_1.
Here's a second method - first we allocate all a[i] before allocating any a[i][j], then we make sure all a[i][j] were successfully allocated before initializing the array contents.
/**
* Breadth-first approach; allocate all a[i], then all a[i][j], then initialize
*/
int ***alloc2( size_t pages, size_t height, size_t width )
{
size_t i, j, k;
/**
* Allocate space for N int ** objects, where N == pages
*/
int ***a = malloc( sizeof *a * pages );
if ( !a )
return NULL; // allocation failed for initial sequence, return NULL
for ( i = 0; i < pages; i++ ) // For each a[i], allocate N objects of type
{ // int *, where N == height
a[i] = malloc( sizeof *a[i] * height );
if ( !a[i] )
break;
}
if ( i < pages )
{
while ( i-- ) // allocation of a[i] failed, free up a[0] through a[i-1]
free( a[i] );
free( a ); // free a
return NULL;
}
for ( i = 0; i < pages; i++ )
{
for ( j = 0; j < height; j++ )
{
a[i][j] = malloc( sizeof *a[i][j] * width ); // for each a[i][j], allocate
if ( !a[i][j] ) // space for N int objects,
break; // where N == width
}
}
if ( j < h )
{
do
{
while ( j-- ) // allocation of a[i][j] failed, free up a[i][0] through a[i][j-1]
free( a[i][j] ); // repeat for all of a[0] through a[i-1].
free( a[i] );
j = h;
} while ( i-- );
free( a ); // free a
return NULL;
}
/**
* All allocations were successful, initialize array contents
*/
for ( i = 0; i < pages; i++ )
for ( j = 0; j < height; j++ )
for ( k = 0; k < width; k++ )
a[i][j][k] = initial_value( i, j, k );
return a;
}
No gotos! But the code doesn't "flow" as well IMO. There's not as clean a separation between allocation and cleanup code, and there's a bit of repetitiveness between the cleanup sections.
Note that for both methods, the memory is not contiguous - the element immediately following a[0][0][h-1] is not going to be a[0][1][0]. If you need all your array elements to be adjacent in memory, you will need to use the method shown by the others:
int (*a)[h][w] = malloc( sizeof *a * 3 );
with the caveat that if h and w are large, you may not have enough contiguously allocated memory to satsify the request.
To solve OP's higher goal, I suspect a pointer to a 2D array would suffice #mch
int (*a)[height][width] = malloc(sizeof *a * 3);
a[c][i][j] = i + j + c;
But per OP's request....
... to allocate space for a 3D array ...
How would code typically create a 3D array?
The below code does that using a variable length array available in C99.
(VLA is optionally support in C11)
int a1[3][height][width];
// and assign it accordingly
for (int c = 0; c < 3; c++) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
a1[c][i][j] = i + j + c;
Yet OP wants to allocate space for such an array.
malloc() returns a pointer. A pointer to allocated memory. So we need to create a pointer to such an array. Once we have done that, allocation and element assignment is easy.
int (*a2)[3][height][width] = malloc(sizeof *a2);
// 3 nested for loop as above
(*a2)[c][i][j] = i + j + c;
Example code
void VT_3_dimensional_array(int height, int width) {
assert(height > 0 && width > 0);
int (*a2)[3][height][width] = malloc(sizeof *a2);
printf("%p %zu\n", (void*) a2, sizeof *a2);
if (a2 == NULL) {
perror("Out of memory");
exit(EXIT_FAILURE);
}
for (int c = 0; c < 3; c++) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
(*a2)[c][i][j] = i + j + c;
}
}
}
// use a;
for (int c = 0; c < 3; c++) {
for (int i = 0; i < height; i++) {
putchar('(');
for (int j = 0; j < width; j++) {
printf(" %X", (*a2)[c][i][j]);
}
putchar(')');
}
puts("");
}
free(a2);
}
int main() {
VT_3_dimensional_array(5, 7);
return 0;
}
output
0x80071980 420
( 0 1 2 3 4 5 6)( 1 2 3 4 5 6 7)( 2 3 4 5 6 7 8)( 3 4 5 6 7 8 9)( 4 5 6 7 8 9 A)
( 1 2 3 4 5 6 7)( 2 3 4 5 6 7 8)( 3 4 5 6 7 8 9)( 4 5 6 7 8 9 A)( 5 6 7 8 9 A B)
( 2 3 4 5 6 7 8)( 3 4 5 6 7 8 9)( 4 5 6 7 8 9 A)( 5 6 7 8 9 A B)( 6 7 8 9 A B C)
Note, technically OP's code is using the wrong size. Usually sizeof(int*) will be the same as sizeof(int**), so no great harm. Yet it does indicate confusion about the allocation.
// wrong type -----------------------v should be int**
int ***a = (int***)malloc(3 * sizeof(int*));
Related
#include<stdio.h>
#define NUM_ROWS 3
#define NUM_COLS 5
int main(void){
int a[NUM_ROWS][NUM_COLS],(*p)[NUM_COLS], i;
for (p = &a[0],i=0; p < &a[NUM_ROWS]; p++,i++){
(*p)[i]=i;
}
printf("The value of a[0][0] is %d\n",a[0][0]); // I want 0
printf("The value of a[0][1] is %d\n",a[0][1]); // 1
printf("The value of a[0][2] is %d\n",a[0][2]); // 2
printf("The value of a[0][3] is %d\n",a[0][3]); // 3
printf("The value of a[0][4] is %d\n",a[0][4]); // 4
return 0;
}
Hi guys I'm a C novice, and I am trying to understand processing the columns of a 2D array.
I wanted output of 0,1,2,3,4 from row 0's columns but I had these results
The value of a[0][0] is 0
The value of a[0][1] is 0
The value of a[0][2] is 1
The value of a[0][3] is 0
The value of a[0][4] is -1
I tried to find what was wrong, but I failed to....
I will be grateful if someone explains what is wrong with my codes..
Your assignment in the loop is initializing the leading diagonal:
(*p)[i] = i;
To illustrate, here's an adaptation of your code that prints the whole matrix (and initializes it):
#include <stdio.h>
#include <string.h>
#define NUM_ROWS 3
#define NUM_COLS 5
int main(void)
{
int a[NUM_ROWS][NUM_COLS], (*p)[NUM_COLS], i;
/* Set all elements to -1 assuming 2's complement */
memset(a, 0xFF, sizeof(a));
for (p = &a[0], i = 0; p < &a[NUM_ROWS]; p++, i++)
{
(*p)[i] = i;
}
for (i = 0; i < NUM_ROWS; i++)
{
for (int j = 0; j < NUM_COLS; j++)
printf("%3d", a[i][j]);
putchar('\n');
}
return 0;
}
The output is:
0 -1 -1 -1 -1
-1 1 -1 -1 -1
-1 -1 2 -1 -1
Notice that the three elements on the leading diagonal are set to 0, 1, 2 and the rest are -1 as set by memset().
If you want to initialize the first row, then you simply use:
int (*p)[NUM_COLS] = &a[0];
for (int i = 0; i < NUM_COLS; i++)
(*p)[i] = i;
Or, more simply still, forget about p and use:
for (int i = 0; i < NUM_COLS; i++)
a[0][i] = i;
If you want to initialize column 0, you need:
(*p)[0] = i;
Or, again, more simply, forget about p and use:
for (int i = 0; i < NUM_ROWS; i++)
a[0][i] = i;
I think you want to write your for loop like this (based on you captions)
for the first row.
for (p = &a[0], i=0; i < NUM_COLS; i++){
(*p)[i] = i;
}
Here increasing the pointer p doesn't help for it will be incremented by a value of NUM_COLS every time due to pointer arithmetic.
Here is a second possible answer if you want to write and read the whole matrix within a single for loop
for (p = &a[0], i = 0; i < NUM_COLS * NUM_ROWS; i++) {
(*p)[i] = i;
}
Or the better solution would be to use two for loops as
for (p = &a[0], i = 0; p < &a[NUM_ROWS] ; p ++) {
int k = 0; //for the column count
for(;k < NUM_COLS; i++, k++) {
(*p)[k] = i;
}
}
Thanks for asking :)
for (p = &a[0]; p < &a[NUM_ROWS]; p++){
for(i=0;i<NUM_COLS;i++){
(*p)[i]=i;
printf("%d\n",(*p)[i]);
// I got 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
}
}
Should I write nested loop to print out all elements of 2D?
Is there a way to print out using 1 loop with processing columns of 2D array?
I don't quite understand what does it mean to assign one pointer to another pointer? Here **p is an array of pointers/2D array, then p[0] is assigned to p[1], do both of them point to same address?
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i,j;
int **p = (int **)malloc(2 * sizeof(int *));
p[0] = (int *)malloc(2 * sizeof(int));
p[1] = p[0];
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
p[i][j] = i + j;
printf("%d",p[0][0]);
return 0;
}
I expected output to be 0 but it's actually 1, why?
The both pointers p[0] and p[1] have the same value after the expression statement
p[1] = p[0];
So where the expression p[1] is used it can be substituted for the expression p[0] because the both expressions have the same value and vice versa.
In this loop
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
p[i][j] = i + j;
when i is equal to 1 and j is equal to 0 (given that p[1] is the same as p[0].) So p[1][0] is equivalent to p[0][0] and equal to i + j that is 1.
In fact this loop
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
p[i][j] = i + j;
is equivalent to the loop
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
p[0][j] = i + j;
Thus the second iteration of the outer loop rewrites the values stored in p[0][0] and p[0][1] after the first iteration.
In the second iteration we have i is equal 1. So for j in the range [0, 1] we have
p[0][0] = i + j (when i == 1 and j == 0 ) = 1
and
p[0][1] = i + j (when i == 1 and j == 1 ) = 2
I don't quite understand what does it mean to assign one pointer to
another pointer? Here **p is an array of pointers/2D array, then p[0]
is assigned to p[1], do both of them point to same address?
Yes. But it's probably more useful conceptually to ignore the significance of the values of p[0] and p[1] (that the values are pointers, and what those values point to) to focus instead on the fact that after the assignment, their values are the same. That the values then point to the same thing follows from that.
Note well that I have intentionally chosen wording that distinguishes between designators for storage locations (e.g. "p[1]") and the contents of those locations -- their values. We often use language that blurs the distinction because it's cumbersome to speak precisely in that way, but it is essential that you maintain the distinction in your head. Formally, it is not the expression p[1] or even the storage location it designates that is a pointer, but rather the value stored there. The assignment operator copies that value to another storage location, so naturally, if the contents of that other storage location are interpreted according to the same data type, then they have the same meaning as the original.
I expected output to be 0 but it's actually 1, why?
Because after having set p[1] = p[0], the expression p[1][0] designates the same object that p[0][0] does. After you assign p[1][0] = 1 + 0, you can therefore read back the resulting value (1) from either p[1][0] or p[0][0].
do both of them point to same address?
Yes.
Here's a modification of your program which should make this more clear:
int main(void) {
int i,j;
int **p = (int **)malloc(2 * sizeof(int *));
p[0] = (int *)malloc(2 * sizeof(int));
p[1] = p[0];
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
p[i][j] = i + j;
for(i = 0; i < 2; i++) {
printf("%d (%p)\t", i, p[i]);
for(j = 0; j < 2; j++)
printf("%d ", p[i][j]);
printf("\n");
}
return 0;
}
Here we print out the pointer values p[0] and p[1], and all four cells of the "two-dimensional" array -- except that, yes, there are really only two cells, doing double duty for each of the two rows. On my system, this prints out
0 (0x7f92ca402710) 1 2
1 (0x7f92ca402710) 1 2
and you can clearly see that the two pointers are the same.
We can think of this, in memory, as looking something like this:
+-------+
p: | * |
+---|---+
|
v
+-------+ +---+---+
| *----------+--->| 1 | 2 |
+-------+ / +---+---+
| *--------'
+-------+
If, on the other hand, you called malloc three times, instead of two, like this:
int **p = (int **)malloc(2 * sizeof(int *));
p[0] = (int *)malloc(2 * sizeof(int));
p[1] = (int *)malloc(2 * sizeof(int));
you would get a printout more like this:
0 (0x7fb747402710) 0 1
1 (0x7fb747402720) 1 2
and you would get a picture in memory something like this:
+-------+
p: | * |
+---|---+
|
v
+-------+ +---+---+
| *-------------->| 0 | 1 |
+-------+ +---+---+
| *--------.
+-------+ \ +---+---+
'--->| 1 | 2 |
+---+---+
I am really stucked on this problem, my C code has worked very well using multidimensional arrays but i need to do the same using pointers but i'll describe the problem first.
Having the following matrix, i will get a number which will be the number of permutations (the number of swapping of columns that will move to the right and the last column will move to the first column).
For example
The number of column's permutations: 5
| 1 2 3 | -----> | 2 3 1 |
| 3 1 2 | -----> | 1 2 3 |
| 2 3 1 | -----> | 3 1 2 |
I wrote the following code using pointers, as you can see i build the matrix with multidimensional array and assign all of it into a pointer:
short elementMatrix[3][3] = {{1, 2, 3},
{3, 1, 2},
{2, 3, 1}};
short *element_matrix;
element_matrix = *elementMatrix;
int counter = 1;
while (counter <= 5)
{
for (int i = 0; i < 3; i++)
{
int temp = elementMatrix[i][PR.elem_mat_size - 1];
*outElementMatrix = *outElementMatrix + i * PR.elem_mat_size + PR.elem_mat_size - 1;
for (int j = 3 - 1; j >= 0; j--)
{
*(outElementMatrix + i * PR.elem_mat_size + j) = *(outElementMatrix + i * PR.elem_mat_size + j - 1);
if (j == 0)
{
*(outElementMatrix + i * PR.elem_mat_size + j) = *outElementMatrix;
}
}
}
counter++;
}
Since you want to swap out columns, it makes sense to have the pointers represent the columns. That way, you can swap a pointer to swap a column. So let's have an array of 3 pointers to a column.
short* col[3];
Each column consists of 3 shorts, so allocate that much memory.
for (int i = 0; i < 3; i++) {
col[i] = (short*)malloc(3 * sizeof(short));
}
Now to initialize the Matrix. This is a bit verbose, so if anyone knows a better way, edit away. :)
col[0][0] = 1; col[1][0] = 2; col[2][0] = 3;
col[0][1] = 3; col[1][1] = 1; col[2][1] = 2;
col[0][2] = 2; col[1][2] = 3; col[2][2] = 1;
Now we do the swap. Note how you need a temp variable, like Rishikesh Raje suggested. Also note that three swaps bring it back to the original, so instead of swapping n times, you only have to swap n % 3 times. Of course it's going to be pretty much instant with 5 or 2 swaps, but if you have to do like a billion, the difference should be noticeable.
for (int i = 0; i < 5; i++) {
short* temp = col[2];
col[2] = col[1];
col[1] = col[0];
col[0] = temp;
}
We assure that the result is correct by printing it:
for (int i = 0; i < 3; i++) {
printf("%d %d %d\n", col[0][i], col[1][i], col[2][i]);
}
You can consider the permutations as a rotation of each row in the matrix and, unless you have to somehow use the matrix after each step, calculate only the final result.
I'll use an extra buffer to help with the swaps.
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
// rotate the values of an array using a buffer to ease the swappings
void rotate_(size_t n, void *arr, void *tmp, size_t offset)
{
assert(n && arr && tmp && offset <= n);
// casting to perform pointer arithmetic
memcpy(tmp, (char *)arr + (n - offset), offset);
memmove((char *)arr + offset, arr, n - offset);
memcpy(arr, tmp, offset);
}
void rotate_columns_short(size_t r, size_t c, short mat[r][c], short *buf, int n)
{
// clamp the value of the offset to the number of columns
size_t offset = (n >= 0
? n % c
: c - -n % c) * sizeof(short);
// transform each row
for (short *row = &mat[0][0], *row_end = row + r * c;
row != row_end;
row += c)
{
rotate_(c * sizeof(short), row, buf, offset);
}
}
void print_matrix_short(size_t r, size_t c, short mat[r][c])
{
for (size_t i = 0; i < r; ++i)
{
for (size_t j = 0; j < c; ++j)
{
printf(" %hd", mat[i][j]);
}
puts("");
}
}
#define ROWS 3
#define COLS 3
int main(void)
{
short matrix[ROWS][COLS] = {{1, 2, 3},
{3, 1, 2},
{2, 3, 1}};
short buf[COLS];
print_matrix_short(ROWS, COLS, matrix);
puts("");
rotate_columns_short(ROWS, COLS, matrix, buf, 5);
print_matrix_short(ROWS, COLS, matrix);
}
The output beeing:
1 2 3
3 1 2
2 3 1
2 3 1
1 2 3
3 1 2
I have a 50 x 50 matrix arr[50][50] and need to swap the values in the sub-array arr[0] and arr[1].
ie, the whole 50 elements in each sub-array need to be swapped.
The only way I can think of to do this is by using a loop like:
for(i=0; i<50; ++i)
{
int t = arr[0][i];
arr[0][i] = arr[1][i];
arr[1][i] = t;
}
I was wondering if there were any simpler or shorter methods? Using pointers maybe?
I tried things like
int *t = arr[0];
arr[0] = arr[1];
arr[1] = t;
but it gave error at the first line about "incompatible types when assigning to type 'int[2]' from type 'int *' ".
Then I tried pointer to an array
int (*t)[50] = arr[0];
arr[0] = arr[1];
arr[1] = t;
This time I got error at the second line about "incompatible types when assigning to type 'int[50]' from type 'int *' ".
If your matrix is implemented as arr[50][50] then the only way to physically swap two rows is to physically exchange data in memory. Your cycle is one way to do it. The rest would be just variations of that approach. You can swap matrix elements one-by-one (your cycle), you can swap the entire rows using an intermediate row-sized buffer (memcpy approach). All of them still do the same thing. There's no way around it.
If your array were implemented differently - say, a "jagged" array implemented as array of pointers to sub-arrays, then you would be able to just swap two pointers and be done with it. But in case of arr[50][50] it is not possible.
If you wish, you can just "convert" your current array into a "jagged" version by a separate row-pointer array. That row-pointer array will now become your matrix a, while the original a[50][50] will become a_data
int a_data[50][50];
int *a[50];
for (unsigned i = 0; i < 50; ++i)
a[i] = a_data[i];
/* Fill the matrix */
for (unsigned i = 0; i < 50; ++i)
for (unsigned j = 0; j < 50; ++j)
a[i][j] = rand();
/* Print the matrix */
for (unsigned i = 0; i < 50; ++i)
{
for (unsigned j = 0; j < 50; ++j)
printf("%d ", a[i][j]);
printf("\n");
}
/* Swap the rows */
int *temp = a[0];
a[0] = a[1];
a[1] = temp;
/* Print the matrix */
for (unsigned i = 0; i < 50; ++i)
{
for (unsigned j = 0; j < 50; ++j)
printf("%d ", a[i][j]);
printf("\n");
}
Note, that despite the physical structure of a is now different, you can still use a[i][j] syntax to work with it.
As explained in the comments, and within the other answers, in order to swap rows of an actual 2D array (as apposed to an array of pointers), you must copy/move the data from the source to target row in memory. The most straight forward way to approach this is either with a loop to copy element-by-element to temporary storage to effect the swap, or use the memory copy functions provided by the C-library (e.g. memcpy or memmove). A simple implementation using memcopy (shown with a 3x10 array for array for purposes of the example) would be:
#include <stdio.h>
#include <string.h>
enum { ROW = 3, COL = 10 };
void swaprow (int (*a)[COL], int c1, int c2);
void prna (int (*a)[COL]);
int main (void) {
int a[ROW][COL] = {{0}};
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
a[i][j] = i;
prna (a);
swaprow (a, 0, 1);
putchar ('\n');
prna (a);
return 0;
}
void swaprow (int (*a)[COL], int c1, int c2)
{
int tmp[COL];
memcpy (tmp, a[c1], COL * sizeof *tmp);
memcpy (a[c1], a[c2], COL * sizeof *a[c1]);
memcpy (a[c2], tmp, COL * sizeof *a[c2]);
}
void prna (int (*a)[COL])
{
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++)
printf ("%2d", a[i][j]);
putchar ('\n');
}
}
Example Use/Output
$ ./bin/array2d_swap_row
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2
1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0
2 2 2 2 2 2 2 2 2 2
Look things over and let me know if you have any questions.
You will have to copy the data to be swapped with memcpy, I have provided sample to program to show how you can do it(ie swap arr[0] and arr[1]).
int main(void) {
// your code goes here
int t[3];
int arr[3][3]={{1,2,3},{4,5,6},{7,8,9}};
printf("\n%d %d %d",arr[0][0],arr[0][1],arr[0][2]);
printf("\n%d %d %d",arr[1][0],arr[1][1],arr[1][2]);
memcpy(t,arr[0],sizeof(t));
memcpy(arr[0],arr[1],sizeof(t));
memcpy(arr[1],t,sizeof(t));
printf("\n%d %d %d",arr[0][0],arr[0][1],arr[0][2]);
printf("\n%d %d %d",arr[1][0],arr[1][1],arr[1][2]);
return 0;
}
I am programming a game which generates the next possible moves. I need to generate the next moves in order to perform the search. However I have no idea about how to do it in C.
The code to generate the board is:
#include <stdio.h> //prints
#include <stdbool.h> //bool
#include <stdlib.h> //malloc
static const int BOARD_SIZE = 6;
typedef int **BOARD;
void print_board(BOARD b){
int i,j;
printf("BOARD array is:\n");
for (i=0; i<BOARD_SIZE; i++) {
for (j=0; j<BOARD_SIZE; j++){
printf("%d ",b[i][j]);
}
printf("\n");
}
}
BOARD set_game(){
//set board
//all the squares starts with 2
int i, j;
BOARD b = malloc(sizeof(int *) * BOARD_SIZE);
for (i = 0; i < BOARD_SIZE; i++){
b[i] = malloc(sizeof(int) * BOARD_SIZE);
}
for (i=0; i<BOARD_SIZE; i++) {
for (j=0; j<BOARD_SIZE; j++){
//position player 0 peons
if(j == 0){
b[i][j] = 0;
}
//position player 1 peons
else if(j == BOARD_SIZE-1){
b[i][j] = 1;
}else{
b[i][j] = 2;
}
}
}
print_board(b);
return b;
}
// Game
int main(){
// a pointer to an int.
BOARD p, board;
p = set_game();
board = board_status(p);
return 0;
}
it prints:
BOARD array is:
0 2 2 2 2 1
0 2 2 2 2 1
0 2 2 2 2 1
0 2 2 2 2 1
0 2 2 2 2 1
0 2 2 2 2 1
I need now to make an array of arrays, to generate all the next possible boards, for example, when the player 0 moves from b[0][0] to b[0][1], this is one leaf of the branch.
BOARD array is:
2 0 2 2 2 1
0 2 2 2 2 1
0 2 2 2 2 1
0 2 2 2 2 1
0 2 2 2 2 1
0 2 2 2 2 1
How should I allocate this array?
I need an array of branches that will have all the other board_status and after that I will perform my search.
I am not sure about the type of the array, how to declare it? It will be an array of BOARD?
I tried to use this approach, that I found here but seems like there's something wrong. It's giving me an error:
incompatible types when assigning to type ‘branches’ from type ‘int’ array[i] = b[i][j];
//generate ALL possible moves
void generatePossibleMoves(int player){
int i, j;
typedef struct
{
int BOARD[BOARD_SIZE];
} branches;
branches** array = NULL;
void InitBranches( int num_elements )
{
array = malloc( sizeof( branches ) * num_elements);
if( !array )
{
printf( "error\n" );
exit( -1 );
}
for(i = 0; i < num_elements; i++ )
{
for(j = 0; j < BOARD_SIZE; j++ )
{
BOARD b = set_game();
array[i] = b[i][j];
printf("%d", array[i]);
}
printf("\n");
}
}
InitBranches(4);
}
Can anyone help me, please? Thank you.
you should not have a function in a function, move InitBranches out of generatePossibleMoves. Also the typedef struct should be outside of the function.
Your declaration of array and the malloc do not match, you should remove a * in the declaration or add one in the sizeof.
just a guess what you want to do:
BOARD* InitBranches( int num_elements )
{
int i;
BOARD* array = malloc(num_elements * sizeof *array);
if( !array )
{
printf( "error\n" );
exit( -1 );
}
for(i = 0; i < num_elements; i++ )
{
array[i] = set_game();
}
return array;
}
void generatePossibleMoves(int player){
BOARD* array = InitBranches(4);
//do your moves here
}
this will create 4 branches of your board array[0] till array[3].