storage size of array isn't constant - c

i'm new to c. i'm writing a .h file dedicated to matrix. I want to write a function in .h file that returns a matrix (array) (not possible in c), so the real return is a pointer to a local array variable. But i can't use a local pointer in the main funct, so i've changed the int matrix[][] to static int matrix[][]. The problem now is: the user insert the number N of rows/columns, but a static array can only take a constant dimension. help
This is the .h
int N;
int i;
int j;
int *get_matrix(){
int user_input;
printf("set the dimension NxN of your matrix >> N=");
scanf("%d",&N );
static int temp_matrix[N][N];
for(i=0;i<N;i++){
for(j=0;j<N;j++){
printf("insert the matrix[%d][%d] value\n",i,j );
scanf("%d",&user_input);
temp_matrix[i][j]=user_input;
}
}
return temp_matrix;
}
void print_matrix(int *matrix){
for(i=0;i<sizeof(matrix)/4;i++){
for(j=0;j<sizeof(matrix)/4;j++){
printf("%7d",matrix[i][j]);
printf("\n");
}
}
}
this is the main.c file
#include <stdio.h>
#include "matrix_math.h"
void main(void){
int i;
int j;
int *p1 = get_matrix();
int matrix1[N][N];
for(i=0;i<N;i++){
for(j=0;j<N;j++){
matrix1[i][j]=p[i][j];
}
}
print_matrix(matrix1);
}

If this is just a school homework, and malloc not allowed/needed, and assuming it is acceptable to limit code to some reasonable upper limit N, consider defining matrix as a struct
#define MAXN 20
struct matrix {
int n ;
int data[MAXN][MAXN] ;
}
// matrix.c
struct matrix get_matrix() { ... ; return m } ;
void print_matrix(struct m *mp) {
for (int i = 0 ; i<mp->n ; i++) {
...
} ;
} ;
And then you can pass "matrix" around. Needless to say, better to pass matrix * whenever possible to improve performance. You can also make functions that return matrix, if needed.

Related

After a pointer Returns from a function i cant print it

I am relatively new to C. My program is supposed to fill in the array with random numbers and i have to find the max and min using 1 function. The program works fine up until the point i have to return the values my 2 pointers get from the function. When i go to print them the porgram stop working and exits with the return value of 3221225477. I have been trying to fix this for 3 hours and i am going INSANE. Please help in any way you can i would really apreciate it.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void MaxMin(int size, int *B, int *Max, int *Min);
int main(int argc, char *argv[])
{
int N, i,*A,*MAX,*MIN;
srand(time(NULL));
/*Making sure the user enters a proper value for the array*/
do
{
printf("Give the number of spaces in the Array\n");
scanf("%d",&N);
}
while(N<1);
A = (int *) malloc(N*(sizeof(N)));
/*Giving random numbers to the array and printing them so i can make sure my code is finding the max min*/
for(i=0;i<N;i++)
{
A[i]=rand()%100;
printf("\n%d\n",A[i]);
}
/*Calling my void function so that the pointers MAX and MIN have a value assigned to them */
MaxMin(N, A, MAX, MIN);
/*Printing them*/
printf("\nMax = %d\nMin = %d",*MAX,*MIN);
free(A);
return 0;
}
/*The function*/
void MaxMin(int size, int *B, int *Max, int *Min)
{
/*using 2 temporary ints to get max min cause pointers and arrays confuse me*/
int max=B[0],min=B[0],i;
for(i=1;i<size;i++)
{
if(max<B[i])
{
max = B[i];
}
if(min>B[i])
{
min = B[i];
}
}
/*These have the proper value last i chekced */
Max = &max;
Min = &min;
}
(edit) SOLUTION Ty so much for the help !
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void MaxMin(int size, int *B, int *Max, int *Min);
int main(int argc, char *argv[])
{
int N, i,*A,MAX ,MIN ;
srand(time(NULL));
/*Making sure the user enters a proper value for the array*/
do
{
printf("Give the number of spaces in the Array\n");
scanf("%d",&N);
}
while(N<1);
A = (int *) malloc(N*(sizeof(int)));
/*Giving random numbers to the array and printing them so i can make sure my code is finding the max min*/
for(i=0;i<N;i++)
{
A[i]=rand()%100;
printf("\n%d\n",A[i]);
}
/*Calling my void function so that the pointers MAX and MIN have a value assigned to them */
MaxMin(N, A, &MAX, &MIN);
/*Printing them*/
printf("\nMax = %d\nMin = %d",MAX,MIN);
free(A);
return 0;
}
/*The function*/
void MaxMin(int size, int *B, int *Max, int *Min)
{
*Max=B[0];
*Min=B[0];
int i;
for(i=1;i<size;i++)
{
if(*Max<B[i])
{
*Max = B[i];
}
if(*Min>B[i])
{
*Min = B[i];
}
}
}
You passed to the function MaxMin pointers MAX and MIN by value. That is the function deals with copies of (indeterminate) values of the passed pointers. Changing the copies does not influence on the original arguments.
Within main you should declare MIN and MAX as objects of the type int.
int N, i,*A, MAX, MIN;
and call the function ,like
MaxMin(N, A, &MAX, &MIN);
Within the function you should write
*Max = &max;
*Min = &min;
And at last in main you should call printf like
printf("\nMax = %d\nMin = %d", MAX, MIN);
Pay attention to that the expression sizeof( N ) used in this statement
A = (int *) malloc(N*(sizeof(N)));
is error prone. The type of the variable N can be changed for example from the type int to the type size_t. In this case the size of the allocated memory will be incorrect, You should write for example
A = (int *) malloc(N*(sizeof( *A )));
You have three bugs:
In main, you don't assign MAX or MIN any values. So you pass garbage to MaxMin.
In MaxMin, Max and Min are about to go out of scope. Changing their values before they go out of scope has no effect on anything.
In main, you don't create any place to hold the maximum and minimum values. So where are you expecting them to be stored?

Passing Multidimensional arrays to functions as Pointers

I have to pass two arrays ( A and B with dimensions of 5X4) to two functions called FUNCTION_1 and FUNCTION_2. Both of arrays columns and rows should be passed as POINTERS. FUNCTION_1 will take each element of A array and calculate the sum of prime factors of each element located in A( (with the help of another function called sumPrime), then it will store these sums in array B. FUNCTION_2 has to print both of A and B arrays. ( The normal numbers array, and the prime factors sums array). There are some additions in the program which are not important now but I am going to show them too in respect of clearness.
#include <stdio.h>
#include <stdlib.h>
#define ROW 5
#define COL 4
# include <math.h>
int sumPrime(int number){
int factor = 2;
int sum=0;
while(1!=number){
if(number%factor==0){
number /= factor;
sum+=factor;
factor = 2;
continue;
}
factor++;
}
return sum;
}
int FUNCTION_1(int *a[][20],int *b[][20],int row, int col){
int c,d;
for(c=0;c<row;c++){
for(d=0;d<col;d++){
b[c][d]=sumPrime(a[c][d]);
return b[c][d];
}
}
}
void FUNCTION_2(int *x[][20],int *y[][20],int rows, int cols){
printf(" \n A matrix is :\n");
int e,f;
for(e=0;e<rows;e++){
for(f=0;f<cols;f++){
printf("A[%d][%d] is %d\n",e,f,x[e][f]);
}
}
printf("\n B matrix is:\n");
for(e=0;e<rows;e++){
for(f=0;f<cols;f++){
printf("A[%d][%d] is %d\n",e,f,FUNCTION_1(x,rows,cols,y,rows,cols));
}
}
}
int main(){
int A[ROW][COL]={0};
int B[ROW][COL]={0};
int x=1;
int i;
int j;
for(i=0;i<ROW;i++){
for(j=0;j<COL;j++){
A[i][j]=x;
x=x+2;
}
}
printf("%d",A[0][0]);
return 0;
}
When trying to perform FUNCTION_1 or FUNCTION_2 I get many errors or even when defining the functions. There is no problem with defining A matrix or prime function! HELP!!
Your definition for a matrix is wrong ..
Use :
func(int* a[20] , int cols)
in this case you will have 20 rows ,
or
func(int a[][20] , int rows)
And define some macro for the columns if it is fixed value .

Multidimensional arrays in functions in c

I have this exercise to make a transpose of a matrix in C. I made a function to check for type n*n but when I'm trying to ask the user for the matrix I don't know how I should declare the array. And I'm getting this compile error "type of formal parameter 1 is incomplete" in the function on the [n2] part.
The parameters of the functions for multi dimensional arrays shouldn't be like this -> int matrix[][n2]. or is cause i'm using a variable and not a constant or a pre defined size. ?
#include <stdio.h>
#define prompt "Dimenção da matriz (nxn) >>"
#define prompt_1 "Introduza os valores : "
void getType( int *n1, int *n2 );
void getMatrix( int matrix[][n2], int lim1, int lim2);
//void trans(int matrix[][n2]);
int main(int argc, char const *argv[]) {
int n1, n2;
getType(&n1, &n2);
int matrix[n1][n2];
//printf("%dx%d\n", n1, n2);
getMatrix(matrix, n1, n2);
//trans(matrix);
return 0;
}
void getType(int *n1, int *n2){
printf("%s", prompt );
scanf("%dx%d", &(*n1), &(*n2));
}
void getMatrix( int matrix[][n2], int lim1, int lim2){
printf("%s\n", prompt_1 );
for(int line = 0; line < lim1; line++ ){
for(int column = 0; column < lim2; column++){
printf("Linha %d coluna %d ->", line, column );
scanf("%d", &matrix[line][column]);
}
}
}
The signature should be:
void getMatrix( int lim1, int lim2, int matrix[lim1][lim2] )
You are allowed omit the lim1 inside square brackets but it is good documentation to include it.
The main point is that the variable inside the square brackets must either be a parameter from earlier in the parameter list, or some other variable in scope (which can only be a global variable, but that's usually a bad idea).
Also it would be good to check scanf return value otherwise you may create matrix with garbage dimension.

Passing two arguments

I want to pass two arguments into void Dividing from void Assign_numbers and void Maximum. I have only learnt to pass one argument at a time. Can you please tell me what I have to do print out the following variables inside void Dividing. If it's possible, I don't want the format of my code to change drastically. Can you also show me an example, since I am a visual learner. Thanks
#include <stdlib.h>
#include <stdio.h>
#define Max 6
struct Numbers
{
double a,b,c,d,e,f;
};
void Maximum(double *ptr);
void Dividing(double Maximum, double *ptr);
void Assign_numbers()
{
struct Numbers number;
number.a=45.78;
number.b=81.45;
number.c=56.69;
number.d=34.58;
number.e=23.57;
number.f=78.35;
Maximum((double*) &number);
Dividing((double*) &number);
}
void Maximum(double *ptr)
{
int i=0;
double Maximum = ptr[0];
for(i;i<Max;i++)
{
if(ptr[i]> Maximum)
{
Maximum = ptr[i];
}
}
Dividing(Maximum);
}
void Dividing(double Maximum, double *ptr)
{
printf("%.2f", Maximum);
printf("%.2f",ptr[3]);
}
int main()
{
Assign_numbers();
return 0;
}
Use array instead of struct - shwon here with reference example
Like Joachim Pileborg said. Don't use a struct as an array. In your case use a multidimensional array.
double[10][6] numbers;
You can easily iterate through such an array like so:
#include <stdio.h>
int main () {
/* an array with 2 rows and 6 columns*/
double numbers[2][6] = {
{45.78, 81.45, 56.69, 34.58, 23.57, 78.35},
{1,2,3,4,5, 6}
};
int i, j;
/* output each array element's value */
for ( i = 0; i < 2; i++ ) {
for ( j = 0; j < 6; j++ ) {
printf("numbers[%d][%d] = %f\n", i,j, numbers[i][j] );
}
}
/* Output by reference */
for(i = 0; i < 2; i++){
for(j=0; j < 6; j++ ){
printf("numbers[%d][%d] = %f\n", i, j,*(*(numbers + i) + j));
}
}
return 0;
}
Why the current code fails
Now onto explaining how your code (does not) work and a little about how pointers work. First off:
Dividing(double Maximum, double* ptr);
Does not work in the way you think it does. "double Maximum" is a new double variable that works within the scope of Dividing and is not a variable retrieved from the function:
void Maximum(double *ptr);
If you already knew this, then you should know or at least have expected how poor the naming of your variables are(keep it lowerCamelCase).
Now lets get onto what you're trying to do. IMHO your code is completely broken unless I am noticeing something. In Assign_numbers() you want to call Dividing() using a pointer reference. In Maximum() you want to call Dividing() again, but this time sending only a value. It doesn't make it better that you have 2 separate different calls that each have one parameter. But the function has to have two parameters. Now in order to iterate through the variables in a struct - again this is not recommended and the bottom code only serves as an example.
struct Numbers
{
double a,b,c,d,e,f;
};
struct Numbers Assign_numbers()
{
struct Numbers number;
number.a=45.78;
number.b=81.45;
number.c=56.69;
number.d=34.58;
number.e=23.57;
number.f=78.35;
return number;
}
int main()
{
struct Numbers number;
number = Assign_numbers(number);
double *value = &(number.a); //take address of the first element, since a pointer always counts upwards.
int i;
/*This loops through the addresses of the struct starting from the initial address in number.a and moves upwards 5 times and hopefully ends in number.f. Seriously bad way to construct arrays*/
/*Just try replacing sizeof(number) with sizeof(double). suddenly you get all kinds of weird values because you have ended up outside of the struct*/
/*Also note that this only works when all the datatypes in the struct have a size of 8 bytes(the size of double) */
for (i = 0; i < sizeof(number) / sizeof(double); i++){
printf("[%d]: %f\n",i, value[i]);
}
return 0;
}
New working code
With all that said. This is the closest I am going to to be able to make your code work since I have no idea what you're trying to accomplish:
#include <stdlib.h>
#include <stdio.h>
#define Max 6
struct Numbers
{
double a,b,c,d,e,f;
};
void Maximum(double *ptr);
void Dividing(double *ptr);
void Assign_numbers()
{
struct Numbers number;
number.a=45.78;
number.b=81.45;
number.c=56.69;
number.d=34.58;
number.e=23.57;
number.f=78.35;
Maximum(&number.a); //You need to parse the very first address of the struct. IN this case 'a'
Dividing(&number.a);
}
void Maximum(double *ptr)
{
int i=0;
double maximum = ptr[0];
for(i;i<Max;i++)
{
if(ptr[i]> maximum)
{
maximum = ptr[i];
}
}
printf("maximum: %f", maximum);
}
/*//removed the first parameter since it was not clear what it was for and you only had function calls to this function with one parameter */
void Dividing(double *ptr)
{
printf("%.2f",ptr[3]);
}
int main()
{
Assign_numbers();
return 0;
}

passing statically allocated 2D arrays as function arguments in C

Consider this code:
#include <stdio.h>
#define N 5
void printMatrix(int (*matrix)[N],int n)
{
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++)
printf("%d",matrix[i][j]);
printf("\n");
}
}
int main()
{
int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
printMatrix(R,3);
}
This works fine as expected.
Now, I thought to write the functions handling 2D-matrices in a separate source file and link them wherever required.
But then I ran into a problem as in the function printMatrix, the size of array of int to which matrix points (i.e N) is required at compile-time. So, my functions would not work in other cases when the size is different.
So,How can I handle this?
Dynamic Arrays are a solution but i want to know if it can be done with static arrays.
You can't use the built-in 2D array type if both sizes are not known at compile time. A built-in 2D array must have at least one of the two sizes known at compile time.
If both sizes are run-time values, then you have no other choice but to use a "manual" implementation of 2D array, like an array of pointers to arrays, for example. In that case the function declaration might look as follows (two alternative equivalent forms)
void printMatrix(int *const *matrix, int n, int m);
void printMatrix(int *const matrix[], int n, int m);
To access to the array elements you can still use the "traditional" syntax
matrix[i][j]
The array itself would be created as follows (a simple example)
int row0[] = { 1, 2, 3 };
int row1[] = { 4, 5, 6 };
int *matrix[2];
matrix[0] = row0;
matrix[1] = row1;
printMatrix(matrix, 2, 3);
But if you already have a matrix implemented as a built-in 2d array
int matrix[2][3] = { ... };
then just to be able to pass it to the above function you can "convert" it into the above form by using an additional temporary "row pointer" array
int *rows[2];
rows[0] = matrix[0];
rows[1] = matrix[1];
printMatrix(rows, 2, 3);
Write yourself a macro:
#define MAT(i,j) matrix[i*n + j];
and declare "matrix" as a simple pointer to an "int".
Calculate the array index yourself. This will handle an arbitrary two dimensional array, for example:
void printMatrix(int *matrix,int n, int m)
{
int i,j;
for(i=0;i<n;i++){
for(j=0;j<m;j++)
printf("%d",matrix[m * i + j]);
printf("\n");
}
}
Don't try to pass it as a 2-D array; pass a pointer to the first element, then compute offsets manually:
void printMatrix(int *a, size_t m, size_t n)
{
size_t i,j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("a[%lu][%lu] = %d\n",
(unsigned long) i,
(unsigned long) j,
a[i*n+j]); // treat a as 1-d array, compute offset manually
}
}
}
int main(void)
{
int arr[5][4];
...
printMatrix(&arr[0][0], 5, 4);
...
}
Granted, this will only work for contiguously allocated arrays.
Although the syntax is not exactly the same, but this also happens to work a bit:
#include <stdio.h>
#define N 5
void printMatrix(int* row,int n,int sz)
{
int i,j;
int *currRow;
for(i=0;i<n;i++){
currRow = row+i*sz;
for(j=0;j<n;j++)
printf("%d",currRow[j]);
printf("\n");
}
}
int main()
{
int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
printMatrix(R[0],3,sizeof(R[0])/sizeof(int));
}

Resources