I am new to c, I am using CUDA compiler. I want to declare five matrices, from a[1][1] to a[5][5]. Initialize them with random values. Print these values. I have shown the whole code I wrote. I face problems
Passing matrix as parameter
Initialize a matrix (should be constant)
#include <stdio.h>
#include <stdlib.h>
void printMatrix(int **a, int rows, int cols)
{
for(int i=0; i<rows; i++){
for (int j=0; j<cols; j++){
printf("%d\t", a[i][j] );
}
printf("\n");
}
}
int main() {
int N;
for (int n=0; n<=5; n++)
N = n;
int a[N][N];
for(int i=0; i<N; i++)
for (int j=0; j<N; j++){
a[i][j] = rand() % 256;
}
printf("Matrix A\n");
printMatrix(a, 10, 10);
}
}
This works fine if i define N on the top. If I did that, I couldn't change N value using for loop. How can I correct.
For starters there is a typo in the program. You omitted the open brace after the loop statement
for (int n=0; n<=5; n++)
^^^^
N = n;
int a[N][N];
//...
There should be
for (int n=0; n<=5; n++) {
^^^^
N = n;
int a[N][N];
//...
Array a is a variable length array. Its dimension may not be equal to 0. So the variable n must to start from 1 as it is written in the assignment
for (int n=1; n<=5; n++) {
^^^^
This function call
printMatrix(a, 10, 10);
^^ ^^
does not make sense because the number 10 has nothing common with the array.
And the function declaration
void printMatrix(int **a, int rows, int cols);
^^^^^^^
is invalid. There is a mismatch between the argument type and the parameter type and there is no implicit conversion from one type to another type.
The program can look like
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void printMatrix( size_t rows, size_t cols, int a[][cols] )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( size_t j = 0; j < cols; j++ ) printf( "%3d ", a[i][j] );
printf( "\n" );
}
}
int main( void )
{
const size_t N = 5;
const int UPPER_VALUE = 256;
srand( ( unsigned int )time( NULL ) );
for ( size_t n = 1; n <= N; n++ )
{
int a[n][n];
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) a[i][j] = rand() % UPPER_VALUE;
}
printf( "Matrix A[%zu][%zu]:\n", n, n );
printMatrix( n, n, a );
printf( "\n" );
}
return 0;
}
Its output might be
Matrix A[1][1]:
117
Matrix A[2][2]:
57 216
50 233
Matrix A[3][3]:
42 117 215
177 218 26
202 81 163
Matrix A[4][4]:
205 178 157 2
229 165 93 94
91 160 39 205
26 242 131 69
Matrix A[5][5]:
147 248 126 107 42
103 149 160 62 70
122 89 17 203 252
222 125 154 224 98
63 61 192 155 222
If the compiler does not support variable length arrays then you have to allocate the arrays dynamically. For example
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void printMatrix( int **a, size_t rows, size_t cols )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( size_t j = 0; j < cols; j++ ) printf( "%3d ", a[i][j] );
printf( "\n" );
}
}
int main( void )
{
const size_t N = 5;
const int UPPER_VALUE = 256;
srand( ( unsigned int )time( NULL ) );
for ( size_t n = 1; n <= N; n++ )
{
int **a = malloc( n * sizeof( int * ) );
for ( size_t i = 0; i < n; i++ )
{
a[i] = malloc( n * sizeof( int ) );
for ( size_t j = 0; j < n; j++ ) a[i][j] = rand() % UPPER_VALUE;
}
printf( "Matrix A[%zu][%zu]:\n", n, n );
printMatrix( a, n, n );
printf( "\n" );
for ( size_t i = 0; i < n; i++ ) free( a[i] );
free( a );
}
return 0;
}
for (int n=0; n<=5; n++){ /* <--missing { which causes N to be 6 after last iteration */
//your code
}
You missed a { after first for loop in main that's why int a[N][N] and other loops are not inside its body (which you probably want "changing value of N ")
It seems that the number of matrices is constant, so just #define it at the top. Without touching your printMatrix method, you can have a main body as follows:
#define N 5
int main(int argc, char ** argv)
{
int **data[N]; // Array of length N of int **, where each int ** will store a matrix.
for (int i = 0; i < N; i++) {
int matrixSize = i + 1; // creating the ith matrix
data[i] = malloc(matrixSize * sizeof *data[i]);
for (int j = 0; j < matrixSize; j++) {
data[i][j] = malloc(matrixSize * sizeof *data[i][j]);
for (int k = 0; k < matrixSize; k++) {
data[i][j][k] = rand() % 256;
}
}
}
// Printing the first one
printMatrix(data[0], 1, 1);
// don't forget to loop again to free the buffers allocated...
return 0;
}
Related
So as you know, in C function declarations, you have to name all dimension sizes but one of array parameters. I'm now working with a 2d array where both sizes are generated at runtime, however I want to pass that array to another function to fill it.
My thought was just using the maximum size in the function declaration, like this:
int max_size = 100;
int actual_size;
int another_size;
static void fill_array(int ar[][max_size])
{
for(int i = 0; i < another_size; i++)
{
for(int j = 0; j < actual_size; j++)
{
ar[i][j] = some int;
}
}
}
static void main()
{
if(some_input) actual_size = 50;
else actual_size = 100;
if(some_input) another_size = 10;
else another_size = 20;
int empty_array[another_size][actual_size] = {0};
fill_array(empty_array);
}
My thought is that even though the function may think that each array line has 100 ints, we're only filling the first 50 anyways. Is this unclever? Any way to accomplish the same more cleaner? Pretty new to C, so sorry if it's a very obvious thing.
For starters such a declaration of the function main
static void main()
is not standard.
The function should be declared like
int main( void )
If your compiler supports variable length arrays then you may declare the function like
static void fill_array( size_t rows, size_t cols, int ar[][cols] );
and pass a two-dimensional array of any sizes.
Here is a demonstrative program.
#include <stdio.h>
static void fill_array( size_t rows, size_t cols, int a[][cols] )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( size_t j = 0; j < cols; j++ )
{
a[i][j] = i * cols + j;
}
}
}
int main(void)
{
size_t rows;
size_t cols;
printf( "Enter the number of rows: " );
scanf( "%zu", &rows );
printf( "Enter the number of columns: " );
scanf( "%zu", &cols );
int a[rows][cols];
fill_array( rows, cols, a );
for ( size_t i = 0; i < rows; i++ )
{
for ( size_t j = 0; j < cols; j++ )
{
printf( "%2d ", a[i][j] );
}
putchar( '\n' );
}
return 0;
}
Its output might look for example like
Enter the number of rows: 3
Enter the number of columns: 5
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
If you want to use passed array as a "normal" array in the function you can use this method. Works even with the ANSI C.
https://godbolt.org/z/aiNjef
void fillarray(void *arr, int cols, int rows)
{
int (*newarr)[cols] = arr;
for(int row = 0; row < rows; row++)
{
for(int col = 0; col < cols; col++)
{
newarr[row][col] = (row << 4) | (col);
}
}
}
#define ROWS 5
#define COLS 10
int main(void)
{
int arr[ROWS][COLS];
fillarray(arr, COLS, ROWS);
for(int row = 0; row < ROWS; row++)
{
for(int col = 0; col < COLS; col++)
{
printf("%02x ", arr[row][col]);
}
printf("\n");
}
}
I am trying to dynamically allocate a 2D array using calloc.
Here is the code that I have tried.
int ** numberOfConstPiArray = calloc(invariannumberOfUniqueKernels * kernelColumnCount, sizeof(int *));
I have initialised the following variables as shown
int numberOfUniqueKernels = 100;
int kernelColumnCount = 10;
int dimensionalMatrixColumnCount = 10;
The following is the main code which loops through and tries to alter the 2D array.
for (int countKernel = 0; countKernel < numberOfUniqueKernels; countKernel++)
{
int countNumberOfConst = 0;
int numberOfTerms = 0;
int numberOfConstPi = 0;
for (int col = 0; col < kernelColumnCount; col++)
{
for (int row = 0; row < dimensionalMatrixColumnCount; row++)
{
if (some condition is satisfied)
{
countNumberOfConst += 1;
}
if (another condition satisfied)
{
numberOfTerms += 1;
}
}
if(countNumberOfConst == numberOfTerms)
{
numberOfConstPi += 1;
numberOfConstPiArray[countKernel][col] = 1;
}
countNumberOfConst=0;
numberOfTerms=0;
}
}
This doesn't seem to work. I understand that doesn't seem to work is vague but as this code is a part of a large compiler, there is no way for me to print out the specific output. Apologies for that.
My question is: Have I initialised the arrays in the correct way and have is the way I modified the values of the elements in the array correct.
Thank you.
This
int ** numberOfConstPiArray = calloc(invariannumberOfUniqueKernels * kernelColumnCount, sizeof(int *));
is not an allocation of a two-dimensional array because at least the type of numberOfConstPiArray is int ** instead of for example int ( * )[kernelColumnCount].
If your compiler supports variable length arrays then you could use the following approach as it is shown in the demonstrative program
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t n = 5;
int ( *a )[n] = calloc( n * n, sizeof( int ) );
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) a[i][j] = i * n + j;
}
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) printf( "%2d ", a[i][j] );
putchar( '\n' );
}
free( a );
return 0;
}
The program output is
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
Or you can allocate an array of arrays the following way.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t n = 5;
int **a = calloc( n, sizeof( int * ) );
for ( size_t i = 0; i < n; i++ )
{
a[i] = calloc( n, sizeof( int ) );
}
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) a[i][j] = i * n + j;
}
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) printf( "%2d ", a[i][j] );
putchar( '\n' );
}
for ( size_t i = 0; i < n; i++ )
{
free( a[i] );
}
free( a );
return 0;
}
The program output is the same as shown above.
numberOfConstPiArray[countKernel][col]
is getting an int* from numberOfConstPiArray[countKernel], then trying to dereference col'th element of this int*, and fails, as numberOfConstPiArray[countKernel] was not initialized with an reference to int array memory.
You may use instead:
int * numberOfConstPiArray = calloc(invariannumberOfUniqueKernels * kernelColumnCount, sizeof(int));
memset(numberOfConstPiArray, 0, invariannumberOfUniqueKernels * kernelColumnCount, sizeof(int));
...
numberOfConstPiArray[countKernel * kernelColumnCount + col] = 1;
I want to allocate memory to two dimensional array of type int but, the memory should be continuous.
it should be freed by just making one call to free( ptr ). I should need not to call free to each block of memory.
Formally, it is done like this:
int (*arr_ptr) [x][y] = malloc( sizeof(int[x][y]) );
(*arr_ptr)[i][j] = something; // access one element
free(arr_ptr);
However, this makes access of the elements a bit inconvenient: (*arr_ptr)[i][j] is a bit hard to read. A trick to avoid this, is to leave out one dimension of the array pointer and instead regard it as an array of one-dimensional arrays:
int (*arr_ptr) [y] = malloc( sizeof(int[x][y]) );
arr_ptr[i][j] = something; // access one element
free(arr_ptr);
If you have an ancient compiler, you must create a more ugly, "mangled" 2D array:
int* ptr = malloc( sizeof(int) * x * y );
ptr[i*y + j] = something; // access one element
free(ptr);
If your compiler supports Variable Length Arrays (VLAs) then you can write the following way
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
size_t m = 3;
size_t n = 4;
int ( *a )[n] = malloc( m * n * sizeof( int ) );
for ( size_t i = 0; i < m; i++ )
{
for ( size_t j = 0; j < n; j++ ) a[i][j] = i * n + j;
}
for ( size_t i = 0; i < m; i++ )
{
for ( size_t j = 0; j < n; j++ ) printf( "%2d ", a[i][j] );
printf( "\n" );
}
free( a );
return 0;
}
The program output is
0 1 2 3
4 5 6 7
8 9 10 11
Otherwise n must be a constant. For example
#include <stdlib.h>
#include <stdio.h>
#define N 4
int main( void )
{
size_t m = 3;
int ( *a )[N] = malloc( m * N * sizeof( int ) );
for ( size_t i = 0; i < m; i++ )
{
for ( size_t j = 0; j < N; j++ ) a[i][j] = i * N + j;
}
for ( size_t i = 0; i < m; i++ )
{
for ( size_t j = 0; j < N; j++ ) printf( "%2d ", a[i][j] );
printf( "\n" );
}
free( a );
return 0;
}
Another possibility is to use a one dimensional array as a two dimensional one, like in the following example:
#include <stdio.h>
#include <stdlib.h>
#define N 2
#define M 3
/*
array has N * M elemts:
| N | N | N |
v v v v
|----|----|----|----|----|----|
array[i][j] == array[i*N + j]
*/
#define GET(i,j) (i*N + j)
int main(int argc, char **argv) {
int *array;
int i, j;
array = malloc(N * M *sizeof(int));
for (i = 0; i < N; i++)
for (j = 0; j < M; j++)
array[i*N + j] = i+j;
for (i = 0; i < N; i++)
for (j = 0; j < M; j++)
printf("array[%d][%d] = %d\n", i, j, array[i*N + j]);
printf("Using the macro:\n");
for (i = 0; i < N; i++)
for (j = 0; j < M; j++)
printf("array[%d][%d] = %d\n", i, j, array[GET(i,j)]);
free(array);
return 0;
}
I also defined a macro GET(i,j) so that the code will be more readable, actually this is really needed only to handle more complex cases then the two dimensional one.
I tried to set values in 2D array and Print it with Function.
but I got trouble to send the Array to the Function.
#include <stdio.h>
void SetArr(int (*arr)[], int n);
void PrintfArr(int (*arr)[], int n);
int main()
{
int arr[100][100];
for(int i=0; i<100; i++)
for(int j=0; i<100; j++)
arr[i][j]=0; //initiallize Array
int size;
printf("input Size : "); scanf("%d", &size);
SetArr(arr, size);
PrintfArr(arr, size);
return 0;
}
void SetArr(int (*arr)[], int n)
{
int i, j;
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
arr[i][j]=i+j; // Error! "Subscript of Pointer to imcomplete~
}
}
void PrintArr(int (*arr)[], int n)
{
int i, j;
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf("%d", arr[i][i]); // Error! "Subscript of Pointer to imcomplete~
}
printf("\n");
}
As you see, both of functions got same problem while using "arr[][]"
In the declaration of the function, array must be mentioned with its size (length). This is what the compiler means when it says "incomplete type": it needs the size to understand how to access its elements.
In order to make size available to the compiler, it should go first in the function's declaration:
void SetArr(int n, int (*arr)[n])
Here arr is technically a "pointer to an array of n elements", but in C it's customary to treat a pointer as an array, so arr can be treated as "an array of arrays of n elements", which is the same as a 2-D array.
You might want to mention both dimensions of the array:
void SetArr(int n, int arr[n][n])
This is equivalent to the first declaration, but seems clearer.
Declare the functions like
void SetArr( int ( *arr )[100], int n );
void PrintfArr( int ( *arr )[100], int n );
You may not declare the functions as it is shown in the answer that you marked as the best
Consider the following code where instead of 100 I am using 3 for the array dimensions.
If you will print the array in function PrintArr and in main you will get different results!
#include <stdio.h>
void SetArr( size_t n, int (*arr)[n] )
void PrintArr( size_t n, int (*arr)[n] )
int main(void)
{
int arr[3][3];
size_t n = 2;
SetArr( n, arr );
PrintArr( n, arr );
printf( "\n" );
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) printf( "%2d", arr[i][j] );
printf( "\n" );
}
return 0;
}
void SetArr( size_t n, int (*arr)[n] )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) arr[i][j] = i * n + j;
}
}
void PrintArr( size_t n, int (*arr)[n] )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) printf( "%2d", arr[i][j] );
printf( "\n" );
}
}
The program output is
0 1
2 3
0 1
3 1
As you see the first output does not coincide with the second output. You would get the correct result if the functions were declared as I pointed in the beginning of the post. For example
#include <stdio.h>
void SetArr( int (*arr)[3], size_t n );
void PrintArr( int (*arr)[3], size_t n );
int main(void)
{
int arr[3][3];
size_t n = 2;
SetArr( arr, n );
PrintArr( arr, n );
printf( "\n" );
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) printf( "%2d", arr[i][j] );
printf( "\n" );
}
return 0;
}
void SetArr( int (*arr)[3], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) arr[i][j] = i * n + j;
}
}
void PrintArr( int (*arr)[3], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < n; j++ ) printf( "%2d", arr[i][j] );
printf( "\n" );
}
}
The program output is
0 1
2 3
0 1
2 3
As you can see in this case the both outputs coincide.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void matrixRandomFill(int size, int size2, int matrix[size][size2]) {
srand(time(NULL));
for ( int i = 0; i < size; i++ ) {
for ( int j = 0; j < size2; j++ ) {
matrix[i][j] = rand() % 9;
}
}
}
void matrixSum(int size, int size2, int matrix1[size][size2], int matrix2[size] [size2], int matrixSum[size][size2]) {
for ( int i = 0; i < size; i++ ) {
for ( int j = 0; j < size2; j++ ) {
matrixSum[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
}
void matrixSubstract(int size, int size2, int matrix1[size][size2], int matrix2[size] [size2], int matrixSubstract[size][size2]) {
for ( int i = 0; i < size; i++ ) {
for ( int j = 0; j < size2; j++ ) {
matrixSubstract[i][j] = matrix1[i][j] - matrix2[i][j];
}
}
}
void matrixMultiply(int size, int size2, int matrix1[size][size2], int matrix2[size] [size2], int matrixMultiply[size][size2]) {
for ( int i = 0; i < size; i++ ) {
for ( int j = 0; j < size2; j++ ) {
matrixMultiply[i][j] = matrix1[i][j] * matrix2[i][j];
}
}
}
void matrixPrint(int size, int size2, int matrix[size][size2]) {
for ( int i = 0; i < size; i++ ) {
for ( int j = 0; j < size2; j++ ) {
printf("%2d ", matrix[i][j]);
}
printf("\n");
}
}
int main() {
int size;
printf("Enter matrix size NxN: ");
scanf("%d", &size);
int matrix1[size][size];
int matrix2[size][size];
int matrixSum[size][size];
int matrixSubstract[size][size];
int matrixMultiply[size][size];
matrixRandomFill(size, size, matrix1);
matrixRandomFill(size, size, matrix2);
printf("Printing first matrix:\n");
matrixPrint(size, size, matrix1);
printf("--------------------------------------\n");
printf("Printing second matrix:\n");
matrixPrint(size, size, matrix2);
printf("--------------------------------------\n");
printf("Printing matrix1 + matrix2:\n");
matrixPrint(size, size, matrixSum);
printf("--------------------------------------\n");
printf("Printing matrix1 - matrix2:\n");
matrixPrint(size, size, matrixSubstract);
printf("--------------------------------------\n");
printf("Printing matrix1 * matrix2:\n");
matrixPrint(size, size, matrixMultiply);
printf("--------------------------------------\n");
return 0;
}
the functions look normal, but i keep getting something like this:
Printing matrix1 + matrix2:
0 0 0
0 0 0
0 0 0
or
Printing matrix1 - matrix2:
-1761243347 32767 -1761341440
32767 0 0
0 0 0
looks like some kind of segmentation fault, but i can't figure out where i made a mistake.
The problem is you are just printing the matrices but not performing any operations before it.
// You forgot to call matrix sum function here.
printf("Printing matrix1 + matrix2:\n");
matrixPrint(size, size, matrixSum);
printf("--------------------------------------\n");
Similarly for subtraction, multiplication operations as well.
Your functions matrixSum etc are never called.
As others said, You never actually evaluate matrixSum and the rest, also I found that your local(to main) variables that have the same name as your functions hide your functions, so they will be no longer available past those variable declarations.
The way I see your another problem is(by example):
int iwilldosomething(int a, int b) /*function iwilldosomething */
int main(void)
{
int iwilldosomething; /* local variable iwilldosomething */
iwilldosomething(2, 3); /* here you will get error, because main can see iwilldosomething and will tell that iwilldosomething is not a function */
.
.
.