if I have an array
double i[5] = {1.023, 1.22, 1.56, 2, 5, 3.331};
how do i sort the values so that they look like this:
double i[5] = {1.023, 1.22, 1.56, 2, 3.331, 5};
i've tried qsort() with no luck, after trying some examples, i came up with:
qsort(i, 5, sizeof(double), sort);
int sort(const void *x, const void *y)
{
return (*(double*)x - *(double*)y);
}
with => error: incompatible type for argument 1
not sorting the array.....
The first argument to qsort is the pointer to the start of the array to be sorted. Instead of
qsort(i[5], 5, sizeof(double), sort);
it should read
qsort(i, 5, sizeof(double), sort);
Some further observations:
The length of i's initializer is incorrect (i has five elements, yet the initializer has six).
Hard-coding the 5 into the qsort call is asking for trouble later on.
The name "i" is most commonly used for loop counters and the like.
Calling the comparison function sort is confusing.
Your comparison function is wrong. Consider how it would compare the numbers 1.1 and 1.2. Also think about what would happen if the difference between the two values doesn't fit in an int.
I would rewrite your entire example like so:
double arr[] = {1.023, 1.22, 1.56, 2, 5, 3.331};
int cmp(const void *x, const void *y)
{
double xx = *(double*)x, yy = *(double*)y;
if (xx < yy) return -1;
if (xx > yy) return 1;
return 0;
}
int main() {
qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), cmp);
}
Note that the above comparison function still doesn't correctly handle NaNs; I leave it as an exercise for the reader to fix that.
Related
I need to pass a 2D array to a function.
#include <stdio.h>
#define DIMENSION1 (2)
#define DIMENSION2 (3)
void func(float *name[])
{
for( int i=0;i<DIMENSION1;i++){
for( int j=0;j<DIMENSION2;j++){
float element = name[i][j];
printf("name[%d][%d] = %.1f \n", i, j, element);
}
}
}
int main(int argc, char *argv[])
{
float input_array[DIMENSION1][DIMENSION2] =
{
{0.0f, 0.1f, 0.2f},
{1.0f, 1.1f, 1.2f}
};
func(input_array);
return 0;
}
Dimensions vary depending on the use case, and the func should stay the same.
I tried the above int func(float *[]) but compiler complains expected ‘float **’ but argument is of type ‘float (*)[3]’, and also I get the segmentation fault error at runtime when trying to access the array at element = name[i][j].
What would be the proper signature of my function? Or do I need to call the func differently?
You can use the following function prototype:
int func(int dim1, int dim2, float array[dim1][dim2]);
For this you have to pass both dimensions to the function (you need this values anyhow in the function). In your case it can be called with
func(DIMENSION1, DIMENSION2, input_array);
To improve the usability of the function call, you can use the following macro:
#define FUNC_CALL_WITH_ARRAY(array) func(sizeof(array)/sizeof(*(array)), sizeof(*(array))/sizeof(**(array)), array)
Then you can call the function and it will determine the dimensions itself:
FUNC_CALL_WITH_ARRAY(input_array);
Full example:
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#define FUNC_CALL_WITH_ARRAY(array) func(sizeof(array)/sizeof(*(array)), sizeof(*(array))/sizeof(**(array)), array)
int func(int dim1, int dim2, float array[dim1][dim2])
{
printf("dim1 %d, dim2 %d\n", dim1, dim2);
return 0;
}
#define DIMENSION1 (4)
#define DIMENSION2 (512)
int main(int argc, char *argv[])
{
float input_array[DIMENSION1][DIMENSION2];
FUNC_CALL_WITH_ARRAY(input_array);
float input_array2[7][16];
FUNC_CALL_WITH_ARRAY(input_array2);
}
Will print
dim1 4, dim2 512
dim1 7, dim2 16
Dimensions vary depending on the use case, and the func should stay the same.
Use VLA:
void func (int r, int c, float arr[r][c]) {
//access it like this
for (int i = 0; i < r; ++i) {
for (int j = 0; j < c; ++j) {
printf ("%f\n", arr[i][j]);
}
}
}
// call it like this
func (DIMENSION1, DIMENSION2, input_array);
You can change your function like this;
int func(float (*arr)[DIMENSION2])
{
}
But also you should change your main code like this;
float input[DIMENSION1][DIMENSION2];//I just upload the dimension1 to dimension2
As noted above in the comment, the key problem is that int func(float *name[]) declares name to be an array of pointers to float.
In this sense, the following modification to main() works:
int main(int argc, char *argv[])
{
float input_array[DIMENSION1][DIMENSION2] =
{
{0.0f, 0.1f, 0.2f},
{1.0f, 1.1f, 1.2f}
};
/* Declare an array of pointers, as this is what func requires at input: */
float* in_p[DIMENSION1];
/* ... and initialize this array to point to first elements of input array: */
for( int i=0;i<DIMENSION1;i++)
in_p[i] = input_array[i];
/* ... and send this array of pointers to func: */
func(in_p);
return 0;
}
This is going to present a very old solution, one that works on every C compiler that exists. The idea goes something like this:
I have multiple pieces of information to keep track of
I should keep them together
This leads us to the idea that we can use a composite type to hold all the related information in one place and then treat that object as a single entity in our code.
There is one more pebble in our bowl of sand:
the size of the information varies
Whenever we have varying-sized objects, dynamic memory tends to get involved.
Arrays vs Pointers
C has a way of losing information when you pass an array around. For example, if you declare a function like:
void f( int a[] )
it means exactly the same thing as:
void f( int * a )
C does not care that the size of the array is lost. You now have a pointer. So what do we do? We pass the size of the array also:
void f( int * a, size_t n )
C99 says “I can make this prettier, and keep the array size information, not just decay to a pointer”. Okay then:
void f( size_t dim1, size_t dim2, float array[dim1][dim2] )
We can see that it is pretty, but we still have to pass around the array’s dimensions!
This is reasonable, as the compiler needs to make the function work for any array, and array size information is kept by the compiler, never by executable code.
The other answers here either ignore this point or (helpfully?) suggest you play around with macros — macros that only work on an array object, not a pointer.
This is not an inherently bad thing, but it is a tricky gotcha: you can hide the fact that you are still individually handling multiple pieces of information about a single object,
except now you have to remember whether or not that information is available in the current context.
I consider this more grievous than doing all the hard stuff once, in one spot.
Instead of trying to juggle all that, we will instead use dynamic memory (we are messing with dynamic-size arrays anyway, right?)
to create an object that we can pass around just like we would with any other array.
The old solution presented here is called “the C struct hack”. It is improved in C99 and called “the flexible array member”.
The C struct hack has always worked with all known compilers just fine, even though it is technically undefined behavior.
The UB problem comes in two parts:
writing past the end of any array is unchecked, and therefore dangerous, because the compiler cannot guarantee you aren’t doing something stupid outside of its control
potential memory alignment issues
Neither of these are an actual issue. The ‘hack’ has existed since the beginning (much to Richie’s reported chagrin, IIRC), and is now codified (and renamed) in C99.
How does this magic work, you ask?
Wrap it all up in a struct:
struct array2D
{
int rows, columns;
float values[]; // <-- this is the C99 "flexible array member"
};
typedef struct array2D array2D;
This struct is designed to be dynamically-allocated with the required size. The more memory we allocate, the larger the values member array is.
Let’s write a function to allocate and initialize it properly:
array2D * create2D( int rows, int columns )
{
array2D * result = calloc( sizeof(array2D) + sizeof(float) * rows * columns, 1 ); // The one and only hard part
if (result)
{
result->rows = rows;
result->columns = columns;
}
return result;
}
Now we can create a dynamic array object, one that knows its own size, to pass around:
array2D * myarray = create2D( 3, 4 );
printf( "my array has %d rows and %d columns.\n", myarray->rows, myarray->columns );
free( myarray ); // don’t forget to clean up when we’re done with it
The only thing left is the ability to access the array as if it were two-dimensional.
The following function returns a pointer to the desired element:
float * index2D( array2D * a, int row, int column )
{
return a->values + row * a->columns + column; // == &(a->values[row][column])
}
Using it is easy, if not quite as pretty as the standard array notation.
But we are messing with a compound object here, not a simple array, and it goes with the territory.
*index2D( myarray, 1, 3 ) = M_PI; // == myarray[ 1 ][ 3 ] = M_PI
If you find that intolerable, you can use the suggested variation:
float * getRow2D( array2D * a, int row )
{
return a->values + row * a->columns; // == a->values[row]
}
This will get you “a row”, which you can array-index with the usual syntax:
getRow2D( myarray, 1 )[ 3 ] = M_PI; // == myarray[ 1 ][ 3 ] = M_PI
You can use either if you wish to pass a row of your array to a function expecting only a 1D array of floats:
void some_function( float * xs, int n );
some_function( index2D( myarray, 1, 0 ), myarray->columns );
some_function( getRow2D( myarray, 1 ), myarray->columns );
At this point you have already seen how easy it is to pass our dynamic 2D array type around:
void make_identity_matrix( array2D * M )
{
for (int row = 0; row < M->rows; row += 1)
for (int col = 0; col < M->columns; col += 1)
{
if (row == col)
*index2D( M, row, col ) = 1.0;
else
*index2D( M, row, col ) = 0.0;
}
}
Shallow vs Deep
As with any array in C, passing it around really only passes a reference (via the pointer to the array, or in our case, via the pointer to the array2D struct).
Anything you do to the array in a function modifies the source array.
If you want a true “deep” copy of the array, and not just a reference to it, you still have to do it the hard way.
You can (and should) write a function to help.
This is no different than you would have to do with any other array in C, no matter how you declare or obtain it.
array2D * copy2D( array2D * source )
{
array2D * result = create2D( source->rows, source->columns );
if (result)
{
for (int row = 0; row < source->rows; row += 1)
for (int col = 0; col < source->cols; col += 1)
*index2D( result, row, col ) = *index2D( source, row, col );
}
return result;
}
Honestly, that nested for loop could be replaced with a memcpy(), but you would have to do the hard stuff again and calculate the array size:
array2D * copy2D( array2D * source )
{
array2D * result = create2D( source->rows, source->columns );
if (result)
{
memcpy( result->values, source->values, sizeof(float) * source->rows * source->columns );
}
return result;
}
And you would have to free() the deep copy, just as you would any other array2D that you create.
This works the same as any other dynamically-allocated resource, array or not, in C:
array2D * a = create2D( 3, 4 ); // 'a' is a NEW array
array2D * b = copy2D( a ); // 'b' is a NEW array (copied from 'a')
array2D * c = a; // 'c' is an alias for 'a', not a copy
...
free( b ); // done with 'b'
free( a ); // done with 'a', also known as 'c'
That c reference thing is exactly how pointer and array arguments to functions work in C, so this should not be something surprising or new.
void myfunc( array2D * a ) // 'a' is an alias, not a copy
Hopefully you can see how easy it is to handle complex objects like variable-size arrays that keep their own size in C, with only a minor amount of work in one or two spots to manage such an object. This idea is called encapsulation (though without the data hiding aspect), and is one of the fundamental concepts behind OOP (and C++). Just because we’re using C doesn’t mean we can’t apply some of these concepts!
Finally, if you find the VLAs used in other answers to be more palatable or, more importantly, more correct or useful for your problem, then use them instead! In the end, what matters is that you find a solution that works and that satisfies your requirements.
I need help finding the appropriate way to provide values to my function in C which can be seen below:
void matrixMultiply(int *A[], int *B[])
I have the following function that needs 2 pointer to arrays, and those pointers point to two 2d arrays. I have the following main function, but I just can't seem to figure out a way to pass my arrays to the function.
int main()
{
int arr[2][2] = {
{ 1, 2 },
{ 5, 6 }
};
int(*p)[2];
p = &arr;
int arr2[2][1] = {
{ 11 },
{ 55 }
};
int(*l)[1];
l = arr2;
for (int i = 0; i < 4; i++) // I don't know if I need this but I used it before when I was experimenting with the form p[i].
{
matrixMultiply(p, l); // p and l are the pointers to the two 2d arrays I have
}
return 0;
}
This is the updated code:
int main()
{
int arr[2][2] = {
{ 1, 2 },
{ 5, 6 }
};
int(**p);
p = &arr;
int arr2[2][1] = {
{ 11 },
{ 55 }
};
int(**l);
l = arr2;
for (int i = 0; i < 4; i++) // I don't know if I need this but I used it before when I was experimenting with the form p[i].
{
matrixMultiply(p, l); // p and l are the pointers to the two 2d arrays I have
}
return 0;
}
new errors:
C:\WINDOWS\system32\cmd.exe /C ""C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/mingw32-make.exe" -j12 SHELL=cmd.exe -e -f Makefile"
C:/Users/Owner/Desktop/Codes/aee22eeCodes/main.c: In function 'main':
C:/Users/Owner/Desktop/Codes/aee22eeCodes/main.c:49:16: warning: passing argument 1 of 'matmul' from incompatible pointer type [-Wincompatible-pointer-types]
matmul(&arr, &arr2); // p and l are the pointers to the two 2d arrays I have
^~~~
C:/Users/Owner/Desktop/Codes/aee22eeCodes/main.c:12:18: note: expected 'int **' but argument is of type 'int (*)[2][2]'
void matmul(int *A[], int *B[])
~~~~~^~~
C:/Users/Owner/Desktop/Codes/aee22eeCodes/main.c:49:22: warning: passing argument 2 of 'matmul' from incompatible pointer type [-Wincompatible-pointer-types]
matmul(&arr, &arr2); // p and l are the pointers to the two 2d arrays I have
^~~~~
C:/Users/Owner/Desktop/Codes/aee22eeCodes/main.c:12:28: note: expected 'int **' but argument is of type 'int (*)[2][1]'
void matmul(int *A[], int *B[])
~~~~~^~~
====0 errors, 4 warnings====
This answer is a snippet of my full answer here.
Here are 4 techniques and when to use each. If your array sizes are fixed and known at compile-time, your prototype and call should look like this:
void matrixMultiply(int (*a)[2][2], int (*b)[2][1]);
matrixMultiply(&arr, &arr2);
...but I don't have enough information from you, so here are the 4 techniques and when to use each. You can follow these examples to create the right answer for your particular situation.
Assume you have the following 2D array:
int arr[][2] =
{
{1, 2},
{5, 6},
{7, 8},
};
...and the following macro definitions:
// Get the number of elements in any C array
// - from my repo here:
// https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/c/utilities.h#L42
#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
/// Definitions: `rows` = "rows"; `cols` = "columns"
/// Get number of rows in a 2D array
#define NUM_ROWS(array_2d) ARRAY_LEN(array_2d)
/// Get number of columns in a 2D array
#define NUM_COLS(array_2d) ARRAY_LEN(array_2d[0])
If the 2D array is ALWAYS the same size each time (it has a FIXED number of rows, and a FIXED number of columns) (3 rows and 2 columns in the below example), do this:
// 1. Function definition
void printArray2(int (*a)[3][2])
{
// See my function definition here:
// https://stackoverflow.com/a/67814330/4561887
}
// 2. Basic usage
// NB: `&` is REQUIRED! See my answer for why: https://stackoverflow.com/a/51527502/4561887
printArray2(&arr);
// 3. Usage via a pointer
// `int (*a)[3][2]` is an explicit ptr to a 3x2 array of `int`. This array pointer does NOT
// naturally decay to a simpler type.
int (*p2)[3][2] = &arr; // must use `&` and MUST USE THESE PARENTHESIS!
printArray2(p2);
If the 2D array has a VARIABLE number of rows, but a FIXED number of columns (2 in this case),
do this:
// 1. Function definition
void printArray3(int a[][2], size_t num_rows)
{
// See my function definition here:
// https://stackoverflow.com/a/67814330/456188
}
// 2. Basic usage
printArray3(arr, NUM_ROWS(arr));
// 3. Usage via a pointer
// `int a[][2]` naturally decays to `int* [2]`
int (*p3)[2] = arr; // MUST USE THESE PARENTHESIS!
printArray3(p3, NUM_ROWS(arr));
If the 2D array has a VARIABLE number of rows AND a VARIABLE number of columns, do this (this
approach is the most-versatile and is generally my go-to approach for multidimensional arrays):
// 1. Function definition
void printArray4(int *a, size_t num_rows, size_t num_cols)
{
// See my function definition here:
// https://stackoverflow.com/a/67814330/456188
}
// 2. Basic usage
printArray4((int *)arr, NUM_ROWS(arr), NUM_COLS(arr));
// OR: alternative call technique:
printArray4(&arr[0][0], NUM_ROWS(arr), NUM_COLS(arr));
// 3. Usage via a pointer
// The easiest one by far!
int *p4_1 = (int*)arr;
// OR
int *p4_2 = &arr[0][0];
printArray4(p4_1, NUM_ROWS(arr), NUM_COLS(arr));
printArray4(p4_2, NUM_ROWS(arr), NUM_COLS(arr));
If you have the following "2D" array, however, you must do something different:
// Each row is an array of `int`s.
int row1[] = {1, 2};
int row2[] = {5, 6};
int row3[] = {7, 8};
// This is an array of `int *`, or "pointer to int". The blob of all rows
// together does NOT have to be in contiguous memory. This is very different
// from the `arr` array above, which contains all data in contiguous memory.
int* all_rows[] = {row1, row2, row3}; // "2D" array
If the 2D array is actually built up of a bunch of ptrs to other arrays (as shown just above),
do this:
// 1. Function definition
void printArray5(int* a[], size_t num_rows, size_t num_cols)
{
// See my function definition here:
// https://stackoverflow.com/a/67814330/456188
}
// 2. Basic usage
printArray5(all_rows, ARRAY_LEN(all_rows), ARRAY_LEN(row1));
// 3. Usage via a pointer
// `int* a[]` naturally decays to `int**`
int **p5 = all_rows;
printArray5(p5, ARRAY_LEN(all_rows), ARRAY_LEN(row1));
See my full answer here for the full function definitions for each function above, more details, example output, and full, runnable code: How to pass a multidimensional array to a function in C and C++
This question already has answers here:
Passing a multidimensional array of variable size
(2 answers)
How to pass 2D array (matrix) in a function in C?
(4 answers)
Closed 4 years ago.
I'm Java developer, not a C programmer. I'm trying to invoke some function that receives a 2D array, tried like:
#include <stdio.h>
int foo(int mat[][N])
{
printf("%d",N); /* <--- here error */
}
int main()
{
int a[5][5] =
{
{1, 2, 3, 4,5},
{1, 5, 5, 5,2},
{1, 4, 30,4,2},
{1, 2, 2,2, 2},
{1,1, 1,1, 2 }
};
foo(a);
return 0;
}
But the compiler says:
'N' undeclared (first use in this function)
I must have the signature: int foo(int mat[][N])
How should I pass the 2D array then?
You can use macros to define constant numbers, i.e. #define N 5. At compile time each appearance of the defined macro name will be replaced with the given value. In our case each N would be replaced with 5.
But this would not solve your problem, because it would print 5 every time, even if you change the dimensions of your array.
Pass the dimensions of the array as parameters.
You can pass the 2D array as a pointer.
I created a printing function, with what I can show you accessing the elements from the array. So the function's prototype would look like:
void print2DMatrix(int *matrix2D, const int rowLength, const int columnLength);
where matrix2D is a pointer, there will be passed the address of the array. The other two parameters tell us the dimensions of the array.
We can access the elements in a selected row and in a selected column with matrix2D[selectedRow * maxRowLength + selectedColumn].
When you call the function, you can pass the name of the array, like print2DMatrix(*myMatrix, myRowLength, myColumnLength);, of course you shall declare and initialize it before using.
print2DMatrix(myMatrix, myRowLength, myColumnLength); would cause warning, because the passed argument and the waited one have different types, but it will run correctly. The passed one is a double pointer, when the waited one is a single pointer. Because of that you have to use print2DMatrix(*myMatrix, myRowLength, myColumnLength);, where *myMatrix will point to the first row of our array.
I would like to mention that myMatrix and *myMatrix point to the same address, the difference is: myMatrix is looked as a double pointer to an integer, when *myMatrix is looked as a pointer to an integer. Run printf("%d %d %d", myMatrix, *myMatrix, **myMatrix); to see the result. **myMatrix will point to the first element of the first row, what is 11. See the entire code below...
#include <stdio.h>
#define ROW_LENGTH 5
#define COLUMN_LENGTH 5
void print2DMatrix(int *matrix2D, const int rowLength, const int columnLength)
{
int i;
for (i = 0; i < rowLength; i++)
{
int j;
for (j = 0; j < columnLength; j++)
{
printf("%d ", matrix2D[i * rowLength + j]);
}
printf("\n");
}
}
int main(void)
{
const int myRowLength = ROW_LENGTH;
const int myColumnLength = COLUMN_LENGTH;
int myMatrix[ROW_LENGTH][COLUMN_LENGTH] =
{
{11, 12, 13, 14, 15},
{21, 22, 23, 24, 25},
{31, 32, 33, 34, 35},
{41, 42, 43, 44, 45},
{51, 52, 53, 54, 55}
};
print2DMatrix(*myMatrix, myRowLength, myColumnLength);
return 0;
}
You are trying to print a non existent value. N is not a declared variable.
The function foo is receiving a pointer. Unlike java, C deals with pointers, not objects, it does not have any information about what it received, except that it is a pointer that contains addresses to ints. Therefore, the function does not know (or care) about your array being of size N (regardless of you mentioning N) .
When you call printf there's nothing in memory called N, which explains the error.
You could always send a second argument which is an int specifying the size and print that one.
void foo(int[][] mat, int matSize){
printf("%d\n",matSize);
}
Notice how I used int[][] this is to simplify and illustrate the fact that is just a pointer.
im trying to make a procedure to find a maximum numbers out of 3, which i will assign later to another variable pointer in main program
int Maximum (int *a, int *b, int *c)
{
if (*a>=*b)
{
if (*a<*c)
{*a=*c;}
}
else
{
*a=*b;
if (*a<*c)
{*a=*c;}
}
return a;
}
compiler giving me error that "expected 'int*' but argument is of type 'int' "
so i changes that part to
int * Maximum (int *a, int *b, int *c)
but error sentence still same ?
First off, your original function is designed to return an int and you're returning a, which is an int pointer. Either return the int (*a), or change the function so it returns an int *.
However, based on your actual message:
expected 'int*' but argument is of type 'int'
and the fact you state you've made that change and still have the problem (note the word "argument" in the message), this indicates that the problem lies not with the return value but with the way you're passing the arguments to it.
You are actually passing int where the function expects int * and that's probably caused by you using something like:
int one = 3;
int two = 7;
int three = 42;
int maxOfThree = Maximum (one, two, three);
If you wanted to pass pointers to the function, you would need:
Maximum (&one, &two, &three);
(passing the pointers to the variables, not the values of them).
A better solution (more readable and with correct data types both going in to, and coming out of, the function) to your problem would probably be:
int Maximum (int a, int b, int c) {
if ((a > b) && (a > c))
return a;
if (b > c)
return b;
return c;
}
If I have an array like this:
2, 4, 6, 0, 0, 0, 0, 0, 0
Is there a way I can use qsort by sorting just the first 3 elements, and leaving the rest untouched?
Would qsort(arrNumbers, 3, sizeof(int), compare) do the job?
Does specifying the number of elements lower than the full array cause only that number of elements to become sorted?
EDIT:
My compare function is:
int comp(const int * a, const int * b)
if(a==b)
{
return 0;
}
else
{
if(a<b)
{
return -1;
}
else
{
return 1;
}
}
Does it seem right?
Yes.
Yes.*
Yes.
* Assuming you define compare() appropriately.
Why don't you try it and see that it works as you expect?
Explanation: the qsort function only gets a pointer to the array, which does not say how long the array is. That's why you have to pass the size as well. In your function call you claim that the array is three ints long, and that's all the qsort function can be sure of. It will not access anything beyond that limit.
The full signature is:
void qsort(
void * base,
size_t num,
size_t width,
int (__cdecl *compare )(const void *, const void *)
);
To sort a specific contiguous range of the array, you just pass in a different base (pointer to starting element for the range) and num (number of elements in the range).
Yes if you specify 3 in your case it will only sort the first 3 elements.