Copying Array Using Pointers - c

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).

Related

How is qsort able to take in any array types and sort it?

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;

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 ) );
}

exchange index in 2D array using pointer in 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 }

Error while printing 2D array using pointers

I want to print 2D array using pointers but in the printf statement it is showing invalid type argument: (See error in image below:)
#include<stdio.h>
void main()
{
int a[3][3]={1,2,3,4,5,6,7,8,9};
int i,j;
int *p;
p=&a;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
printf("%d",*(p+i)+j);
printf("\n");
}
}
please help me out with this error.
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
This initializer of the pointer p is incorrect.
int *p;
p = &a;
because the pointer and its initializer have different pointer types and there is no implicit conversion between the types.
This expression
*( *( p + i ) + j)
is also invalid. The expression *( p + i ) yields an object of the type int not of a pointer type.
You can use the following approaches
#include <stdio.h>
int main(void)
{
enum { N = 3 };
int a[N][N] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int *p = ( int * )a;
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
printf( "%d ", *( p + i * N + j ) );
}
putchar( '\n' );
}
putchar( '\n' );
for ( int ( *p )[N] = a; p != a + N; ++p )
{
for ( int *q = *p; q != *p + N; ++q )
{
printf( "%d ", *q );
}
putchar( '\n' );
}
putchar( '\n' );
return 0;
}
The program output is:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
a is a pointer to a pointer but you're assigning it to a pointer. If you fix that, rest should work fine

Resources