How to traverse through a column in a 2D array - c

Given array A[3][2] ={(1,2),(3,4),(5,6)}
I want to traverse through the first column elements i.e 1,3,5 and next column elements, 2,4,6. All this must be done using a single pointer. How to do this?

If you have 2 array indices, use two for loops.
uint32_t m, n, sum = 0U;
for(n = 0U; n < 2; ++n){ // For each column [n]
for(m = 0U; m < 3; ++m){ // For each row [m] in column [n]
sum += A[m][n];
}
}
Edit: There's not really a difference when using pointers (especially once passed into a function, when it decays). But you have to deal with dereferencing the pointer. This code is more type obfuscating, and could lead one to improperly type/reference, if you don't compile with sufficient warning flags.
uint32_t A[3][2] = {{1,2},{3,4},{5,6}};
uint32_t m, sum = 0U;
uint32_t (*pa2_n)[2];
uint32_t * p_m;
for(pa2_n = &A[0]; pa2_n < &A[3]; ++pa2_n){ // For each column [n]
for(m = 0U; m < 2U; ++m){ // For each row [m] in column [n]
sum += (*pa2_n)[m];
}
// Or
for(p_m = &(*pa2_n)[0]; p_m < &(*pa2_n)[2]; ++p_m){ // For each row [m] in column [n]
sum += *p_m;
}
}
printf("Hello World %u\n", sum);

//
// a method using only 1 pointer could rely on pointer math
//
#include <stdio.h>
#define ROWS 3
#define COLS 2
int
main(void)
{
int matrix[ROWS][COLS] = {
{ 1, 2 },
{ 3, 4 },
{ 5, 6 },
};
int *ptr = &matrix[0][0];
while (1) {
printf("%d,", *ptr);
// point into the next row, same col
ptr += COLS;
// now pointing at least 1 row too many?
if (ptr >= &matrix[ROWS][0]) {
printf("\n");
// at least 1 row too many, last col?
if (ptr >= &matrix[ROWS][COLS - 1])
break;
// backup by total element count - 1 (first row, next col)
ptr -= (ROWS * COLS) - 1;
}
}
return (0);
}

If you want to traverse in the given array int A[3][2] using single pointer you should look at this code:
#include <stdio.h>
int main(void)
{
int arr[3][2] = { 1, 2, 3, 4, 5, 6 };
int *ptr = arr[0], i, j;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 3; j++)
{
printf("%4d", *(ptr+j*2+i));
}
putchar('\n');
}
return 0;
}
I assume you know about the memory representation of a 2D array. If you don't then I'll tell you in short.
A 2D array is stored in the computer's memory on consecutive locations, i.e. one row after another.
That is elements of arr in the above code, will be stored as first 1, second 2, and so on. Using this *(ptr+j*2+i) statement we are traversing through the array. In 1st iteration we are printing ptr+0 then ptr+2 and so on.
Or you can make it simple by declaring a pointer to an array
int (*ptr)[2]; ptr = arr;
and now you can access elements of arr using ptr just like a 2D array.
printf("%4d", ptr[j][i]); or printf("%4d", *(*(ptr+j)+i));
I hope you'll understand the answer.

Related

Using functions to lesser repetitiveness

I have been working on this problem for a while now: basically I need to put the for loop in a function so I can call for it, but I don't how to to make a function return a 2D array, I want to solve this by creating a 1D array, but the problem is that my task is to compute the sum of numbers under the diagonal of a matrix, so I need it to be 2D first, then it can only become 1D. Does anyone have a solution?
Maybe my thought process is just wrong and somebody could just recommend how to put the for loops in functions? If it was without the if clause inside then I might have an idea, but now I really don't.
#include <math.h>
#include <stdio.h>
#include <stdlib.h> // libraries added from example
#include <time.h>
//(*) For a square matrix calculate the sum of elements under the main diagonal excluding it.
#define A -10
#define B 10
int main() {
void enter(int *x, int *y);
int get_random(int lbound, int ubound); // telling the programs that functions are declared
int r;
int c;
int row, col, sum = 0;
enter(&r, &c); // calling the function
srand48(time(NULL)); //Call srand48 with current time reported by `time` casted to a long integer.
// srand48 is used to reinitialize the most recent 48-bit value in this storage
int array[r][c]; // we decided its gonna be r rows and c columns
int line[r * c]; // turning 2d into 1d array
for (row = 0; row < r; ++row) // we cycle numeration of rows of matrix
{
for (col = 0; col < c; col++) // we cycle numeration of columns of matrix
{
array[row][col] = get_random(B, A);// filling array with random numbers, taken from example
printf("%d ", array[row][col]);
if (row > col) { //since we want the sum numbers below the diagonal row>col must be true
sum = sum + array[row][col];// if row>col then we add the number to our sum;
};
}
printf("\n"); // this is to break line after row 1,2 col 3, so it looks nicer
}
for (row = 0; row < r; ++row) // we cycle numeration of rows of matrix
{
for (col = 0; col < c; col++) // we cycle numeration of columns of matrix
{
line[row * r + col] = array[row][col];
}
}
printf("the array in 1D: ");
for (row = 0; row < r * c; row++) {
printf("%d ", line[row]);
}
printf("\n");
printf("sum of array below the diagonal: %d\n", sum);
return 0;
}
void enter(int *x, int *y) { // we have to use pointers if we want more then one return from a function
printf("How man rows in array? "); // just like the last lab we decide how big the matrix will be
scanf("%d", x); // we use x instead of &x because we need the address of the number not the value
printf("How man columns in array? ");
scanf("%d", y); // we use y instead of &y because we need the address of the number not the value
}
int get_random(int lbound, int ubound) {
return mrand48() % (ubound - lbound + 1) + lbound; // function for generating random numbers
}
Conditions have to be met:
the user decides size of square matrix
the matrix has to be filled with random numbers
the array is called by the function has to be 1D using i*N+j, 2D array can't be passed
Let's consider your assignment
Conditions have to be met:
the user decides size of square matrix
the matrix has to be filled with random numbers
the array is called by the function has to be 1D using i*N+j, 2D
array can't be passed
Firstly the matrix must be square.
So this your function
void enter(int *x, int *y) { // we have to use pointers if we want more then one return from a function
printf("How man rows in array? "); // just like the last lab we decide how big the matrix will be
scanf("%d", x); // we use x instead of &x because we need the address of the number not the value
printf("How man columns in array? ");
scanf("%d", y); // we use y instead of &y because we need the address of the number not the value
}
does not make sense. The user can enter different values for the numbers of rows and columns of the matrix. You need to enter only one positive value.
Secondly as we are speaking about a matrix then it means that you have to define a two-dimensional array.
Also you need to write a function that will calculate the sum of elements under the main diagonal of a matrix. The function is declared such a way that it can accept only a one-dimensional array. This means that you need to pass your matrix to the function casting it to a pointer of the type int *. There is no need to create an auxiliary one-dimensional array,
Here is a demonstration program that shows how the function can be declared and defined and how the matrix can be passed to the function.
#include <stdio.h>
long long int sum_under_dioganal( const int a[], size_t n )
{
long long int sum = 0;
for (size_t i = 1; i < n; i++)
{
for (size_t j = 0; j < i; j++)
{
sum += a[i * n + j];
}
}
return sum;
}
int main( void )
{
enum { N = 5 };
int a[N][N] =
{
{ 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 2, 3, 0, 0, 0 },
{ 4, 5, 6, 0, 0 },
{ 7, 8, 9, 10, 0 }
};
printf( "sum of elements under the main diagonal = %lld\n",
sum_under_dioganal( ( int * )a, N ) );
}
The program output is
sum of elements under the main diagonal = 55
Another approach to define the function and call it is the following
#include <stdio.h>
long long int sum_under_dioganal( const int a[], size_t n )
{
long long int sum = 0;
size_t m = 0;
while (m * m < n) ++m;
if (m * m == n)
{
for (size_t i = 1; i < m; i++)
{
for (size_t j = 0; j < i; j++)
{
sum += a[i * m + j];
}
}
}
return sum;
}
int main( void )
{
enum { N = 5 };
int a[N][N] =
{
{ 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 2, 3, 0, 0, 0 },
{ 4, 5, 6, 0, 0 },
{ 7, 8, 9, 10, 0 }
};
printf( "sum of elements under the main diagonal = %lld\n",
sum_under_dioganal( ( int * )a, N * N ) );
}
The program output is the same as shown above.
sum of elements under the main diagonal = 55
2d arrays don't really exist. The compiler just allows you to write a[i][j] so that you can believe in them. Here's some simple code to demonstrate a few methods:
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void *
make_array(size_t size)
{
int *a = malloc(sizeof *a * size * size);
int *t = a;
if( a == NULL ){
perror("malloc");
exit(1);
}
for( int row = 0; row < size; row += 1 ){
for( int col = 0; col < size; col += 1 ){
*t++ = rand() % 32 - 16;
}
}
return a;
}
int
trace(void *v, size_t s)
{
int *a = v;
int sum = 0;
for( size_t i = 0; i < s; i += 1 ){
sum += *a;
a += s + 1;
}
return sum;
}
int
main(int argc, char **argv)
{
srand(time(NULL));
size_t s = argc > 1 ? strtol(argv[1], NULL, 0) : 5;
void *v = make_array(s);
/* a, b, c, and d will demonstrate different access techniques */
int *a = v; /* a is the conventional "1-d array" (1)*/
int (*b)[s] = v; /* b is a "two-d" array */
int *c = v; /* c iterates through each element */
int *d = v; /* d treats each row as a 1-d array */
for( int i = 0; i < s; i += 1 ){
for( int j = 0; j < s; j += 1 ){
printf("%3d ", b[i][j]);
assert( a[i * s + j] == b[i][j] );
assert( *c == b[i][j] );
assert( d[j] == b[i][j] );
c += 1;
}
d += s;
putchar('\n');
}
printf("trace: %d\n", trace(v, s));
}
/* (1) These comments are not strictly accurate. `a` is *not* an
* array, and `b` is *not* a 2-d array. `a` is a pointer, and `b` is
* an array of pointers. Arrays are not pointers, and pointers are
* not arrays.
*/

Get pointer to column of 2D array in C

I am new to C programming and especially to pointers. In the program I wrote, I tried to write a function that returns a pointer to specified column of array. See the code below for better understanding (or confusion :) ):
#include <stdio.h>
#include <stdlib.h>
// function for getting pointer to specidifed column index
// 'ind' is index of requested column, 'ncol' is number of items in column
int* get_col(const int* arr, unsigned int ind, unsigned int ncol);
int main() {
unsigned int n;
printf("Input matrix size : ");
scanf("%i", &n);
int arr[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
arr[i][j] = i * n + j;
}
for (int i = 0; i < n; i++) {
printf("values in column %d: \n", i);
int *col = get_col((int*)arr, i, n);
for (int j = 0; j < n; j++) {
printf("%d ", *col);
col = col + 1;
}
printf("\n");
}
return 0;
}
int* get_col(const int* arr, unsigned int ind, unsigned int ncol) {
int *result = malloc(sizeof(int) * ncol);
for (int i = 0; i < ncol; i++)
*result = *(arr + i*ncol + ind);
return result;
}
As you see get_col function accepts pointer to array, column index and column size (n of elements in column, i.e number of rows) as arguments and trying to return a pointer to 1D array that contains values of column at requested index. The problem is that result is not correct. In case n=3 results are like below:
Input matrix size : 3
values in column 0:
6 0 0 // supposed to be 0 3 6
values in column 1:
7 0 0 // supposed to be 1 4 7
values in column 2:
8 0 0 // supposed to be 2 5 8
I think that the problem lies in my understanding of pointers not the algorithm implemented. Actually, at first I didn't use pointer in my get_col function like below:
int result[ncol];
// ... do my work here to populate array
return &result;
Then as compiler complains warning: function returns address of local variable [-Wreturn-local-addr], I converted result from array to pointer in get_col function like above. What is the problem in this code? Did I use pointers in get_col function as it should be?
In the following line:
*result = *(arr + i*ncol + ind);
You're always writing to the same memory address.
Change it to one of the two following options:
*(result + i) = *(arr + i*ncol + ind);
result[i] = *(arr + i*ncol + ind);
Regarding your second problem when you used:
int result[ncol];
// ... do my work here to populate array
return &result;
You should understand that result variable in this case (static-memory allocation) is stored in the stack. So, after your function returns, the variable values doesn't exist anymore in the memory. That's why you need dynamic-memory allocation. In dynamic-memory allocation, that values stay in the memory until you call free by yourself.

Create a variable size matrix

I am trying to create a variable matrix using a function that inputs an empty array pointer m and outputs the int array pointer m with values 1,2,3,4,...n elements in the matrix. I use the variable k and increment the value upwards to accomplish this (not sure if this is the best way).
I am getting a subscripted value is not an array, pointer, or vector in my for loop here matrix[i][j] = k++; and I am not really sure why it is only appearing inside the for loop and nowhere else.
If I am inputting an int array pointer called matrix, I shouldn't be getting this error right?
int *create_matrix(int* matrix) {
int i,j;
int k = 0;
// 'total' will be 70 = 10 * 7
int total = sizeof(matrix);
// 'column' will be 7 = size of first row
int column = sizeof(matrix[0]);
// 'row' will be 10 = 70 / 7
int row = total / column;
for (i=0; i < row; i++) {
for (j=0; j < column; j++) {
matrix[i][j] = k++;
}
}
return matrix;
}
int main(void) {
// Creating a custom matrix.
int m[3][4] = {0};
create_matrix(*m);
return 0;
}
You need to learn the difference between arrays and pointers. You can point a pointer to a matrix, but the information about size and number of dimensions are lost as long as you're only accessing the array via the pointer.
You would need to do something like this:
int *create_matrix(int* matrix, size_t size_x, size_t size_y) {
...
}
int main()
{
int m[3][6];
size_t size_y=sizeof m[0]/sizeof m[0][0];
size_t size_x=sizeof m / sizeof m[0];
create_matrix(m);
}
To do
int m[3][4] = {0};
create_matrix(*m);
is equivalent of
int m[3][4] = {0};
create_matrix(m[0]);
so is equivalent of having
int m[4] = {0};
create_matrix(m);
// 'total' will be 70 = 10 * 7
int total = sizeof(matrix);
matrix is a int *, sizeof(matrix) values 4 if an address uses 32b and 8 if an address uses 64b
The effective size of matrix in main is not relevant
// 'column' will be 7 = size of first row
int column = sizeof(matrix[0]);
matrix[0] is an int, so you get the size of an int (4 or 8 probably)
matrix[i][j] = k++;
because matrix is an int * the form matrix[i][j] is invalid.
To name it matrix is not helpful.
Your program can be :
#include <stdio.h>
void fill_matrix(int matrix[][4], size_t row) {
size_t i, j;
int k = 0;
for (i=0; i < row; i++) {
for (j=0; j < sizeof(matrix[0])/sizeof(int); j++) {
matrix[i][j] = k++;
}
}
}
int main(void) {
// Creating a custom matrix.
int m[3][4] = {0};
fill_matrix(m, sizeof(m)/sizeof(m[0]));
size_t i, j;
for (i=0; i < sizeof(m)/sizeof(m[0]); i++) {
for (j=0; j < sizeof(m[0])/sizeof(int); j++) {
printf("matrix[%d][%d] = %d\n", i, j, m[i][j]);
}
}
return 0;
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wextra m.c
pi#raspberrypi:/tmp $ ./a.out
matrix[0][0] = 0
matrix[0][1] = 1
matrix[0][2] = 2
matrix[0][3] = 3
matrix[1][0] = 4
matrix[1][1] = 5
matrix[1][2] = 6
matrix[1][3] = 7
matrix[2][0] = 8
matrix[2][1] = 9
matrix[2][2] = 10
matrix[2][3] = 11
Probably it is more visible if you initialize each cell of the matrix with i*10+j rather than with k++, in that case that prints :
matrix[0][0] = 0
matrix[0][1] = 1
matrix[0][2] = 2
matrix[0][3] = 3
matrix[1][0] = 10
matrix[1][1] = 11
matrix[1][2] = 12
matrix[1][3] = 13
matrix[2][0] = 20
matrix[2][1] = 21
matrix[2][2] = 22
matrix[2][3] = 23
Your attempt is a reasonable attempt but it reveals some misconceptions about how objects in C work. That's all right. Yours is a good teaching example and I believe that you will be glad that you have made it. Now try this:
static const int NO_ROWS = 3;
static const int NO_COLUMNS = 4;
int *create_matrix(
int *const matrix, const int no_rows, const int no_columns
) {
int k = 0;
for (int i = 0; i < no_rows; i++) {
for (int j = 0; j < no_columns; j++) {
matrix[no_columns*i+j] = k++;
}
}
return matrix;
}
int main(void) {
// Creating a custom matrix.
int m[NO_ROWS][NO_COLUMNS];
create_matrix(m[0], NO_ROWS, NO_COLUMNS);
return 0;
}
Your matrix is constructed as an array of arrays. However, in C, an array is just a region of storage in which a sequence of objects of the same type (in your case, int) can be kept. The symbol m is interpreted by the C compiler as
meaning the address of the matrix's initial element—or, more precisely, because your matrix is an array of arrays, the address of the matrix's initial row; and
referring to the type of the matrix's initial row, which is itself an array type, int[NO_COLUMNS].
The problem is that there exists no really neat, direct way to specify to a precompiled function the type int[NO_COLUMNS] unless you are willing to hard-code the type. Therefore, one relatively straightforward way to treat the matrix within create_matrix() would be as a single, linear array, as shown.
One point to grasp here is that C does not understand the shape of your matrix. Rather than rows and columns, C sees a linear region of storage.
Another point to grasp is that function to which an array is passed receives only the array's initial address. If it needs the size, that must be separately passed.

Treating one dimensional array as two dimensional at run time

I have some data stored in a one dimensional array of size say 'M'. Now I need to treat it as a two dimensional array with dimension NxP, where the product of N and P is equal to M. I know the values of N and P only at runtime. How can I implement such a function in C?
int array[M]; /* one dimensional array where some data is stored*/
int** newArray; /* the dimension of newArray should be NxP such that we can access the data in 'array' as a two-dimensional array*/
Just cast it to the appropriate array pointer type:
int (*newArray)[N] = (int (*)[N])array;
After that, you can access the array with:
for(int y = 0; y < P; y++) {
for(int x = 0; x < N; x++) {
array[y][x] = 42;
}
}
This is equivalent to the following indexing:
for(int y = 0; y < P; y++) {
for(int x = 0; x < N; x++) {
newArray[y*N + x] = 42;
}
}
This works even if N is only known at run time since C99. Note that you do not need to set up an index array that way, as you would have to do if you used an int**.
You don't need to define a new array. You can use the existing one.
Assuming you know N and P, and N is the number of rows, you can access item (i,j) as:
array[i*N + j]
You could do it like this:
int ** newArray = malloc(sizeof(int*) * N);
for (i = 0; i < N; ++i) {
newArray[i] = array[i * J];
}
This will make an array that "looks" just like a dynamically allocated 2D array of N rows and J columns, but in fact points to the rows of the 1D array.
That way if you have functions to operate on 2D arrays already, you don't need to rewrite them to use the 1D syntax described in other answer.
The runtime makes this a little harder, but :-
newArray = malloc( sizeof( int*) * N ); /* create an array of pointers.
{
size_t i;
for( i = 0; i < N; i++ ) {
newArray[i] = &array[ i* P];
}
}
/* Now newArray[i][j] is usable */
You can just cast the 1d array as the 2d array you want. It's just a block of memory.
int _tmain(int argc, _TCHAR* argv[])
{
int oneDArray[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
int(*twoDArray)[3] = (int(*)[3])&oneDArray[0]; // This is the magic line!
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
printf("i: %d j: %d value: %d\r\n", i, j, twoDArray[i][j]);
}
}
_getch();
return 0;
}
Also see question Convert Array Question
There's some inherent unsafeness in doing this, but your question states that NxP=M, so if that's true it will work. People will frown at it though.

Iterating 2D array with pointer expressions in C

I'm practicing pointers and want to substitute pointer operations in place of the arrays to traverse through the elements of the array. I have read numerous articles and cannot grasp this concept. Can someone explain?
Here I made a 2D array and iterated through it using a basic nested for-loop, but want to use pointers;
int test[3][2] = {1,4,2,5,2,8};
for (int i = 0 ; i < 3; i++) {
for (int j = 0; j < 2; j++) {
printf("%d\n", test[i][j]);
}
}
int test[3][2] = {{1,4},{2,5},{2,8}};
// Define a pointer to walk the rows of the 2D array.
int (*p1)[2] = test;
// Define a pointer to walk the columns of each row of the 2D array.
int *p2 = NULL;
// There are three rows in the 2D array.
// p1 has been initialized to point to the first row of the 2D array.
// Make sure the iteration stops after the third row of the 2D array.
for (; p1 != test+3; ++p1) {
// Iterate over each column of the arrays.
// p2 is initialized to *p1, which points to the first column.
// Iteration must stop after two columns. Hence, the breaking
// condition of the loop is when p2 == *p1+2
for (p2 = *p1; p2 != *p1+2; ++p2 ) {
printf("%d\n", *p2);
}
}
In some compilers you can also use a single loop, treating a multidimensional array as a one-dimensional array read in row-major order.
This is mentioned in King's C Programming: A Modern Approach (2nd ed., p268).
#include <stdio.h>
int main(void)
{
int test[3][2] = {{1,4},{2,5},{2,8}}, *p;
for(p = &test[0][0]; p <= &test[2][1]; p++)
{
printf("%d\n", *p);
}
return 0;
}
Try the following and investigate
#include <stdio.h>
int main(void)
{
int test[3][2] = { { 1,4 }, { 2,5 }, { 2,8 } };
for ( int ( *p )[2] = test ; p != test + 3; ++p )
{
for ( int *q = *p; q != *p + 2; ++q ) printf( "%d ", *q );
puts( "" );
}
return 0;
}
The putput is
1 4
2 5
2 8
The first pointer is a pointer to an object of type int[2] that is it points to the first "row" of the array and then due to increments it points to other rows.. The second pointer is a pointer to an object of type int. It points to the first element of each row in the inner loop.
Treating a 2d array as 1d array is very easy using pointer arithmetic to iterate.
void print_2d_array(int *num, size) {
int counter = 0;
while (counter++ < size) {
printf("%i ", *num);
num++;
}
printf("\n");
}
int main() {
int matrix[2][3] = {{2, 11, 33},
{9, 8, 77}};
int matrix_size = sizeof(matrix) / sizeof(int); // 24 bytes / 4 (int size) = 6 itens
print_2d_array(matrix, matrix_size);
return 0;
}
If pointer declaration is the goal of your practice, use the following initialization:
int (*pTest)[rmax][cmax] = test;
Once you do that, the syntax of using pointer indexing mirrors that of array indexing, except that you have to use the * de-referencing operator.
for (int i= 0; i < 3; i++) {
for (int j= 0; j < 2; j++) {
printf ("%d ", *(pTest[i][j]));
}
printf ("\n");
}
However, if pointer arithmetic is the goal of your practice, then the following will work too:
int *res = &test;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
printf ("%d ", *(res + i*2 + j));
}
printf ("\n");
}
OUTPUT
1 4
2 5
2 8

Resources