exchange index in 2D array using pointer in C - c

I have a problem to exchange the values of an index in a 2D array by using a pointer. My code for example has an two dimensional array with the initialization {{1,2},{2,3},{3,4},{4,5}} and I want to exchange the values of two indexes in the 2D array. I created a function named swap like this:
void swap(double points[20][2],int i, int j){
double *a,*b;
a= *(*(points +i)+ 0;
*(*(points +i)+ 0 = points[j][0];
*(*(points +j)+ 0 = a;
b= *(*(points +i)+ 1;
*(*(points +i)+ 1 = points[j][1];
*(*(points +j)+ 1 = a;
}
i,j here mean I want to change index i to j and vice-versa so for example when I used swap(points,0,1) the 2D array points will change like this: {{2,3},{1,2},{3,4},{4,5}}
Any help would appreciated.

You can treat 2D array as a pointer to 1D arrays, and do a swap using a temporary array, like this:
void swap(double points[20][2],int i, int j) {
double tmp[2];
memcpy(tmp, points+i, sizeof(*points));
memcpy(points+i, points+j, sizeof(*points));
memcpy(points+j, tmp, sizeof(*points));
}
demo
The implementation is the classic swap, i.e.
tmp = points[i];
points[i] = points[j];
points[j] = tmp;
but since arrays in C cannot be assigned as a unit, memcpy is used instead.

Here you are
void swap( double points[][2], size_t i, size_t j )
{
double ( *a )[2] = points + i;
double ( *b )[2] = points + j;
for ( size_t i = 0; i < 2; i++ )
{
double tmp = ( *a )[i];
( *a )[i] = ( *b )[i];
( *b )[i] = tmp;
}
}
Or entirely without the subscript operator
void swap( double points[][2], size_t i, size_t j )
{
double ( *a )[2] = points + i;
double ( *b )[2] = points + j;
for ( size_t i = 0; i < 2; i++ )
{
double tmp = *( *a + i );
*( *a + i ) = *( *b + i );
*( *b + i ) = tmp;
}
}
Here is a demonstrative program
#include <stdio.h>
#define N 2
void swap( double points[][N], size_t i, size_t j )
{
double ( *a )[N] = points + i;
double ( *b )[N] = points + j;
for ( size_t i = 0; i < N; i++ )
{
double tmp = *( *a + i );
*( *a + i ) = *( *b + i );
*( *b + i ) = tmp;
}
}
int main(void)
{
double points[][N] =
{
{ 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }
};
const size_t M = sizeof( points ) / sizeof( *points );
for ( size_t i = 0; i < M; i++ )
{
printf( "{ %.1f, %.1f } ", points[i][0], points[i][1] );
}
putchar( '\n' );
swap( points, 0, 1 );
for ( size_t i = 0; i < M; i++ )
{
printf( "{ %.1f, %.1f } ", points[i][0], points[i][1] );
}
putchar( '\n' );
return 0;
}
The program output is
{ 1.0, 2.0 } { 2.0, 3.0 } { 3.0, 4.0 } { 4.0, 5.0 }
{ 2.0, 3.0 } { 1.0, 2.0 } { 3.0, 4.0 } { 4.0, 5.0 }

Related

Set typedef that can be 2 different types

I am trying to make a function that can receive a variable which can be a char or an int and for that I have to give the variable a type but I don't know what to put because I want it to be able to receive both.
My code is like this and i don't know what to put in the spot where is written 'IDK':
#include <stdio.h>
#include <string.h>
int is_string = 0;
#define less(A,B) (!is_string ? ((A)<(B)) : (strcmp(A,B)<0))
void merge(IDK a[], int l, int m, int r)
{
IDK aux[10000][20];
int i, j, k;
for (i = m+1; i > l; i--) aux[i-1] = a[i-1];
for (j = m; j < r; j++) aux[r+m-j] = a[j+1];
for (k = l; k <= r; k++){
if (less(aux[j], aux[i])) a[k] = aux[j--];
else a[k] = aux[i++];
}
}
void mergesort(IDK a[], int l, int r) {
int m = (r+l)/2;
if (r <= l)
return;
mergesort(a, l, m);
mergesort(a, m+1, r);
merge(a, l, m, r);
}
int main(){
mergesort(a,left,right);
}
I want the 'IDK' to be char when the variable is_stringis 1, and int when else...
The goal is to use the function to sort words alphabetically or numbers (lowest to highest), the function just has to sort one type of object at a time, but I want it to be able to sort both types of objects so I don't have to repeat code.
I want to have a program that chooses (at runtime) what type it needs to sort.
Thanks
The general approach of writing such functions in C is to declare a function that accepts a pointer of the type void * together with the number of elements in the passed array, the size of an object of the array element type and a comparison function similarly how the standard C function qsort is declared.
Here is a demonstrative program that shows such an approach.
The function merge can be written without allocating dynamically memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void merge( void *a, size_t m, size_t n, size_t size, int cmp( const void *, const void * ) )
{
void *p = malloc( n * size );
size_t i = 0, j = m;
char *pos = p;
while ( i < m && j < n )
{
if ( cmp( ( char * )a + j * size, ( char *)a + i * size ) < 0 )
{
memcpy( pos, ( char * )a + j * size, size );
++j;
}
else
{
memcpy( pos, ( char * )a + i * size, size );
++i;
}
pos += size;
}
if ( i < m )
{
memcpy( pos, ( char * )a + i * size, ( m - i ) * size );
}
if ( j < n )
{
memcpy( pos, ( char * )a + j * size, ( n - j ) * size );
}
memcpy( a, p, n * size );
free( p );
}
void mergesort( void *a, size_t n, size_t size, int cmp( const void *, const void * ) )
{
if ( n / 2 )
{
mergesort( a, n / 2, size, cmp );
mergesort( ( char * )a + n / 2 * size, n - n / 2, size, cmp );
merge( a, n / 2, n, size, cmp );
}
}
int cmp_int( const void *p1, const void *p2 )
{
int a = *( int * )p1;
int b = *( int * )p2;
return ( b < a ) - ( a < b );
}
int cmp_string( const void *p1, const void *p2 )
{
return strcmp( *( const char * const * )p1, *( const char * const * )p2 );
}
int main(void)
{
int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N1 = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N1; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
mergesort( a, N1, sizeof( *a ), cmp_int );
for ( size_t i = 0; i < N1; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
char * s[] = { "J", "I", "H", "G", "F", "E", "D", "C", "B", "A" };
const size_t N2 = sizeof( s ) / sizeof( *s );
for ( size_t i = 0; i < N2; i++ )
{
printf( "%s ", s[i] );
}
putchar( '\n' );
mergesort( s, N2, sizeof( *s ), cmp_string );
for ( size_t i = 0; i < N2; i++ )
{
printf( "%s ", s[i] );
}
putchar( '\n' );
return 0;
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
J I H G F E D C B A
A B C D E F G H I J
You're looking for a union, but that won't work with your calls to scanf and printf. They expect a certain type of argument depending on the format modifier, in this case expecting an int or int* for modifier "%d".
union IDK
{
int int_val;
char *string_val;
};
void merge(union IDK a[], int l, int m, int r);
What you read from the console is always a string. scanf can convert it to a number, if that's what you ask for with "%d". But it appears that what you really are looking for is a way to sort strings that may consist of digits. The easiest way to do that is to try to convert it using strtol.
There's another pitfall you should be aware of. strcmp compares the ASCII values of characters. This won't sort alphabetically, if that's what you're looking for.
Note that a generalized sorting function is usually implemented by passing it a void*, the number of elements, the size of those elements, and a function pointer to a comparison function. See qsort for an example.

C kind of sorting

Ok so a function which arranges the elements in an array in such a way that all elements
smaller than a given value are placed into positions to the left of the elements that are larger
than the given value.
For instance if the array contents are {4,6,2,9,1,7,3,10} and x is given as 5, then
{4,3,2,1,9,7,6,10} is a possible solution, since all elements smaller than 5 are to the left
of the elements larger than 5.
Also, using brackets [ ] is ​ forbidden ​ except for defining the array in the main function.
Also, implement a function which prints the contents of an array. Both functions must be
implemented recursively.
you are allowed to access each element of the array only for once.
ok so this "challenge" and I dont know if it is possible with the given restrictions. I have tried to make it with a while loop and then convert it to recursive somehow but you are not allowed to change the parameters as well. Does anyone know a solution.
I have written something but its garbage.
#include <stdio.h>
#define length 8
void selection(int array[],int size, int x){
int i=0;
int temp;
if(( array[i]>x ) && (array[i] > array[i+1])){
temp=array[i+1];
array[i+1]=array[i];
array[i]=temp;
i++;
selection(array+1,size-1,x)
}
else if(( array[i] > x) && ( array[i+1] > array[i])){
i++;
}
//This is not correct
}
void printArray(int arr[], int start, int len)
{
if(start >= len)
return;
printf("%d ", arr[start]);
printArray(arr, start + 1, len);
}
int main(){
int array[length]={6,4,2,9,1,7,3,10};
int x=5;
selection(array,length,x);
printArray(array,0,length);
return 0;
}
I havent implemented the a recursive solution because things I tried kept giving segmentation faults because I was reaching outside the array.
Can anyone do this recursivly without for or while. I guess you need to split the array and look at it half by half
Here you are.
#include <stdio.h>
void partition( int a[], size_t n, int pivot )
{
if ( !( n < 2 ) )
{
if ( *a < pivot )
{
partition( a + 1, n - 1, pivot );
}
else
{
if ( *( a + n - 1 ) < pivot )
{
int tmp = *a;
*a = *( a + n - 1 );
*( a + n - 1 ) = tmp;
partition( a + 1, n - 2, pivot );
}
else
{
partition( a, n - 1, pivot );
}
}
}
}
int main(void)
{
int a[] = { 4, 6, 2, 9, 1, 7, 3, 10 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
int pivot = 5;
partition( a, N, pivot );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
return 0;
}
The program output is
4 6 2 9 1 7 3 10
4 3 2 1 9 7 6 10
Or also with a recursive definition of the function printArray.
#include <stdio.h>
void partition( int a[], size_t n, int pivot )
{
if ( !( n < 2 ) )
{
if ( *a < pivot )
{
partition( a + 1, n - 1, pivot );
}
else
{
if ( *( a + n - 1 ) < pivot )
{
int tmp = *a;
*a = *( a + n - 1 );
*( a + n - 1 ) = tmp;
partition( a + 1, n - 2, pivot );
}
else
{
partition( a, n - 1, pivot );
}
}
}
}
void printArray( const int a[], size_t n )
{
if ( n )
{
printf( "%d ", *a );
printArray( a + 1, n - 1 );
}
else
{
putchar( '\n' );
}
}
int main(void)
{
int a[] = { 4, 6, 2, 9, 1, 7, 3, 10 };
const size_t N = sizeof( a ) / sizeof( *a );
printArray( a, N );
int pivot = 5;
partition( a, N, pivot );
printArray( a, N );
return 0;
}
The recursive function printArray also can be defined the following way
void printArray( const int a[], size_t n )
{
n == 0 ? ( void )putchar( '\n' )
: ( printf( "%d ", *a ), printArray( a + 1, n - 1 ) );
}

Copying Array Using Pointers

I am trying to create a copy of an array by only accessing an array using pointer arithmetic. This is my function
int* arrCopy(int *a, int size){
int *b = (int*)malloc(size*sizeof(int));
for(int i = 0; i < size; i++){
*(b+(sizeof(int)*i)) = *(a+(sizeof(int)*i));
}
return b;
}
When I print the array it shows that the copied array is filled with the repeating of the first two values in the original array. So if the original array was [1, 2, 3, 4, 5], then arrcopy would be [1, 2, 1 ,2 ,1] and I can't figure out why.
Here you are
int * arrCopy( const int *a, size_t n )
{
int *b = malloc( n * sizeof( int ) );
for ( size_t i = 0; i < n; i++ )
{
*( b + i ) = *( a + i );
}
return b;
}
Or you could check whether the memory was successfully allocated.
int * arrCopy( const int *a, size_t n )
{
int *b = malloc( n * sizeof( int ) );
if ( b != NULL )
{
for ( size_t i = 0; i < n; i++ )
{
*( b + i ) = *( a + i );
}
}
return b;
}
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
int * arrCopy( const int *a, size_t n )
{
int *b = malloc( n * sizeof( int ) );
if ( b != NULL )
{
for ( size_t i = 0; i < n; i++ )
{
*( b + i ) = *( a + i );
}
}
return b;
}
int main(void)
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
int *b = arrCopy( a, N );
if ( b != NULL )
{
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", b[i] );
}
putchar( '\n' );
}
free( b );
return 0;
}
Its output is
0 1 2 3 4 5 6 7 8 9
As for your code then for example this expression
*(b+(sizeof(int)*i))
is invalid. It selects the element of the array b equivalent to
b[sizeof(int)*i]
So for example when i is equal to 1 and sizeof( int ) equal to 4 then instead of getting the element b[1] you are getting the element b[4].
From the C Standard (6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero).

qsort with structs in C

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

Setting up and accessing array of void pointers

In a block of memory, treatead as two segments, A and B,
i set up pointers in segment A such that values from
segment B can be viewed as matrices and accessed by indices:
float **matrix = ( ( void ** ) view->data[ i ] )[ j ];
After allocating memory and assigning the pointers i then set all the
values for a specific matrix.
However, when trying to print individual values of that matrix,
the program seg-faults due to an invalid read.
If i dont't call the set_weights function, values are printed
fine ( and valgrind reports no leaks ). So i assume that trying
to set values has an unwanted side effect of messing up pointers.
I would like to understand if the error is in the pointer assignments
or on access.
Pease have a look and help me.
Regards,
Alfred
[ OS: x86_64 debian linux, gcc 4.2.9 ]
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
enum { Weight, Delta, Max };
typedef struct {
void **data;
} View;
void matrix_2D_print( int x, int y, float **values ) {
int i, j;
for( i = 0; i < x; ++i ) {
for( j = 0; j < y; ++j ) {
printf( "\t\t%f", values[ i ][ j ] ); // Invalid read
if( j < ( y - 1 ) ) {
printf( ", " );
}
}
printf( "\n" );
}
}
void set_weights( int layers, int x, int y, View *view ) {
int i, j, l;
void **view_ptr = view->data[ Weight ];
for( l = 0; l < layers; ++l ) {
float **m2_data = view_ptr[ l ];
for( i = 0; i < x; ++i ) {
for( j = 0; j < y; ++j ) {
m2_data[ i ][ j ] = 0.27f;
}
}
}
}
int main( int argc, char **argv ) {
int i, l, m;
int x = 3;
int y = 2;
int layers = 2;
size_t step_view = Max * sizeof( void ** );
size_t len_step_view = x * sizeof( void ** );
size_t len_segment_A = step_view + x * layers * Max * sizeof( void ** );
size_t len_segment_B = x * y * layers * Max * sizeof( float );
char *storage = calloc( 1, len_segment_A + len_segment_B );
float *segment_b = ( float * )( storage + len_segment_A );
View view;
view.data = ( void ** ) storage;
for( m = 0; m < Max; ++m ) {
void **segment_a = ( void ** )( storage + step_view );
view.data[ m ] = segment_a;
for( l = 0; l < layers; ++l ) {
segment_a[ l ] = segment_b;
void **cur = segment_a[ l ];
for( i = 0; i < x; ++i ) {
cur[ i ] = segment_b;
segment_b += y;
}
step_view += len_step_view;
}
}
assert( len_segment_A == step_view );
set_weights( layers, x, y, &view );
void **view_ptr = view.data[ Weight ];
printf( "\tLayer: %d\n", 0 );
matrix_2D_print( x, y, view_ptr[ 0 ] );
free( storage );
return 0;
}

Resources