I would like to create a function which increase a given 2d dynamic int array with one row. I looked several website, guide, tutorial, but all is different, so I'm very confused now.
The 2d array has 2 fixed columns.
My code is here:
int length=1;
void arrayinc(int** array, int x0, int x1)
{
if (array == NULL)
malloc(array, sizeof(int[2]));
else
realloc(array, (++length)*sizeof(int[2]));
array[length-1][0]=x0;
array[length-1][1]=x1;
free(array);
}
int main()
{
int** array=NULL;
arrayinc(&array, 1, 2);
// I will do some stuff after the increase
}
I hope someone can help me, and explain how it really works!
Sorry for my english and bad malloc/realloc knowlage.
Function parameters are its local variables. So within the function you deal with a copy of the original argument.
At least the parameter shall be declared like
int*** array
If the number of columns is a compile-time constant then the function can be defined the following way.
#include <stdio.h>
#include <stdlib.h>
#define N 2
size_t arrayinc( int ( **array )[N], size_t n, int x0, int x1)
{
int ( *tmp )[N] = realloc( *array, ( n + 1 ) * sizeof( int[N] ) );
if ( tmp )
{
*array = tmp;
( *array )[n][0] = x0;
( *array )[n][1] = x1;
++n;
}
return n;
}
int main(void)
{
int ( *array )[N] = NULL;
size_t n = 0;
for ( size_t i = 0; i < 10; i++ )
{
n = arrayinc( &array, n, ( int )( 2 * i ), ( int )( 2 * i + 1 ) );
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%d\t%d\n", array[i][0], array[i][1] );
}
free( array );
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
Related
qsort has the following function protype
void qsort(
void* _Base,
size_t _NumOfElements,
size_t _SizeOfElements,
_CompareFunction
);
How is it possible that it is able to sort any array types (int, double, char, etc.)?
How does qsort know the type of array that I am asking it to sort?
It is due to the comparison function that casts void pointers to required types when it compares elements of the array.
Here is a demonstration program.
#include <stdio.h>
#include <stdlib.h>
int cmp( const void *px, const void *py )
{
int x = *( const int * )px;
int y = *( const int * )py;
return ( y < x ) - ( x < y );
}
int main( void )
{
int a[] ={5, 3, 1, 9, 8, 2, 4, 7};
const size_t N = sizeof( a ) / sizeof( *a );
for (size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
qsort( a, N, sizeof( *a ), cmp );
for (size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
The program output is
5 3 1 9 8 2 4 7
1 2 3 4 5 7 8 9
As you can see within the comparison function cmp the passed pointers are casted to the required type.
int x = *( const int * )px;
int y = *( const int * )py;
To traverse the array the function qsort uses the pointer arithmetic the following way. Initially the pointer _Base points to the first element of the passed array. To move for example the pointer to the i-th element of the array it does something like the following
void *ith_element_ptr = ( char * )_Base + i * _SizeOfElements;
I am currently learning C and I need to write a function to create an array of random integers. I've hit a problem where after creating I try to print and it the first 8 numbers correctly but the rest don't.
int* create(int n) {
int* array = malloc(n);
if (!array) return NULL;
srand(time(NULL));
for (int i = 0; i < n; i++) {
array[i] = rand() % 100 + 1;
printf("num: %i\n", array[i]);
}
for (int i = 0; i < n; i++) {
printf("%i\n", array[i]);
}
return array;
}
Here is my output for this:
num: 39
num: 2
num: 15
num: 74
num: 80
num: 29
num: 14
num: 16
num: 8
num: 11
num: 2
39
2
15
74
80
29
14
16
973747761
909588276
2614
This memory allocation
int* array = malloc(n);
allocates not enough memory for an array with n elements of the type int, You have to write
int* array = malloc( n * sizeof( int ) );
Also the parameter should have unsigned integer type. Otherwise the user can pass a negative integer that will result in undefined behavior.
It is better to declare the parameter as having the type size_t. It is the type of the parameter of the function malloc.
And the function should do one thing: allocate and initialize an array. It is the caller of the function that will decide whether to output the array provided that the function did not return a null pointer.
So the function can look like
int * create( size_t n )
{
const int MAX_VALUE = 100;
int *array = malloc( n * sizeof( int ) );
if ( array != NULL )
{
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = rand() % MAX_VALUE + 1;
}
}
return array;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int * create( size_t n )
{
const int MAX_VALUE = 100;
int *array = malloc( n * sizeof( int ) );
if ( array != NULL )
{
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = rand() % MAX_VALUE + 1;
}
}
return array;
}
int main(void)
{
size_t n = 0;
printf( "Enter the size of an array: " );
scanf( "%zu", &n );
int *array = create( n );
if ( array != NULL )
{
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", array[i] );
}
putchar( '\n' );
}
free( array );
return 0;
}
Its output might look like
Enter the size of an array: 10
75 36 30 75 53 49 42 52 61 9
Though it is better to declare the function such a way that the user can determine the maximum value himself. That is the function can look like
int * create( size_t n, int max_value )
{
int *array = malloc( n * sizeof( int ) );
if ( array != NULL )
{
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = rand() % max_value + 1;
}
}
return array;
}
Issues with your code:
malloc expects a size_t, you are directly giving an int. So you should technically do:
int *array = malloc(sizeof(int) * n);
This basically says that allocate n blocks of sizeof(int) bytes each.
What you are doing is allocating n bytes of data. The program is not guaranteed to run always and you are running out of bounds. If you were lucky you would get a Segmentation Fault in one of the runs.
You aren't allocating enough space. malloc(n) allocates n bytes. You need space for n ints! Use malloc(n * sizeof(int)), or more preferably: malloc(n * sizeof(*array)) (so you don't need to repeat the type) instead.
So this is the code I wrote, trying to reverse that array t using recursivity
#include <stdio.h>
#include <stdlib.h>
void rev(int n, float *t)
{
float x;
if(n==0)
{
return 0 ;
}
else
{
x=*t;
*t=*(t+(n-1));
*(t+(n-1))=x;
return rev(n-1, t+1);
}
}
void main()
{
int i;
float t[]={1,2,3,4,5,6,7,8,9};
int n=sizeof t /sizeof *t;
rev (n,t);
for(i=0;i<n;i++) printf("%f",t[i]);
}
I'd like to understand why this solution does not work, I'm not that interested in the solution overall but I want to understand what mistakes I made in this one for it not to work.
For starters a function that has the return type void shall return nothing value. So this statement
return 0 ;
is invalid.
The function swaps two elements so the size of the array must be decremented by 2.
The function can look like
void rev( float a[], size_t n )
{
if ( !( n < 2 ) )
{
float tmp = *a;
*a = *( a + n - 1 );
*( a + n - 1 ) = tmp;
rev( a + 1, n - 2 );
}
}
and be called like
size_t n = sizeof t /sizeof *t;
rev( t, n);
Here is a demonstrative program.
#include <stdio.h>
void rev( float a[], size_t n )
{
if ( !( n < 2 ) )
{
float tmp = *a;
*a = *( a + n - 1 );
*( a + n - 1 ) = tmp;
rev( a + 1, n - 2 );
}
}
int main(void)
{
float a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
size_t n = sizeof a /sizeof *a;
for ( size_t i = 0; i < n; i++ )
{
printf( "%.0f ", a[i] );
}
putchar( '\n' );
rev( a, n );
for ( size_t i = 0; i < n; i++ )
{
printf( "%.0f ", a[i] );
}
putchar( '\n' );
return 0;
}
The program output is
1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1
Pay attention to that according to the C Standard the function main shall be declared like
int main( void )
instead of
void main()
There are small easy to fix problems like return 0; and return rev(n-1, t+1);. The first one should be just
return;
because you can't return anything from a function returning void.
The other should be a call to rev() itself
rev(n-1, t+1);
because that's what recursive functions do (and also because you can't return anything)
Then you should use int main( void ) or at least int main() Difference between int main() and int main(void)?
Finally, you have a logic error here
x=*t;
*t=*(t+(n-1));
*(t+(n-1))=x;
rev(n-1, t+1);
*(t+(n-1)) will always be the value of the last element of the array: yes you pass n-1 so you expect that if *(t+(n-1)) was 8th element, in the next call it will be 7th, however you are also passing t+1 so *(t+(n-1)) will always be the 8th element of the array.
And even this one is an easy-to-fix problem. You just pass n-2.
Here's your recursive function
void rev(int n, float *t)
{
float x;
if(n > 0) {
x=*t;
*t=*(t+(n-1));
*(t+(n-1))=x;
rev(n-2, t+1);
}
return;
}
Doing
if(n != 0) {
.... something....
}
return;
Is the same of doing
if(n == 0) {
return;
}
else {
... something...
}
I put n > 0 instead of n != 0 because since n is always initially positive the two conditions are equivalent, however since you pass n-2 if n is an odd number you are going to have negative values of n without passing for 0.
I have to write a program that uses the qsort function to sort a vector
of points in the Cartesian plane. Each point is formed by a pair of
coordinates (x, y).
Points must be sorted by ascending x-axis. With the same x-axis,
y-axis is ordered by descending.
This is a sample input:
5 (Struct numbers)
2 5
12 2
2 7
3 4
2 2
With the output:
2 7
2 5
2 2
3 4
12 2
Now, this is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct x_y
{
int x;
int y;
}coordinates;
typedef coordinates *coordinatesList;
int compare(const void *a, const void *b)
{
coordinates *a1 = (coordinates *)a;
coordinates *b1 = (coordinates *)b;
if (a1->x > b1->x)
return 1;
else if (a1->x < b1->x)
return (-1);
else if (a1->x == b1->x)
{
if (a1->y < b1->y)
return 1;
else if (a1->y > b1->y)
return (-1);
else
return 0;
}
}
int main()
{
int n, i;
scanf("%d", &n);
coordinatesList *A = (coordinatesList*)malloc(n * sizeof(coordinates));
for (i = 0; i < n; i++)
{
A[i] = (coordinatesList)malloc(sizeof(coordinates));
scanf("%d%d", &A[i]->x, &A[i]->y);
}
qsort(A, n, sizeof(coordinates*), compare);
for (i = 0; i < n; i++)
printf("%d %d\n", A[i]->x, A[i]->y);
return 0;
}
whith his wrong output:
2 7
3 4
2 2
2 5
12 2
If I try to separate the structs by element:
int compare(const void *a, const void *b)
{
coordinates *a1 = (coordinates *)a;
coordinates *b1 = (coordinates *)b;
int a_x = a1->x;
int a_y = a1->y;
int b_x = b1->x;
int b_y = b1->y;
if (a_x > b_x)
return 1;
else if (a_x < b_x)
return (-1);
else if (a_x == b_x)
{
if (a_y < b_y)
return 1;
else if (a_y > b_y)
return (-1);
else
return 0;
}
}
...gives me a different wrong output:
2 2
12 2
2 7
3 4
2 5
The compare function gets pointers to the elements to be sorted, so here it gets pointers to coordinates pointers. The correct beginning is:
int compare(const void *a, const void *b)
{
const coordinates *a1 = *(const coordinates **)a;
const coordinates *b1 = *(const coordinates **)b;
I added const because you shouldn't cast away const-ness, even if it doesn't matter here. You would notice if you used warnings with the compilation.
You should also use sizeof(coordinates) in the call to qsort, not sizeof(coordinates*), because otherwise the sort function can't know how big your elements are, but these two probably have the same value here.
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
In this declaration
coordinatesList *A = (coordinatesList*)malloc(n * sizeof(coordinates));
you have to use expression sizeof( coordinatesList ) instead of the expressions sizeof( coordinates ).
In the function compare you have to write
int compare(const void *a, const void *b)
{
const coordinatesList a1 = *( const coordinatesList *)a;
const coordinatesList b1 = *( const coordinatesList *)b;
//...
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
typedef struct x_y
{
int x;
int y;
} coordinates;
typedef coordinates *coordinatesList;
int compare( const void *a, const void *b )
{
const coordinatesList a1 = *( const coordinatesList * )a;
const coordinatesList b1 = *( const coordinatesList * )b;
if ( a1->x < b1->x )
{
return -1;
}
else if ( b1->x < a1->x )
{
return 1;
}
else
{
if ( a1->y < b1-> y )
{
return 1;
}
else if ( b1->y < a1->y )
{
return -1;
}
else
{
return 0;
}
}
}
int main(void)
{
const size_t N = 5;
coordinatesList *A = malloc( N * sizeof( coordinatesList ) );
for ( size_t i = 0; i < N; i++ )
{
A[i] = malloc( sizeof( coordinates ) );
}
A[0]->x = 2; A[0]->y = 5;
A[1]->x = 12; A[1]->y = 2;
A[2]->x = 2; A[2]->y = 7;
A[3]->x = 3; A[3]->y = 4;
A[4]->x = 2; A[4]->y = 2;
for ( size_t i = 0; i < N; i++ )
{
printf( "%d\t%d\n", A[i]->x, A[i]->y );
}
putchar( '\n' );
qsort( A, N, sizeof( coordinatesList ), compare );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d\t%d\n", A[i]->x, A[i]->y );
}
putchar( '\n' );
return 0;
}
Its output is
2 5
12 2
2 7
3 4
2 2
2 7
2 5
2 2
3 4
12 2
I'm trying to write a sorting function with just recursion. I keep getting the error:
lvalue required as unary '&' operand
This are the functions I'm using:
void sorter_rec (int a[], int n) {
if (n ==1 ) return;
else {
swap( &(maximumrec(a,n)), &a[n-1]);
sorter_rec(a,n-1);
return;
};
}
The error is in sorter_rec.
void swap(int *px, int *py)
{ int z = *px;
*px = *py;
*py = z;
return;
}
int maximumrec(int ar[], int n)
{
if (n == 1) {
return ar[0];
} else {
int max = maximumrec(ar, n-1);
return ar[n-1] > max ? ar[n-1] : max;
}
}
How can I solve this?
You may not apply the operator & to the temporary object returned by the function maximumrec.
Also if you are using the selection sort starting from the end of array then the maximum element should be also searched starting from the end of array. In this case the sorting algorithm will be more stable.
Here is a demonstrative program that uses your approach but instead of the searching maximum element it searches minimum element. You can rewrite it such a way that it would search the maximum element if you want.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define N 20
int * min_element( int a[], size_t n )
{
int *min = a;
if ( !( n < 2 ) )
{
min = min_element( a + 1, n - 1 );
min = *min < *a ? min : a;
}
return min;
}
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void sort( int a[], size_t n )
{
if ( !( n < 2 ) )
{
int *min = min_element( a, n );
if ( min != a ) swap( a, min );
sort( a + 1, n - 1 );
}
}
int main(void)
{
int a[N];
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < N; i++ ) a[i] = rand() % N;
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
sort( a, N );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
return 0;
}
The program output might look like
17 9 12 15 1 17 19 17 6 2 14 19 2 8 5 19 0 12 16 8
0 1 2 2 5 6 8 8 9 12 12 14 15 16 17 17 17 19 19 19
Your basic algorithm works. All I had to do was fix up the way you passed pointers around, and it worked the first time! Hope this helps. I changed some names to fit my own style a bit, and added some convenience things (macro and logging method), and main() so I could test it.
Note that the name of an array is the same as &array[0]
#include <stdio.h>
#define INT_COUNT(n) (sizeof(n) / sizeof(int))
void dumpIntArray(int *array, int n) {
printf("{ ");
for (int i = 0; i < n; i++) {
printf("%d ", array[i]);
}
printf(" }\n");
}
void swap(int *px, int *py) {
int z = *px;
*px = *py;
*py = z;
return;
}
int *ptrToMax(int *sortable, int n) {
if (n == 1) {
return sortable;
} else {
int *maximum = ptrToMax(sortable, n - 1);
return sortable[n - 1] > *maximum ? &sortable[n - 1] : maximum;
}
}
void quicksort(int *sortable, int n) {
if (n == 1 ) {
return;
} else {
swap(ptrToMax(sortable, n), &sortable[n - 1]);
quicksort(sortable, n - 1);
return;
}
}
int main(int argc, char **argv) {
int foo[] = { 1, 5, 3, 2, 4, 9, 10, 8, 7 };
printf("Before:\n");
dumpIntArray(foo, INT_COUNT(foo));
quicksort(foo, INT_COUNT(foo));
printf("After:\n");
dumpIntArray(foo, INT_COUNT(foo));
}