How to access elements of a matrix array via pointers in C? - c

I can't seem to find any info on how to access elements of an array via pointer in a function, I tried following multiple answers but none of them seem to work for me.
My task is next: Write a program in C with m x n dimension with elements being randomly generated from 0 to 9. Using two new functions calculate the sum of even elements and count the number of elements being equal to zero.
#include <stdio.h>
#include <stdlib.h>
void SumEven(int *a, int n, int m, int *sum){
}
void EqualToZero(int *a, int n, int m, int *number){
}
int main()
{
int** a;
int m, n, l, i, j, r, sum;
printf("Enter number of columns for matrix: ");
scanf("%d", &m);
printf("Enter number of rows for matrix: ");
scanf("%d", &n);
a = (int **) malloc(m*sizeof(int));
for (l = 0 ; l < m ; l++){
a[l] = (int **) malloc(n*sizeof(int));
}
time_t t;
srand((unsigned)time(&t));
printf("\n");
printf("Your matrix is:\n");
printf("\n");
for(i = 0 ; i < m ; i++){
for(j = 0 ; j < n ; j++){
r = rand() % 10;
a[i][j] = r;
printf("%d ", r);
}
printf("\n");
}
printf("\n");
SumEven(&a, n, m);
return(0);
}
As you can see in the provided code I left those functions empty as I don't know how to pass the matrix to them and access their elements so I can be able to print my results.
Also my pseudo code for the logic for the functions themselves are:
if(a[i][j] % 2 == 0)
printf("%d ", a[i][j])
and
if(a[i][j] == 0)
printf("%d ", a[i][j])
Also those parameters of the function are predefined in my task, so I have to follow them.
EDIT: I also don't know if I'm even passing the same matrix to the function with SumEven(&a, n, m);. I tried outputing the address of the matrix and using printf("%d", &a) to display an address both from main() and SumEven() functions.

This code may help. It does the following:
1. For an arbitrary array of integers, sum the elements of the array
- using a pointer to the SUM function
2. For an arbitrary array of integers, count the number of zero elements in
the array - using a pointer to the COUNTZERO function
#include <stdio.h>
#include <stdlib.h>
// sum the elements of the matrix
void sum(int* arr, int rows, int cols, int* result)
{
int sum = 0;
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
sum = sum + arr[i*cols + j];
}
}
*result = sum;
}
// count the number of zero elements in the matrix
void countZero(int* arr, int rows, int cols, int* result)
{
int count = 0;
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
if (arr[i*cols + j] ==0) count = count + 1;
}
}
*result = count;
}
// arbitrary initialisation of 2D array of ints (force last entry of the array to equal zero - for testing purposes)
void init2D(int *arr, int rows, int cols) {
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
arr[i*cols + j] = 1;
}
}
// use this to test the countZero function
arr[(rows-1)*(cols-1)] = 0;
}
int main() {
int *array; // will hold a 2D array of integers
int N = 10; // arbitrary number of rows
int M = 5; // arbitrary num cols
// 2D array of integers expressed as one "contiguous row" of memory
// make sure your indexing is correct when referenceing the array for (i,j)th element
array = (int*)malloc(sizeof(int)*N*M);
if (array != NULL) {
init2D(array, N, M);
}
// the function pointer
void(*general)(int*,int,int,int*);
// will contain the sum result
int sumAll = 0;
int* ptsumAll = &sumAll;
// make the function pointer point to the sum function
general = ∑
// sum the contents of the array
general(array,N,M, ptsumAll);
printf("sum of array elements: %d\n", *ptsumAll);
// contains a count of the zero elements in the array
int count =0;
int* ptcount = &count;
// make the function pointer point to the count function
general = &countZero;
// count the number of zero element in the array
general(array, N, M,ptcount);
printf("number of zeros: %d\n", *ptcount);
free(array);
return 0;
}
some references:
https://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html
http://www.cprogramming.com/tutorial/function-pointers.html

I have added comments to help you with the code.
#include <stdio.h>
#include <stdlib.h>
void SumEven(int *a, int n, int m, int *sum){
//put this statement in 2 nested for loops of size n and m
if(a[i][j] % 2 == 0)
sum += a[i][j];
}
void EqualToZero(int *a, int n, int m, int *number){
//put this statement in 2 nested for loops of size n and m
if(a[i][j] == 0)
number++;
}
int main()
{
int** a;
int m, n, l, i, j, r, sum;
printf("Enter number of columns for matrix: ");
scanf("%d", &m);
printf("Enter number of rows for matrix: ");
scanf("%d", &n);
a = (int **) malloc(m*sizeof(int));
//should be m*sizeof(int*)
for (l = 0 ; l < m ; l++){
a[l] = (int **) malloc(n*sizeof(int));
//should be cast as (int*)
}
//I suggest you take look at declaring 2d arrays in C
time_t t;
srand((unsigned)time(&t));
printf("\n");
printf("Your matrix is:\n");
printf("\n");
for(i = 0 ; i < m ; i++){
for(j = 0 ; j < n ; j++){
r = rand() % 10;
a[i][j] = r;
printf("%d ", r);
}
printf("\n");
}
printf("\n");
SumEven(&a, n, m);
//need to pass &sum to this function. Also make sure it is initialized to 0
//call EqualToZero() function with proper parameters.
return(0);
//return 0; not return(0);
}

These will be your function prototypes:
void SumEven(int **a, int n, int m,int *sum);
void EqualToZero(int **a, int n, int m,int *number);
since you are passing a(double pointer) from calling then the there should be a double pointer(int **a) to receive it.
Calling:
SumEven(a, n, m,&sum);
EqualToZero(a, n, m,&number);
And this is how you can access the array inside your function:
void SumEven(int **a, int n, int m,int *sum){
int i,j,tsum=0;
for(i = 0 ; i < m ; i++){
for(j = 0 ; j < n ; j++){
if(a[i][j] % 2 == 0)
{
tsum+=a[i][j];
printf("%d ",a[i][j]);
}
}
}
*sum=tsum;
}
Also there is an error in this line a[l] = (int **) malloc(n*sizeof(int)); (‘int**’ to ‘int*’assignment),it should be a[l] = (int *) malloc(n*sizeof(int));.

Here's an example, given a 3D array
int buffer[5][7][6];
An element at location [2][1][2] can be accessed as buffer[2][1][2] or *( *( *(buffer + 2) + 1) + 2).
Reference

if(( *(*(a + i) + j) % 2 ) == 0 )
printf("%d", *(*(a + i) + j) )
if( *(*(a + i) + j) == 0 )
printf("%d", *(*(a + i) + j) )
This is how you do it.

Related

I'm not able to read my matrix dynamically

My program crashes when it comes to the reading function, at the scanf line. What can I do?
I'm guessing it's an issue with the way I wrote (*(a + i) + j) but I can't tell.
void read(int **a, int n)
{
int i, j;
for(i=0;i<n;i++)
for (j = 0; j < n; j++)
{
printf("a[%d][%d]=", i, j);
scanf("%d", (*(a + i) + j)); //Access violation writing location
}
}
void show(int**a, int n)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
{
printf("%d", *(*(a + i) + j));
}
}
int main()
{
int n,opt,a;
printf("number of lines and columns:");
scanf("%d", &n);
a = (int**)malloc(n*n * sizeof(int));
while (1)
{...
A dynamic 2D n x n array is allocated using this code:
int (*a)[n] = malloc(n * sizeof *a);
It means: Declare a as pointer to an integer array with n element and allocate n of those arrays (i.e. n * sizeof *a). In that way it ends up with n x n integers.
So a full version of your code could be like:
#include <stdio.h>
#include <stdlib.h>
void read(int n, int a[][n])
{
int i, j;
for(i=0;i<n;i++)
for (j = 0; j < n; j++)
{
printf("a[%d][%d]=\n", i, j);
scanf("%d", &a[i][j]);
}
}
void show(int n, int a[][n])
{
int i, j;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
printf("%d ", a[i][j]);
}
puts("");
}
}
int main(void)
{
int n = 0;
printf("number of lines and columns:\n");
scanf("%d", &n);
if (n < 1) exit(1);
int (*a)[n] = malloc(n * sizeof *a);
read(n, a);
show(n, a);
free(a);
return 0;
}
note : To keep it simple I skipped all check of scanf return values. In real code, the scanf return value shall always be checked.
There is nothing wrong with allocating a block using malloc ( n * n * sizeof *a);
The address of the block must be assigned to a pointer int *a
Elements can be accessed by (a + i * n + j) or a[i * n +j]
void read(int *a, int n)
{
int i, j;
for(i=0;i<n;i++)
for (j = 0; j < n; j++)
{
printf("a[%d][%d]=", i, j);
scanf("%d", (a + i * n + j));
// scanf("%d", &a[i * n + j]);
}
}
void show(int *a, int n)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
{
printf("%d", *(a + i * n + j));
// printf("%d", a[i * n + j]);
}
}
int main()
{
int n = 0, opt = 0, *a = NULL;
printf("number of lines and columns:");
scanf("%d", &n);
a = malloc ( n * n * sizeof *a);
while (1)
{...

Heapsort program does not return the result

I am implementing the Heapsort program in C language which sorts with the binary tree. When I run this program, it is ok until it meets the heapsort function in the program. I also try to debug this but it still gets wrong as meeting the heapsort function.
As referencing some algorithms on the Internet, I find it similar to my source code but they run correctly, so its really hard for me to find out the errors in my source code
#include <stdio.h>
#define MAX 2100
void downheap(int a[], int n, int k)
{
int i=0;
int temp = a[0];
while (k <= n/2)
{
i = k + k;
if(i<n && a[i] <= a[i+1]) i++;
if(temp < a[i]) break;
a[k] = a[i]; k = i;
}
a[k] = temp;
}
void heapsort(int a[], int n)
{
int i, j;
for(i=0; i<=n; i++) downheap(a, n, i);
while(n>=0)
{
j = a[0]; a[0] = a[n]; a[n] = j;
downheap(a, --n, 0);
}
}
int main()
{
int n, a[MAX], i;
printf("Enter your number of elements: ");
scanf("%d", &n);
for(i=0; i<n; i++) printf("%d: ", i), scanf("%d", &a[i]);
heapsort(a, n-1);
for(i=0; i<n; i++) printf("%d ", a[i]);
return 0;
}
There are multiple problems in your code that I list below:
You should stick to the common convention that n is the number of elements. In your code it is the number of elements minus one which is inconvenient. In this case you would call heapsort(a, n).
In the heapsort function, for(i=0; i<=n; i++) downheap(a, n, i) should be for(i=n/2-1; i>=0; i--) downheap(a, n, i).
Next, since n is the number of elements in a, the loop should be while(--n > 0). The iteration where n=0 is pointless since it will then swap a[0] with a[0]. Finally you call downheap(a, n, 0).
The function downheap, is where you have the biggest problem. The function should compare the element at index i with its two children and store the max of the tree at index i. If a swap with a child occurred, resume donwheap with this child. Your function is completely wrong. Here is a correct implementation.
void downheap(int *a, int n, int k){
int l = 2*k+1, r = 2*k+2, max = k;
if (l < n && a[l] > a[max])
max = l;
if (r < n &d a[r] > a[max])
max = r;
if (max != k) {
int j = a[k]; a[k] = a[max]; a[max] = j;
downheap(a, n, max);
}
}
As you can see, this code is very different from yours which is completely wrong.
For your convenience, here is the code of the heapsort function. That code was not as bad, but still incorrect.
void heapsort(int *a, int n){
int i, j;
for(i=n/2-1; i>=0; i--)
downheap(a, n, i);
while(--n > 0){
j = a[0]; a[0] = a[n]; a[n] = j;
downheap(a, n, 0);
}
}
EDIT
Non recursive implementation of downheap:
void downheap(int *a, int n, int k){
while (1) {
int l = 2*k+1, r = 2*k+2, max = k;
if (l < n && a[l] > a[max])
max = l;
if (r < n &d a[r] > a[max])
max = r;
if (max == k)
break;
int j = a[k]; a[k] = a[max]; a[max] = j;
k = max;
}
}

C - Two dimensional matrix, add in a shape of two symmetrical up-down triangles (almost like X)

The objective: Add only the pieces of the matrix that are part of a full X (upper and lower triangle).
1 1 1
0 1 0
1 1 1
Like this, middle one should add only once.
I can't add the lower triangle properly. Help much appreciated :)
void write(int niz[20][20], int n){
int i, j;
for(i=0; i<n; i++){
for(j=0; j<n; j++){
scanf("%d", &niz[i][j]);
}
}
}
void x(int niz[20][20], int n){
//Upper triangle
int i, j, pr=n, suma=0;
for(i=0; i<n/2 + n%2; i++,pr--){
for(j=i; j<pr; j++){
suma += niz[i][j];
}
}
printf("%d\n",suma);
//Lower triangle
pr = n;
for(i=n; i>n/2 + n%2; i--,pr--){
printf("%d",pr);
for(j=n-i; j<pr; j++){
printf("\n%d", niz[i][j]);
suma += niz[i][j];
}
}
printf("%d", suma);
}
int main()
{
int n;
printf("Matrix dimensions: ");
scanf("%d", &n);
printf("Numbers in the matrix: \n");
int niz[n][n];
write(niz, n);
x(niz, n);
}
Instead of writing separate functions for each lower, upper & diagonals you can do all together with little tricks, but it works only if row == column and thats's what you want I think.
int main() {
/* it can be anything like a[3][3] or a[7][7] and elements can
be all one or all 2 or any number */
int arr[5][5] = { {1,1,1,1,1},
{0,0,1,0,0},
{0,0,1,0,0},
{0,0,1,0,0},
{1,1,1,1,1} };
int row = sizeof(arr)/sizeof(arr[0]);
int col = sizeof(arr[0])/sizeof(arr[0][0]);
int sum = 0;
for(int index = 0; index < row; index++) {
for(int sub_index = 0; sub_index < col; sub_index++) {
if(index == 0 || (index == row-1) || sub_index == row/2)
sum = sum + arr[index][sub_index];
}
}
printf("sum = %d \n",sum);
return 0;
}
Its fine if it helps you otherwise write your own logic.
There are some mismatches between the declarations and types of the arguments passed to OP's function. While in main they declare a variable length array, named niz:
int n;
// ...
int niz[n][n];
The posted signature of both write and x requires an int niz(*)[20]. It should be changed to:
void write(int n, int niz[n][n]);
// this ^^^ may be a size_t, just remember to write it before the array
About the pattern you have to follow for the sum, I can't say to fully understand your requirement, but if I'm not completely wrong, it could be done this way:
#include <stdio.h>
#include <stdlib.h>
void read_matrix(int n, int niz[n][n])
{
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
scanf("%d", &niz[i][j]);
}
}
}
// Separate the calculation from the printing
int hourglass_sum(int n, int niz[n][n])
{
int sum = 0;
int i = 0;
//Upper triangle
for(int k = n; i < k; ++i, --k) {
for(int j = i; j < k; ++j) {
sum += niz[i][j];
}
}
//Lower triangle
for(int k = i + 1; i < n; ++i, ++k) {
for(int j = n - i - 1; j < k; ++j) {
sum += niz[i][j];
}
}
return sum;
}
int main()
{
int n;
printf("Matrix dimensions: ");
scanf("%d", &n);
int niz[n][n];
read_matrix(n, niz);
printf("\nSum: %d", hourglass_sum(n, niz));
}

c - warning: pointer argument of a function may be used uninitialized

#include <stdio.h>
#include <stdlib.h>
void multiplyMatrix (int **first, int **second, int **multiply);
int m, n, p, q, i, c, d, k, sum = 0;
int main()
{
int **first, **second, **multiply;
printf("Enter the number of rows and columns of first matrix\n");
scanf("%d%d", &m, &n);
first = (int **) malloc(m * sizeof(int *));
for(i = 0 ; i < n ; i++){
first[i]=(int *)malloc(m * sizeof(int *));
}
printf("Enter the elements of first matrix\n");
for (c = 0; c < m; c++)
for (d = 0; d < n; d++)
scanf("%d", &first[c][d]);
printf("Enter the number of rows and columns of second matrix\n");
scanf("%d%d", &p, &q);
second = (int **) malloc(p * sizeof(int *));
for(i = 0 ; i < q ; i++){
second[i]=(int *) malloc(p * sizeof(int *));
}
if (n != p)
printf("Matrices with entered orders can't be multiplied with each other.\n");
else
{
printf("Enter the elements of second matrix\n");
for (c = 0; c < p; c++)
for (d = 0; d < q; d++)
scanf("%d", &second[c][d]);
/*for (c = 0; c < m; c++) {
for (d = 0; d < q; d++) {
for (k = 0; k < p; k++) {
sum = sum + first[c][k]*second[k][d];
}
multiply[c][d] = sum;
sum = 0;
}
}*/
multiplyMatrix(first, second, multiply);
printf("Product of entered matrices:-\n");
for (c = 0; c < m; c++) {
for (d = 0; d < q; d++)
printf("%d\t", multiply[c][d]);
printf("\n");
}
}
return 0;
}
void multiplyMatrix (int **first, int **second, int **multiply)
{
for (c = 0; c < m; c++) {
for (d = 0; d < q; d++) {
for (k = 0; k < p; k++) {
sum = sum + first[c][k]*second[k][d];
}
multiply[c][d] = sum;
sum = 0;
}
}
}
The program i want to write should be like this: The program asks to the user to enter both the sizes and elements of 2 matrices (or you can call it 2d arrays). Then it will multiply those matrices and print the answer.
The problem i am getting: i used pointers and malloc functions to dynamically allocate the matrices. for the multiplication, i created a function called "multiplyMatrix" which i get a warning for one of the arguments of it in the decleration. here is the warning:
warning: 'multiply' may be used uninitialized in this function.
so there is some kind of a problem with initializing this argument. i feel like the answer is simple but at the same time i can't find the solution.
You have not allocated the memory to be used by the multiply matrix - hence it is being flagged as uninitialised.
You also need to review how you use your row and column values when allocating the first and second matrices, for example:
first = (int **) malloc(m * sizeof(int *));
for(i = 0 ; i < m ; i++){
first[i]=(int *)malloc(n * sizeof(int *));
}
(Incorporates comment made by wildplasser)
This will allow first to be accessed as first[row][col]
the variable multiply was declared in main(), however it is never set to point to anything. it needs to be created the same way as first and second, however it does not need to have its' values filled in.
Suggestions to improve your code:
Create a function to allocate memory for a matrix.
Create a function to read matrix data.
Create a function to deallocate memory of a matrix.
Avoid use of global variables. Pass the necessary arguments to a function.
Use those functions instead of duplicating code in main.
#include <stdio.h>
#include <stdlib.h>
int** createMatrix(int rows, int cols)
{
int i;
int** mat = malloc(sizeof(*mat)*rows);
for ( i = 0; i < rows; ++i )
mat[i] = malloc(sizeof(*mat[i])*cols);
return mat;
}
void readMatrix(int** mat, int rows, int cols)
{
int r;
int c;
for ( r = 0; r < rows; ++r )
for ( c = 0; c < cols; ++c )
scanf("%d", &mat[c][c]);
}
void deleteMatrix(int** mat, int rows)
{
int i;
for ( i = 0; i < rows; ++i )
free(mat[i]);
free(mat);
}
void multiplyMatrix (int **first, int **second, int **multiply,
int frows, int fcols, int scols)
{
int sum = 0;
int r;
int c;
int k;
for (r = 0; r < frows; r++) {
for (c = 0; c < scols; c++) {
sum = 0;
for (k = 0; k < fcols; k++) {
sum += first[r][k]*second[k][c];
}
multiply[r][c] = sum;
}
}
}
int main()
{
int m, n, p, q;
int r, c;
int **first, **second, **multiply;
printf("Enter the number of rows and columns of first matrix\n");
scanf("%d%d", &m, &n);
first = createMatrix(m, n);
printf("Enter the elements of first matrix\n");
readMatrix(first, m, n);
printf("Enter the number of rows and columns of second matrix\n");
scanf("%d%d", &p, &q);
if (n != p)
printf("Matrices with entered orders can't be multiplied with each other.\n");
else
{
second = createMatrix(p, q);
printf("Enter the elements of second matrix\n");
readMatrix(second, p, q);
multiply = createMatrix(m, q);
multiplyMatrix(first, second, multiply, m, n, q);
printf("Product of entered matrices:-\n");
for (r = 0; r < m; r++) {
for (c = 0; c < q; c++)
printf("%d\t", multiply[r][c]);
printf("\n");
}
deleteMatrix(multiply, m);
deleteMatrix(second, p);
}
deleteMatrix(first, m);
return 0;
}

Transpose a matrix via pointer in C

I'm trying to transpose a matrix in C while passing the matrix to a function and return a pointer to a transposed matrix. What am I doing wrong in the second while loop?
in main
ptr = (float *) getMatrix(numRowsB, numColsB);
transposePtr = transpose(ptr, numRowsB, numColsB);
printf("\nBtranspose =\n");
printMatrix(transposePtr, numColsB, numRowsB);
create matrix
float* getMatrix(int n, int m)
{
int i, j;
float *arrayPtr;
if ((n <= 0) || (m <= 0))
{
printf("function getMatrix(): matrix dimensions are invalid\n");
return NULL;
}
arrayPtr = (float *) malloc(n*m*sizeof(float));
if(arrayPtr == NULL)
{
printf("function getMatrix: Unable to malloc array\n");
return NULL;
}
transpose function
float* transpose(float *matrix, int n, int m)
{
int i = 0;
int j = 0;
float num;
float *transposed=(int*) malloc(sizeof(int)*n*m);
while(i < n-1)
{
while(j < m-1)
{
num = *(matrix+i*m+j);
*(transposed+j*m+i)= num;
j++;
}
i++;
}
return transposed;
}
print fucntion
void print(float *matrix, int n, int m)
{
int i = 0;//row counter
int j = 0;//col counter
for(i = 0; i < n; i++){
printf("\n");
for(j = 0; j < m; j++){
printf("%f ", *(matrix + i*n + j));
}
}
}
Example input:
1 2 3
4 5 6
Output:
1.000000 0.000000
2.000000 3396.580087
-0.000000 0.000000
Part of the problem was your print function
Here is a version of your functions that works:
float* transpose(float *matrix, int n, int m)
{
int i = 0;
int j = 0;
float num;
float *transposed=malloc(sizeof(float)*n*m);
while(i < n) {
j = 0;
while(j < m) {
num = *(matrix + i*m + j);
*(transposed + i+n*j) = num; // I changed how you index the transpose
j++;
}
i++;
}
return transposed;
}
void print(float *matrix, int n, int m)
{
int i = 0;//row counter
int j = 0;//col counter
for(i = 0; i < n; i++){
printf("\n");
for(j = 0; j < m; j++){
printf("%f ", *(matrix + i*m + j)); // Changed from n to m
}
}
}
There were a few things.
Use sizeof(float) instead of sizeof(int)
Your loop should be i < n and j < m instead of i < n-1 and j < m-1 and finally you need to reset j to zero every time
The matrix indexes in inner most loop of your transpose function was incorrect
Your print function was using the wrong variable in the multiplication
Also it is generally considered bad practice to cast the result of malloc in C.

Resources