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]);
}
}
}
Related
I have created two matrices in C with the following code:
static allocation method
int data[NMAX][NMAX]; // define NMAX 10 is in header
dynamic allocation method
int** data = (int**) malloc(sizeof(int*) * N);
for (int i = 0; i < N; i++) {
data[i] = (int*) malloc(sizeof(int) * M);
}
now i want to insert data into them with ONE function like so:
int inputMatrix(int **data, int N, int M) { ... }
How can i make the same function declaration work for both array types?
Currently it outputs
expected 'int **' but argument is of type 'int ** (*)[10]'
I have tried creating the static array like this:
int* data[NMAX];
for (int i = 0; i < N; i++) {
data[i] = (int[NMAX]) {};
}
but this code produces a matrix with every line being the same after I input numbers into it
The function inputMatrix will take an array whose elements are pointers to int, so you can create an array that holds pointers to each rows of statically allocated array and pass that to the function.
Construction of the pointer array can be done like this:
int data[NMAX][NMAX];
int *pdata[NMAX]; // array of pointers
for (int i = 0; i < N; i++) {
pdata[i] = data[i]; // the array data[i] is converted to pointers to their first elements here
}
##EDI##
You array pointers
int arr[10][5];
int main(void)
{
srand(time(NULL));
fillArray(5, 10, arr);
printArray(5, 10, arr);
}
See the implementations below https://godbolt.org/z/M6GhrEojn
Do not use arrays of pointers. Use array pointers instead. You remove one level of indirection and you can allocate and free it using one function call. As the whole array is a contignous chunk of memory it is much easier for processor yo use the cache.
void *allocateArray(size_t rows, size_t cols)
{
int (*a)[cols] = malloc(rows * sizeof(*a));
return a;
}
and example usage:
void fillArray(size_t cols, size_t rows, int (*arr)[cols])
{
for(size_t row = 0; row < rows; row++)
for(size_t col = 0; col < cols; col++)
arr[row][col] = rand();
}
void printArray(size_t cols, size_t rows, int (*arr)[cols])
{
for(size_t row = 0; row < rows; row++)
{
for(size_t col = 0; col < cols; col++)
printf("[%02zu][%02zu]%d,\t", row, col, arr[row][col]);
printf("\n");
}
}
int main(void)
{
size_t cols, rows;
scanf("%zu,%zu", &rows, &cols);
printf("rows:%zu, cols:%zu", rows, cols);
int (*array)[cols] = allocateArray(rows, cols);
srand(time(NULL));
printf("%p\n", array);
if(array)
{
fillArray(rows, cols, array);
printArray(rows, cols, array);
}
free(array);
}
I was doing the assignment to use pointer to transpose matrices. My code can successfully transpose the first row of the matrix but fail to transpose other rows and columns. I suspect there's some problems with for loops but I cannot find where the problem is. The following attached is my code.
void transposeMatrix(int matrix[ROWS][COLS]){
int** transpose=(int **)malloc(ROWS*sizeof(int*));
for(int i=0; i< ROWS; i++)
transpose[i]=(int*)malloc(COLS*sizeof(int));
for(int i=0; i<ROWS;i++){
puts("");
for(int j=0; j<COLS;j++){
*(transpose+i*ROWS+j)= *(matrix+j*COLS+i);
printf("%d ",transpose[j][i]);
}
puts("");
}
}
The matrix generates random numbers and the problems looks like this:
Original Matrix:
10 20 30
40 50 60
70 80 90
Transpose Matrix:
10 0 43009213
20 3401401 910429
30 0 134910124
I cannot attach the image so the above is just an elaboration of the problem I faced, the real situation is not exactly like that but very similar.
Thank you for your help!
*(transpose+i*ROWS+j) is not the correct way to access elements of an array of pointers. That's the way to access a 2-dimensional array that's stored contiguously in row-major order in an int[] array or through an int* pointer.
The way to access an element of a 2-dimensional array that's implemented as an array of pointers is with *(*(transpose + i)+j). *(transpose + i) returns the pointer to row i, adding j to that returns the address of the j'th column in the row, and deferencing that gets or sets the value.
This will also work with an array declared as
int matrix[ROWS][COLS];
because of the way arrays decay to pointers.
So your assignment line should be:
*(*(transpose + i)+j) = *(*(matrix + j)+i);
Then you need to change the printf() line, because it's not printing the same element you just assigned. It should be:
printf("%d ", transpose[i][j]);
The full working function is:
void transposeMatrix(int matrix[ROWS][COLS]){
int** transpose=(int **)malloc(ROWS*sizeof(int*));
for(int i=0; i< ROWS; i++)
transpose[i]=(int*)malloc(COLS*sizeof(int));
for(int i=0; i<ROWS;i++){
puts("");
for(int j=0; j<COLS;j++){
*(*(transpose + i)+j) = *(*(matrix + j)+i);
printf("%d ",transpose[i][j]);
}
puts("");
}
}
You have problem with identifying memory location for row and col of each cells
Here is the way using them:
i-th rows of transpose = *(transpose + i)
j-th col in i-th row of transpose = *(*(transpose+i) + j)
Similar to matrix:
i-th rows of matrix= *(matrix + i)
j-th col in i-th row of matrix = *(*(matrix+i) + j)
So here is my solution:
void transposeMatrix(int matrix[ROWS][COLS]) {
int** transpose = (int **)malloc(ROWS * sizeof(int*));
for (int i = 0; i < ROWS; i++)
transpose[i] = (int*)malloc(COLS * sizeof(int));
for (int i = 0; i < ROWS; i++) {
puts("");
for (int j = 0; j < COLS; j++) {
*(*(transpose + i) + j) = *(*(matrix + j) + i);
printf("%d ", transpose[i][j]);
}
puts("");
}
}
It's not necessary for you to allocate a new matrix row by row. Also, the functions that do the transpose and printing can be passed straight int * rather than preshaped arrays like int [3][2] etc.
It's even possible to reshape the matrix in place (i.e. without allocating new space). If you like I can post example code for that later.
For instance:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int M[2][3] = { {1, 2, 3}, {7, 8, 9} };
int N[3][3] = { {1, 2, 3}, { 4, 5, 6 }, {7, 8, 9} };
int *alloc_transpose(const int *matrix, size_t rows, size_t cols);
void print_matrix(const int *matrix, size_t rows, size_t cols);
int main()
{
int *t_matrix;
print_matrix(&M[0][0], 2, 3);
fprintf(stderr, "----\n");
t_matrix = alloc_transpose(&M[0][0], 2, 3);
if (t_matrix) {
print_matrix(t_matrix, 3, 2);
}
free(t_matrix);
t_matrix = alloc_transpose(&N[0][0], 3, 3);
if (t_matrix) {
fprintf(stderr, "----\n");
print_matrix(t_matrix, 3, 3);
}
free(t_matrix);
return 0;
}
void print_matrix(const int *matrix, size_t rows, size_t cols)
{
size_t r, c;
for (r = 0; r < rows; r++) {
for (c = 0; c < cols; c++) {
printf("%d ", *((matrix + r * cols) + c));
}
putchar('\n');
}
}
int *alloc_transpose(const int *matrix, size_t rows, size_t cols)
{
int *tm;
int r, c; /* relative to transposed matrix */
tm = malloc(sizeof(int) * cols * rows); /* contiguous is okay */
if (!tm)
return NULL;
for (r = 0; r < rows; r++) {
for (c = 0; c < cols; c++) {
*((tm + c * rows) + r) =
*((matrix + r * cols) + c);
}
}
return tm;
}
I was experimenting some basic C code that defines an int matrix with pointers.
typedef int **Matrix;
Matrix createMatrix(int lines, int columns) {
int i, j;
Matrix m = (Matrix) malloc(sizeof(int) * lines * columns);
for (i = 0; i < lines; ++i) {
for (j = 0; j < columns; ++j) {
m[i][j] = 0;
}
}
return m;
}
int main(int argc, char**argv) {
Matrix m = createMatrix(5, 10);
// ...
if (m[2][3] == 20) {
// ...
}
return 0;
}
However, these m[i][j] accesses are throwing segmentation faults. What's wrong here? Too many asterisks?
I was convinced that a pointer to a pointer to an int was effectively the same as a matrix.
Your allocation of the Matrix data item assumes you're accessing it linearly with a single index. If you want to access it with two indices, e.g., m[1][1] you need to allocate each dimension:
Matrix m = malloc(sizeof(int *) * lines);
for ( int i = 0; i < lines; i++ )
m[i] = malloc(sizeof(int) * columns);
Note also that you should not type cast malloc.
I'm new to C and I'm trying to define a matrix using a struct and some methods that will change the int** field of the struct. The matrix is supposed to be dynamically allocated and also resizable in how many rows it can have. When I run the program below and print out the values of the matrix in main, the matrix just have random values, not the ones inserted in genMatrix() and addRow(). What am I doing wrong? Very grateful for any help.
I define the struct like this:
typedef struct matrix {
int** matrix;
int rows;
int cols;
int capacity;
} matrix;
And then have the following methods that should change the field of the struct:
matrix* genMatrix() {
matrix* matrix = malloc(sizeof(matrix));
initMatrix(matrix, 100, 3, 200);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
int row[] = {i+j, i*j, i-j};
addRow(matrix, row);
}
}
return matrix;
}
void initMatrix(matrix* matrix, int rows, int cols, int capacity) {
matrix->matrix = malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
matrix->matrix[i] = malloc(cols * sizeof(int));
}
matrix->cols = cols;
matrix->rows = rows;
matrix->capacity = capacity;
}
void addRow(matrix* matrix, int* row) {
if (matrix->rows == matrix->capacity) {
matrix->capacity *= 2;
matrix->matrix = realloc(matrix->matrix, matrix->capacity * sizeof(int*));
}
matrix->matrix[matrix->rows++] = row;
}
And in main I call the function genMatrix and then print the result out, but get random values like 32691, -1240670624 etc.
int main() {
matrix* matrix = genMatrix();
}
WHen you try to add a row here:
int row[] = {i+j, i*j, i-j};
addRow(matrix, row);
the data you are adding is a temporary local variable. On the next loop iteration it will get overwritten and then when the loop exits it will go out of scope.
You need to allocate some memory for the new row data, e.g. using malloc:
int * row = malloc(3 * sizeof(int));
row[0] = i+j;
row[1] = i*j;
row[2] = i-j;
addRow(matrix, row);
Don't forget to free all these row allocations later when you're done with the matrix.
You are storing row, a local variable. This pointer ceases to be valid once its scope ends:
for (int j = 0; j < 10; j++) {
int row[] = {i+j, i*j, i-j};
addRow(matrix, row);
}
You must dynamically allocate memory for the row data, too.
row is a local variable.As soon as loop goes for new iteration data gets overwritten and after loop exits data goes out of scope .
So use
int * row = malloc(NumOfRows * sizeof(int));
and then row members.
I am new to C and during my learning I want to return a two dimensional array from a function, so that I can use it in my main program. Can anyone explain me the same with example. Thanks in advance.
It depends how it is implemented. You can either work with just a one-dimensional array where you know the length of each (row) and the next row begins immediately after the previous one. OR, you can have an array of pointers to arrays. The extra cost though is you need to de-reference two pointers to get to one element of data.
// 2D array of data, with just one array
char* get_2d_ex1(int rows, int cols) {
int r, c, idx;
char* p = malloc(rows*cols);
for (r=0; r<rows; r++) {
for (c=0; c<cols; c++) {
idx = r*cols + c; // this is key
p[idx] = c; // put the col# in its place, for example.
}
}
return p;
}
Declare your function as returning a pointer to a pointer. If we use int as an example:
int **samplefunction() {
int** retval = new int*[100];
for (int i = 1; i < 100; i++) {
retval[i] = new int[100];
}
// do stuff here to retval[i][j]
return retval;
}
Here's an example of how you might create, manipulate and free a "2d array":
#include <stdlib.h>
#define ROWS 5
#define COLS 10
int **create_2d_array(size_t rows, size_t cols)
{
size_t i;
int **array = (int**)malloc(rows * sizeof(int*));
for (i = 0; i < rows; i++)
array[i] = (int*)malloc(cols * sizeof(int));
return array;
}
void free_2d_array(int **array, size_t rows, size_t cols)
{
size_t i;
for (i = 0; i < rows; i++)
free(array[i]);
free(array);
}
int main(void)
{
int **array2d = create_2d_array(ROWS, COLS);
/* ... */
array2d[3][4] = 5;
/* ... */
free_2d_array(array2d, ROWS, COLS);
return 0;
}
To create a "2d array"/matrix, all you have to do is create a dynamic array of pointers (in this case int*) of the size of the rows/width:
int **array = (int**)malloc(rows * sizeof(int*));
Then you set each of those pointers to point to a dynamic array of int of the size of the columns/height:
array[i] = (int*)malloc(cols * sizeof(int));
Note that the casts on malloc aren't required, it's just a habit I have.