I have created a contiguous array with random values (0-9), but I don't know how to pass it to a function that would print it.
Right now I'm simply iterating through the array inside the main function, whenever I need to print it. But I want to have a function for that, it would make my code cleaner.
A minimal code example is below:
#include <stdio.h>
#include <stdlib.h>
int **alloc_2d_int(int rows, int cols);
int main(int argc, char** argv){
int **matrix;
int i,j,size=3;
matrix = alloc_2d_int(size,size);
// generate the array
for (i=0; i<size; i++)
{
for (j=0; j<size; j++)
{
matrix[i][j] = rand() % 10;
}
}
// how I print the array right now
for (i=0; i<size; i++)
{
for (j=0; j<size; j++)
{
printf("[%d][%d]=%d\n", i,j,matrix[i][j]);
}
}
// this is how I want the printing to happen
print_arr(matrix,3);
}
int **alloc_2d_int(int rows, int cols) {
int *data = (int *)malloc(rows*cols*sizeof(int));
int **array= (int **)malloc(rows*sizeof(int*));
int i;
for (i=0; i<rows; i++)
array[i] = &(data[cols*i]);
return array;
}
void print_arr(int **array,int size)
{
int i,j;
for (i=0; i<size; i++)
{
for (j=0; j<size; j++)
{
printf("matrix[%d][%d]=%d\n", i,j,array[i][j]);
}
}
}
Error message:
conflicting types for ‘print_arr’ [enabled by default]
You forgot to add the declaration(prototype) of your function. In C language, by-default, the return type of a function is of int type. But for your print_arr() function, the return type is void. So, you get the conflict type error.
So, Declare the print_arr() function above the main() function. Like:
void print_arr(int **array,int size);
You haven't declared print_arr function before the main so it is not able to find it. Rest works smoothly.
Related
I have two functions. One that creates a multiplication table of a given number and the other function prints the array out. Below is my code:
Here's the error (Line 18):
expression must be a pointer to a complete object type
How do I fix this error and print the array? Also, I don't know how to print a new line after every row.
#include "multiplication.h"
#include <stdio.h>
int arr[][];
void mulitpication(int num){
/* initialize array and build*/
int arr[num][num];
for(int i=0; i<num;i++){
for(int j=0;j<num;j++){
arr[i][j]= (i+1)*(j+1);
}
}
}
void print(int arr[][]){
/* print the arr*/
int i;
for(i=0;i<sizeof(arr);i++){
for(int j=0;j<sizeof(arr);j++){
printf("%d ",arr[i][j])**(line 18)**;
}
}
}
If using C99 or later with VLA support, pass into the print function the dimensions needed.
// void print(int arr[][]){
void print(size_t rows, size_t cols, int arr[row][col]){
size_t r,c;
for (size_t r = 0; r < rows; r++) {
for (size_t c = 0; c < cols; c++) {
printf("%d ",arr[r][c]);
}
printf("\n");
}
}
You need to declare the array in main(), so it can be passed to both functions.
When an array is passed as a function parameter, it just passes a pointer. You need to pass the array dimensions, they can't be determined using sizeof.
To get each row of the table on a new line, put printf("\n"); after the loop that prints a row.
#include <stdio.h>
void multiplication(int num, arr[num][num]){
/* initialize array and build*/
for(int i=0; i<num;i++){
for(int j=0;j<num;j++){
arr[i][j]= (i+1)*(j+1);
}
}
}
void print(int num, int arr[num][num]){
/* print the arr*/
int i;
for(i=0;i<num;i++){
for(int j=0;j<num;j++){
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
int main(void) {
int size;
printf("How big is the multiplication table? ");
scanf("%d", &size);
int arr[size][size];
multiplication(size, arr);
print(size, arr);
return 0;
}
I'm new to C programming and I've run into a problem when creating 2D array printing function. When I try to execute the code below I get:
points.c:13: error: unknown array element size
As I've checked there are very similar codes online, which are supposed to work. I've tried to initialize function as
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
but it raises:
points.c:3: error: 'arrayLen' undeclared
Could somebody tell me what's wrong with this code and how to fix it? I also don't understand why very similar function for 1D arrays works just fine. It has to be in pure C.
#include <stdio.h>
//supposed to print 2D array:
int print2DArray(int array[][], int arrayLen, int elementLen)
{
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d", array[i][j]);
}
printf("\n");
}
}
//prints 1D array:
int printArray( int array[], int arrayLen)
{
int i;
for (i = 0; i < arrayLen; i++)
{
printf("%d", array[i]);
}
}
--- edit ---
I undestand most of you pointed out that the function has to be called like that:
#include <stdio.h>
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
{
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d", array[i][j]);
}
printf("\n");
}
}
This raises an error:
points.c:3: error: 'arrayLen' undeclared
I'm using tcc for windows and according to documentation it is supposed to support C99 VLA.
It appears OP's compiler (or the mode it is used) does not support variable length array (VLA) as a function parameter.
Below is a non-VLA approach.
void print2DArrayX(int arrayLen, int elementLen, const int *array) {
int i;
int j;
for (i = 0; i < arrayLen; i++) {
for (j = 0; j < elementLen; j++) {
printf("%5d", array[i*elementLen + j]);
}
printf("\n");
}
}
Call with address of first int, not the 2D array
#define ARRAY_LEN 3
#define ELEMENT_LEN 4
int array[ARRAY_LEN][ELEMENT_LEN] = { 0 };
...
print2DArrayX(ARRAY_LEN, ELEMENT_LEN, array[0]);
Ok, so thanks for all the answers - they were very helpful. I've just tried to use gcc in linux and as you've pointed out this approach works fine:
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
I guess tcc (tiny c compiler, windows version 0.9.27) doesn't support VLA after all. A bit strange since documentation says it does.
How about you try this solution.
#include <stdio.h>
int print2DArray(int* array, int arrayLen, int elementLen)
{
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d ", *(array+j+elementLen*i));
}
printf("\n");
}
}
int main(){
int arr[2][6] = { {9,258,9,96,-8,5},
{1,1212,-3,45,27,-6}
};
print2DArray(*arr,2,6);
return 0;
}
Unless you are using a C99 compiler,
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
is not possible.
Even if you are using C99 compiler, your code has a problem. You need to pass one of the dimension first.
int print2DArray(int arrayLen, int elementLen, int arr[][elementLen]);
So,
int print2DArray(int arrayLen, int elementLen, int arr[][elementLen])
{
// Your code
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d", array[i][j]);
}
printf("\n");
}
return 0;
}
This can be used as
int main(void)
{
int i32Array[3][3] = {{-15, 4, 36}, {45, 55, 12}, {-89, 568, -44568}};
int m = 3, n = 3;
// I am not sure why 'print2DArray' would return an int
// (or anything at all for that matter).
// If you can establish a case for it,
// modify the function and the value it is supposed to return,
// And catch it below.
print2DArray(m, n, i32Array);
return 0;
}
I am not sure how you are calling print2DArray function. Unless you post that piece of code, it is difficult to resolve your problem. Confirm that you are calling the function correctly as shown above.
So I have task like this:
"Write a program that will calculate determinants of matrixes. Size of the matrix should be typed as a command line parameter of the program. The user should type the matrix elements from the keyboard once the program is executed. The determinants should be calculated for different square matrix sizes (<=3) and not for the single fixed one. Divide your program into several functions. Use pointers. The size of arrays you'll use is determined by user during the program execution, therefore there is no need to use dynamic memory allocation."
I've heard that it's not possible to do this task with command line parameters, but not dynamic memory allocation. I'm just a beginner, so I wouldn't know. I haven't gotten to the part with calculating the determinants, I only wrote the functions to input and print a matrix, but there are already problems. I'm really lost as to what should I do.
This is what I have so far (it is not compiling right):
void inputMatrix(int size);
void printMatrix(int *matrix, int size);
int main(int argc, char *argv[])
{
int size = atoi(argv[1]);
int *matrix;
inputMatrix(size);
printMatrix(*matrix, size);
return 0;
}
void inputMatrix(int size)
{
int i, j;
int *matrix;
for(i=0; i<size; i++)
{
for(j=0; j<size; j++)
{
scanf("%d", (*(matrix + i) + j));
}
}
}
void printMatrix(int *matrix, int size)
{
int i, j;
int *matrix;
for(i=0; i<size; i++)
{
for(j=0; j<size; j++)
{
printf("%d ", *(*(matrix +i) + j));
}
printf("\n");
}
}
The answer by Joni addresses the main issue, but there are other things to be fixed in OP's code.
For starters, we have to decide whether to use a an array of arrays (like int mat[3][3];) or a simple array (like int mat[9];), while in OP's code, there's some confusion about it:
int main(int argc, char *argv[])
{
// ...
int *matrix; // <-- This pointer is uninitialized, its value is indeterminated
// ...
printMatrix(*matrix, size);
// ^ dereferencing it, you are passing an 'int'
}
// ...
void printMatrix(int *matrix, int size)
{ // ^ a pointer to an int is expected
int i, j;
int *matrix; // <-- This is a local variable that will shadow the parameter
// with the same name and it is also uninitialized.
for(i=0; i<size; i++)
{
for(j=0; j<size; j++)
{
printf("%d ", *(*(matrix +i) + j));
// ^^^^ this is equivalent to 'matrix[i][j]',
// but 'matrix' is only a pointer to 'int'
}
printf("\n");
}
}
So, if any dynamic memory allocation must be avoided, we can write somthing like this:
// ...
#define MAX_SIZE 3
int main(int argc, char *argv[])
{
int matrix[MAX_SIZE][MAX_SIZE];
// read 'size' from command line arguments, then
inputMatrix(size, matrix); // <-- Note that I'm passing 'matrix' here too.
printMatrix(size, matrix);
// ...
}
// The functions must be modified accordingly, e.g.:
void printMatrix(int size, int matrix[][MAX_SIZE])
// The inner dimension must be specified ^^^^^^
{
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size; j++)
{
printf("%d ", *(*(matrix + i) + j)); // <-- "Use pointers." they said
}
printf("\n");
}
}
In case you want to use a plain array instead, it can be written like this:
// ...
#define MAX_SIZE 9 // <-- the total size: 3*3
int main(int argc, char *argv[])
{
int matrix[MAX_SIZE];
// ...
printMatrix(size, matrix);
// ...
}
void printMatrix(int size, int matrix[])
{
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size; j++)
{
printf("%d ", *(matrix + (i * size + j));
// Note the math ^^^^^^^^^^^^^^^^^
// In this simple case of row wise traversal, it could be as simple as
// *(matrix++)
}
printf("\n");
}
}
Since you're not allowed to use dynamic memory allocation, you'll have to create the matrix in the main function and pass it to the other functions as a parameter. This uses a feature of C called variable length arrays:
int matrix[size*size];
inputMatrix(size, matrix);
If variable length arrays are not allowed either, just make it matrix[9] - size is at most 3 in your assignment
Finding determinant of square matrix of order n (n is finite) is quite easy with dynamic memory allocation. But, what is important in this case, is to free the memory at the end of program.
You can view my code here!
#include <stdio.h>
void f(int *app[][20]) {
int i, j;
for (i =0; i< 20; i++){
for (j=0; j<20; j++){
*app[i][j] = i;
}
}
}
int main() {
int app[20][20];
int i, j;
f(&app);
for (i =0; i< 20; i++){
for (j=0; j<20; j++){
printf("i %d, j%d val= %d\n", i, j, app[i][j]);
}
}
return 0;
}
What exactly am I doing wrong here? I don't get any error, but there is a segmentation fault and I don't know why.
te.c:15:5: warning: passing argument 1 of ‘f’ from incompatible pointer type
f(&app);
^
te.c:3:6: note: expected ‘int * (*)[20]’ but argument is of type ‘int (*)[20][20]’
void f(int *app[][20]) {
void f(int *app[][20]) { /* a 2d array of pointers to int */
should be
void f(int app[][20]) { /* a pointer to an array of 20 int's */
or
void f(int (*app)[20]) { /* a pointer to an array of 20 int's */
*app[i][j] = i;
should be
app[i][j] = i; /* you don't need to dereference */
f(&app);
should be
f(app);
void f(int *app[][20])
should be
void f(int app[][20])
and the call should be like
f(app);
The changes done in the function f() is visible in main()
You can access the array in function f() like app[i][j]
the following code correctly implements the definition and passing of a pointer to the 'app[][]' array to function 'f'
Notice the replacement of the 'magic' numbers
with #define'd values
Notice the proper use of prototypes.
This will become very important as the projects become larger and consist of multiple files. Although when the project becomes multiple files, then each source file should have its' own header file that contains the prototypes for that source file
The code cleanly compiles and runs correctly
#include <stdio.h>
#define ROWS (20)
#define COLS (20)
void f(int app[][COLS]) ;
int main( void )
{
int app[ROWS][COLS];
int i, j;
f(app);
for (i =0; i< ROWS; i++)
{
for (j=0; j<COLS; j++)
{
printf("i %d, j%d val= %d\n", i, j, app[i][j]);
}
}
return 0;
}
void f(int app[][COLS])
{
int i, j;
for (i =0; i< ROWS; i++)
{
for (j=0; j<COLS; j++)
{
app[i][j] = i;
}
}
}
I need to create a function that takes a matrix and returns it transpose. The only requirement is that it directly returns a matrix, not just modifies it by reference. Here's what I've done so far:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define ROW 100000000
#define COL 100000000
int (*(f_MatTrans)(int mat[][COL], int r, int c))[COL];
int main(void)
{
int x[2][2]={1,2,3,4};
int (*a)[2];
a=f_MatTrans(x,2,2);
for(int i=0; i<2; i++)
{
for(int j=0; j<2; j++)
{
printf("X[%d][%d]=%d\n",i,j,x[i][j]);
printf("A[%d][%d]=%d\n",i,j,a[i][j]);
}
}
return 0;
}
int (*(f_MatTrans)(int mat[][COL], int r, int c))[COL]
{
int a[c][r];
for(int i=0; i<r; i++)
{
for(int j=0; j<c; j++)
{
a[j][i]=mat[i][j];
}
}
return a;
}
The purpose of this is to include the function on a library created by myself, just in case it is useful information.
The code in the question (when I read it) doesn't compile because the array x is not compatible with the function signature.
I'm not clear what the real constraints on your problem are. The easy way to do it in C99 or C11 is with VLA notation:
#include <stdio.h>
static void MatrixTranspose(int r, int c, int src[r][c], int dst[c][r])
{
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
dst[j][i] = src[i][j];
}
int main(void)
{
int x[3][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
int y[2][3];
MatrixTranspose(3, 2, x, y);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
printf("X[%d][%d]=%d ", i, j, x[i][j]);
printf("Y[%d][%d]=%d\n", j, i, y[j][i]);
}
}
return 0;
}
Sample output:
X[0][0]=0 Y[0][0]=0
X[0][1]=1 Y[1][0]=1
X[1][0]=2 Y[0][1]=2
X[1][1]=3 Y[1][1]=3
X[2][0]=4 Y[0][2]=4
X[2][1]=5 Y[1][2]=5
My suspicion is that you are supposed to be doing something different (notationally more complex), but it is not yet clear what.
You cannot return a pointer to the local array, because that ceases to exist when the function returns. If you want your function to create the result array (not write to some other array that is passed into the function), you must use malloc() in these cases:
//The return type is actually `int (*)[r]`, but C doesn't like that.
int* f_MatTrans(int r, int c, int mat[][c]) {
int (*a)[r] = malloc(c*sizeof(*a));
for(int i=0; i<r; i++) {
for(int j=0; j<c; j++) {
a[j][i]=mat[i][j];
}
}
return *a;
}
Note that I changed the array types: If you declare mat as int mat[][COL], the number COL will be used to calculate the offset mat[1][0], which will be 100000000 integers after the first element in your case, while the array that you pass in only contains four integers. This is undefined behavior, and your program is allowed to format your harddrive if you do this.
Unfortunately, it is not possible for the type of the returned pointer to depend on the value of an argument to the function. That is why I changed the return type to a plain integer pointer, you must document that this is meant to be a pointer of type int (*)[r].
You would use the function above like this:
int main(void) {
int x[2][3]={1,2,3,4,5,6};
int (*a)[2] = (int (*)[2])f_MatTrans(2, 3, x);
for(int i=0; i<2; i++) {
for(int j=0; j<2; j++) {
printf("X[%d][%d]=%d\n",i,j,x[i][j]);
printf("A[%d][%d]=%d\n",i,j,a[i][j]);
}
}
free(a); //Cleanup!
return 0;
}