Swap sub-arrays of a multi-dimensional array in C - c

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;
}

Related

Create a matrix with elements taken by another matrix

I have to implement a function which, given a matrix of 0s and 1s, returns a new matrix that contains the coordinates of the 1s. For example: if matrix is 3x3 and the output is:
1 0 1
0 1 1
0 0 1
New matrix will be 5x2 and the output will be:
0 0
0 2
1 1
1 2
2 2
Some advice? My method would be this:
int matrix[3][3];
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
if (matrix[i][i] == 1){
//Code i need
}
}
}
The solution really depends on the requirement:
Is it allowed to allocate result matrix with the maximum size possible (in this case 9 x 2).
If point 1 is not allowed, is it strictly required to use fixed size array (no dynamic allocation). If this is the case then may need to pass the matrix twice to allocate the right size of array.
Other solution is of course by using dynamic allocation (using malloc etc).
The simplified version of option 1 & 2 is shown below:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int matrix[3][3];
matrix[0][0] = 1;
matrix[0][1] = 0;
matrix[0][2] = 1;
matrix[1][0] = 0;
matrix[1][1] = 1;
matrix[1][2] = 1;
matrix[2][0] = 0;
matrix[2][1] = 0;
matrix[2][2] = 1;
//Solution 1 - If allowed to allocate matrix with size more than the result,
//i.e. if input is 3x3 matrix, then the maximum size of result matrix is 9 x 2
int resultMatrix1[9][2];
int usedCount1=0;
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 1) {
resultMatrix1[usedCount1][0] = i;
resultMatrix1[usedCount1][1] = j;
usedCount1++;
} //end if
} //end for
} //end for
//Print the result
printf("\nSolution 1\n");
for (int i = 0; i < usedCount1; i++){
printf("%d %d\n", resultMatrix1[i][0], resultMatrix1[i][1]);
} //end for
//Solution 2 - strictly allocate matrix with size equal to the result.
//Without using dynamic allocation, meaning we need to have two passes.
//1st pass is to count the element which satisfy the criteria
int usedCount2=0;
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 1) {
usedCount2++;
} //end if
} //end for
} //end for
int resultMatrix2[usedCount2][2]; //allocate the right size
int idx=0;
//2nd pass is to fill in the result matrix
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 1) {
resultMatrix2[idx][0] = i;
resultMatrix2[idx][1] = j;
idx++;
} //end if
} //end for
} //end for
//Print the result
printf("\nSolution 2\n");
for (int i = 0; i < usedCount2; i++){
printf("%d %d\n", resultMatrix2[i][0], resultMatrix2[i][1]);
} //end for
return 0;
}
Results are the same for both solution:
Solution 1
0 0
0 2
1 1
1 2
2 2
Solution 2
0 0
0 2
1 1
1 2
2 2
If matrix[i][j] == 1 what do you know about the coordinates [i,j] ? That they are the coordinates of a 1 :)
Secondly, will the input matrix always be 3x3? If not, you'll want to store the dimensions of the matrix in variables, and use theses variables for your for loops.

C : Processing the columns of a 2D array

#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?

Function not initializing

Hi I have problem with initializing my function for printing an error message if some numbers in an array are same.
#include<stdio.h>
#include<stdlib.h>
void printRepeating(int arr[], int size)
{
int i, j;
for(i = 0; i < size; i++)
for(j = i+1; j < size; j++)
if(arr[i] == arr[j])
printf("Wrong input. Same numbers in array!\n");
}
int main()
{
int arr[200],i;
int res, num;
while((res = scanf("%d", &num)) == 1)
{
arr[i++] = num;
if(num == 0){
break;
}
}
for(i = 0; i < arr[i]; i++)
printf("%d ", arr[i]);
printf("\n");
int arr_size = sizeof(arr[i])/sizeof(arr[0]);
printRepeating(arr, arr_size);
return 0;
}
If I scan 1 2 3 1 4 5 0, my function printRepeating wont start nevertheless I have numbers 1 1 that are same in the array, Why ? And another problem is when I type 1 2 3 1 5 0 it only prints 1 2 3 and for example I when I scan 1 2 3 4 5 6 7 8 9 0 it prints all numbers except for 0.
There are multiple issues in your code. First, initialize i to be 0, and declare a new variable j alongside i,
int arr[200], i = 0, j;
The size of your array would simply be i, which you increment every time you insert an element in the array, and change this,
for(i = 0; i < arr[i]; i++)
printf("%d ", arr[i]);
to this
for(j = 0; j < i; j++)
printf("%d ", arr[j]);
since the size of your array is stored in variable i. Also, the way you are calculating the size of your array is wrong which returns 1 everytime since the numerator and denominator are the same. Generally, it is sizeof(array)/sizeof(array[0]), and in this case, it too, would return 200, since the size of your declared array is 200, but since you increment your i every time at insertion, simply set your arr_size to be i.
int arr_size = i;
This line
int arr_size = sizeof(arr[i])/sizeof(arr[0]);
does not do what you are expecting. You are only dividing the size of two elements of the array, which are always the same size, thus always giving 1 as result. If you want to give the number of elements to the function, give it a variable that you used to count each number as you read them.
Also this:
for(i = 0; i < arr[i]; i++)
printf("%d ", arr[i]);
Is only printing numbers that are not larger than their indices. Again, your program is missing a variable to count the number of input values.

C - Read matrix of unknown size from file

I have file that has 30 matrices and each matrix has unknown size of rows and columns(with a max size of 1000). For instance:
0 5 2
5 0 2
1 6 0
0 9 7 4
3 0 9 1
9 1 0 4
9 4 1 0
I need to read each matrix into a 2d array. What would be the most efficient way of doing this?
This is what I have so far:
int** mat=malloc(1000000*sizeof(int*));
for(i=0;i<1000000;++i)
mat[i]=malloc(4*sizeof(int));
while(!feof(file))
{
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++){
fscanf(file,"%d%*[^\n]%*c",&mat[i][j]);
printf("%d\n", mat[i][j]);
}
}
}
Well the most efficient way is definitely not that. First figure out how big an array you need, then allocate it.
Apparently some matrices are small, so there is no need to allocate the maximum size 1000x1000. One way is to put the matrix in a structure to make it easier to keep track of size:
struct s_matrix
{
int **matrix;
int N; //one side of the square matrix N x N
};
typedef struct s_matrix Matrix;
Then allocate and free the matrix
void allocate_matrix(Matrix *m, int N)
{
m->N = N;
m->matrix = (int**)malloc(N * sizeof(int*));
*m->matrix = (int*)malloc(N * N * sizeof(int));
for (int i = 0; i < N; i++)
m->matrix[i] = *m->matrix + i * N;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
m->matrix[i][j] = 0;
}
void free_matrix(Matrix *m)
{
if (!m) return;
if (!m->matrix) return;
free(*m->matrix);
free(m->matrix);
}
Now we can declare how many matrices we need. It looks like this number is fixed at 30, so I don't think we need dynamic allocation.
int main()
{
const int max_count = 30;
Matrix list[max_count];
for (int i = 0; i < max_count; i++)
list[i].matrix = NULL;
allocate_matrix(&list[0], 3);//allocate 3x3 matrix
allocate_matrix(&list[1], 1000);//1000x1000
allocate_matrix(&list[2], 4000);//4000x4000
int **m;
m = list[0].matrix;
m[0][0] = 0;
m[0][1] = 1;
m[0][2] = 2;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
printf("%02d %s", m[i][j], (j == 2) ? "\n" : "");
//...
for (int i = 0; i < max_count; i++)
free_matrix(&list[i]);
printf("hey it worked, or maybe it didn't, or it did but there is memory leak\n");
return 0;
}

How to efficiently store a triangular matrix in memory?

I want to store a lower triangular matrix in memory, without storing all the zeros.
The way I have implemented it is by allocating space for i + 1 elements on the ith row.
However, I am new to dynamic memory allocation in C and something seems to be wrong with my first allocation.
int main ()
{
int i, j;
int **mat1;
int dim;
scanf("%d", &dim);
*mat1 = (int**) calloc(dim, sizeof(int*));
for(i = 0; i < dim; i++)
mat1[i] = (int*) calloc(i + 1, sizeof(int));
for(i = 0; i < dim; i++)
{
for(j = 0; j < i + 1; j++)
{
scanf("%d", &mat1[i][j]);
}
}
/* Print the matrix without the zeros*/
for(i = 0; i < dim; i++)
{
for(j = 0; j < (i + 1); j++)
{
printf("%d%c", mat1[i][j], j != (dim-1) ? ' ' : '\n');
}
}
return 0;
}
If you want to conserve space and the overhead of allocating every row of the matrix, you could implement a triangular matrix by using clever indexing of a single array.
A lower triangular matrix (including diagonals) has the following properties:
Dimension Matrix Elements/row Total elements
1 x . . . 1 1
2 x x . . 2 3
3 x x x . 3 6
4 x x x x 4 10
...
The total number of elements for a given dimension is:
size(d) = 1 + 2 + 3 + ... + d = (d+1)(d/2)
If you lay the rows out consecutively in a single array, you can use the formula above to calculate the offset of a given row and column (both zero-based) inside the matrix:
index(r,c) = size(r-1) + c
The formulas above are for the lower triangular matrix. You can access the upper matrix as if it was a lower matrix by simply reversing the indexes:
index((d-1)-r, (d-1)-c)
If you have concerns about changing the orientation of the array, you can devise a different offset calculation for the upper array, such as:
uindex(r,c) = size(d)-size(d-r) + c-r
Sample code:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define TRM_SIZE(dim) (((dim)*(dim+1))/2)
#define TRM_OFFSET(r,c) (TRM_SIZE((r)-1)+(c))
#define TRM_INDEX(m,r,c) ((r)<(c) ? 0 : (m)[TRM_OFFSET((r),(c))])
#define TRM_UINDEX(m,r,c,d) ((r)>(c)?0:(m)[TRM_SIZE(d)-TRM_SIZE((d)-(r))+(c)-(r)])
#define UMACRO 0
int main (void)
{
int i, j, k, dimension;
int *ml, *mu, *mr;
printf ("Enter dimension: ");
if (!scanf ("%2d", &dimension)) {
return 1;
}
ml = calloc (TRM_SIZE(dimension), sizeof *ml);
mu = calloc (TRM_SIZE(dimension), sizeof *mu);
mr = calloc (dimension*dimension, sizeof *mr);
if (!ml || !mu || !mr) {
free (ml);
free (mu);
free (mr);
return 2;
}
/* Initialization */
srand (time (0));
for (i = 0; i < TRM_SIZE(dimension); i++) {
ml[i] = 100.0*rand() / RAND_MAX;
mu[i] = 100.0*rand() / RAND_MAX;
}
/* Multiplication */
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
for (k = 0; k < dimension; k++) {
mr[i*dimension + j] +=
#if UMACRO
TRM_INDEX(ml, i, k) *
TRM_UINDEX(mu, k, j, dimension);
#else
TRM_INDEX(ml, i, k) *
TRM_INDEX(mu, dimension-1-k, dimension-1-j);
#endif
}
}
}
/* Output */
puts ("Lower array");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
printf (" %2d", TRM_INDEX(ml, i, j));
}
putchar ('\n');
}
puts ("Upper array");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
#if UMACRO
printf (" %2d", TRM_UINDEX(mu, i, j, dimension));
#else
printf (" %2d", TRM_INDEX(mu, dimension-1-i, dimension-1-j));
#endif
}
putchar ('\n');
}
puts ("Result");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
printf (" %5d", mr[i*dimension + j]);
}
putchar ('\n');
}
free (mu);
free (ml);
free (mr);
return 0;
}
Note that this is a trivial example. You could extend it to wrap the matrix pointer inside a structure that also stores the type of the matrix (upper or lower triangular, or square) and the dimensions, and write access functions that operate appropriately depending on the type of matrix.
For any non-trivial use of matrices, you should probably use a third-party library that specializes in matrices.
mat1 = calloc(dim,sizeof(int*));
mat1 is a double pointer.You need to allocate memory for your array of pointers and later you need to allocate memory to each of your pointers individually.No need to cast calloc()
You are dereferencing mat1 at line 8 before it has even been set to point anywhere. You are allocating an array of pointers to int, but you are not assigning that to mat1 but to the dereference of mat1, which is uninitialized, we don't know what it points to.
So this line:
// ERROR: You are saying an unknown memory location should have the value of calloc.
*mat1 = (int**)calloc(dim,sizeof(int*));
Should change to:
// OK: Now you are assigning the allocation to the pointer variable.
mat1 = (int**)calloc(dim,sizeof(int*));

Resources