My function prototype is
int** rotate(int **arr, int row, int col, int fl);
where arr is the two dimensional array, row and col is the number of row and columns of the 2D array respectively, fl is a flag variable. If the value of fl is 0 then the array will be rotated right, if fl is 1 then the array will be rotated left.
I have called the function as follows:
int **res= rotate(arr, row, col, fl);
But I got one warning and one note
[Warning] passing argument 1 of 'rotate' from incompatible pointer type.
[Note] expected 'int **' but argument is of type 'int (*)[20]'
A pointer to a pointer is different from a pointer to an array. Array-to-pointer decaying can only happen on the left-most side (e.g. int [3][20] to int (*)[20]).
Change your function declaration to
int** rotate(int (*arr)[20], int row, int col, int fl);
or more obviously,
int** rotate(int arr[][20], int row, int col, int fl);
Note you have to fix the size at compile-time.
If your compiler supports variable length arrays then the function declaration can look the following way
void rotate( size_t row, size_t col, int arr[][col], int fl);
or
void rotate( size_t row, size_t col, int arr[][col], _Bool fl);
In this case you can use arrays with different sizes.
Here is a demonstrative program
#include <stdio.h>
void rotate( size_t row, size_t col, int a[][col], _Bool fl )
{
for ( size_t i = 0; i < ( fl ? row : col ); i++ )
{
for ( size_t j = 0; j < ( fl ? col : row ); j++ )
{
printf( "%d ", a[fl ? i : j][fl ? j : i] );
}
putchar( '\n' );
}
}
#define N1 3
int main(void)
{
int a[][3] =
{
{ 1, 2, 3 },
{ 4, 5, 6 }
};
rotate( sizeof( a ) / sizeof( *a ), N1, a, 0 );
putchar( '\n' );
rotate( sizeof( a ) / sizeof( *a ), N1, a, 1 );
putchar( '\n' );
return 0;
}
Its output is
1 4
2 5
3 6
1 2 3
4 5 6
Otherwise if within the function you are going to create new arrays then the function can look as it is shown in the following demonstrative program.
#include <stdio.h>
#include <stdlib.h>
int ** rotate( size_t, size_t, int a[][*], _Bool fl );
int ** rotate( size_t row, size_t col, int a[][col], _Bool fl )
{
int **p = malloc( col * sizeof( int * ) );
for ( size_t i = 0; i < col; i++ )
{
p[i] = ( int * )malloc( row * sizeof( int ) );
}
if ( fl )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
p[col - j - 1][i] = a[i][j];
}
}
}
else
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
p[j][i] = a[row - i - 1][j];
}
}
}
return p;
}
#define M 2
#define N 3
int main(void)
{
int a[M][N] =
{
{ 1, 2, 3 },
{ 4, 5, 6 }
};
int **p = rotate( M, N, a, 0 );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < M; j++ )
{
printf( "%d ", p[i][j] );
}
putchar( '\n' );
}
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
free( p[i] );
}
free( p );
p = rotate( M, N, a, 1 );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < M; j++ )
{
printf( "%d ", p[i][j] );
}
putchar( '\n' );
}
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
free( p[i] );
}
free( p );
return 0;
}
Its output is
4 1
5 2
6 3
3 6
2 5
1 4
From the example, I assume that you are using a static definition of arr.
The Pointer to pointer is not the same as a 2D array.
Change
int** rotate(int **arr, int row, int col, int fl);
to
int** rotate(int arr[][20], int row, int col, int fl);
Note that the no of columns will have to be defined before compilation.
Related
So I don't want to make a function for every data type, I would like to be able to just use pointers to fix the problem. Tried the idea with a function for copying an array. I didn't get the result i expected or wanted, even if it had just gone entirely wrong with the new_arr not changing at all i would be ok this isn't it. but it gave me hope.
void *copy_array(const void *arr[], const void *new_arr[], size_t arr_len, size_t type_size) {
for (int i = 0; i < arr_len ; ++i) {
*(new_arr + (i * type_size)) = *(arr + (i * type_size));
}
}
void print_int_array(int * array, int length) {
for (int i = 0; i < length; ++i) {
printf("\nelement %d = %d", i, array[i]);
}
}
int main() {
int arr[ARRAY_LENGTH] = {12, 3,4};
int new_arr[ARRAY_LENGTH] = {0, 0, 0};
print_int_array(arr, ARRAY_LENGTH);
print_int_array(new_arr, ARRAY_LENGTH);
copy_array(&arr, &new_arr, ARRAY_LENGTH, sizeof(new_arr[0]));
print_int_array(arr, ARRAY_LENGTH);
print_int_array(new_arr, ARRAY_LENGTH);
return 0;
}
Console returns this for some reason, it gets the 12 and the 3 by why not the 4?
element 0 = 12
element 1 = 3
element 2 = 4
element 0 = 0
element 1 = 0
element 2 = 0
element 0 = 12
element 1 = 3
element 2 = 4
element 0 = 12
element 1 = 3
element 2 = 0
You declared a function
void *copy_array(const void *arr[], const void *new_arr[], size_t arr_len, size_t type_size) {
where the both first parameters have the qualifier const. So the function declaration is incorrect.
Instead it would be better to declare the first parameter of the function print_int_array with the qualifier const and the second parameter as having the type size_t
void print_int_array( const int * array, size_t length) {
On the other hand, the expressions
*(new_arr + (i * type_size))
and
*(arr + (i * type_size))
have pointer types. Their sizes can be greater than the size of an object of the type int. For example sizeof( void * ) can be equal to 8 while sizeof( int ) can be equal to 4.
Thus the function can invoke undefined behavior.
Apart from that the function has a non-void return type but returns nothing.
Also there is no great sense to call the function passing pointers to arrays like
copy_array(&arr, &new_arr, ARRAY_LENGTH, sizeof(new_arr[0]));
where each expression has the type int( * )[3].
The function can be defined the following way as shown in the demonstration program below.
#include <stdio.h>
#include <string.h>
void copy_array( void *new_arr, const void *arr, size_t arr_len, size_t type_size )
{
for (size_t i = 0; i < arr_len; i++)
{
memcpy( new_arr, arr, type_size );
new_arr = ( char * )new_arr + type_size;
arr = ( const char * )arr + type_size;
}
}
int main( void )
{
enum { ARRAY_LENGTH = 3 };
int arr[ARRAY_LENGTH] = { 12, 3,4 };
int new_arr[ARRAY_LENGTH] = { 0, 0, 0 };
printf( "arr : " );
for (size_t i = 0; i < ARRAY_LENGTH; i++)
{
printf( "%d ", arr[i] );
}
putchar( '\n' );
printf( "new_arr: " );
for (size_t i = 0; i < ARRAY_LENGTH; i++)
{
printf( "%d ", new_arr[i] );
}
putchar( '\n' );
putchar( '\n' );
copy_array( new_arr, arr, ARRAY_LENGTH, sizeof( int ) );
printf( "arr : " );
for (size_t i = 0; i < ARRAY_LENGTH; i++)
{
printf( "%d ", arr[i] );
}
putchar( '\n' );
printf( "new_arr: " );
for (size_t i = 0; i < ARRAY_LENGTH; i++)
{
printf( "%d ", new_arr[i] );
}
putchar( '\n' );
}
The program output is
arr : 12 3 4
new_arr: 0 0 0
arr : 12 3 4
new_arr: 12 3 4
So this is what i wanted to do which is basicly memcpy. The arrays get converted to char arrays which is only 1 byte, so every byte gets copied from the size of the original array.
void copy_array(void *arr, void *new_arr, size_t arr_size) {
char *char_new_arr = (char *) new_arr;
char *char_arr = (char *) arr;
for (int i = 0; i < arr_size; ++i) {
char_new_arr[i] = char_arr[i];
}
}
#include <stdio.h>
int removeduplicates(int arr[],int n){
int j=0;
int temp[15];
if(n==0 || n==1){
return n;
}
for(int i=0;i<n-1;i++){
if(arr[i]!=arr[i+1]){
temp[j++]=arr[i];
}
temp[j++]=arr[n-1];
}
for(int i=0;i<j;i++){
arr[i]=temp[i];
}
return j;
}
int main(){
int n;
int num[];
num[]= {1,2,3,3,4,4,5,5,5};
n= sizeof(num)/sizeof(num[0]);
n=removeduplicates(num,n);
printf("%d",n);
return 0;
}
Here in this question I was writing a code to remove duplicates from a sorted array. But I am getting the following error although I defined the array size and although I provided the array size.
main.c:36:9: error: array size missing in ‘num’
int num[];
^~~
main.c:37:9: error: expected expression before ‘]’ token
num[]= {1,2,3,3,4,4,5,5,5};
This code snippet
int num[];
num[]= {1,2,3,3,4,4,5,5,5};
is syntactically incorrect.
Instead write
int num[] = {1,2,3,3,4,4,5,5,5};
Also within the function this declaration with the magic number 15
int temp[15];
and this statement
temp[j++]=arr[n-1];
in the substatement of this for loop
for(int i=0;i<n-1;i++){
if(arr[i]!=arr[i+1]){
temp[j++]=arr[i];
}
temp[j++]=arr[n-1];
}
do not make a sense.
To remove duplicates there is no need to define an auxiliary array.
The function can be written for example the following way as shwon in the demonstrative program below.
#include <stdio.h>
size_t removeduplicates( int arr[], size_t n )
{
size_t m = 0;
for ( size_t i = 0; i != n; )
{
if ( m != i )
{
arr[m] = arr[i];
}
++m;
while ( ( ++i != n && arr[i] == arr[i-1] ) );
}
return m;
}
int main(void)
{
int num[]= { 1, 2, 3, 3, 4, 4, 5, 5, 5 };
const size_t N = sizeof( num ) / sizeof( *num );
for ( size_t i = 0; i != N; i++ )
{
printf( "%d ", num[i] );
}
putchar( '\n' );
size_t m = removeduplicates( num, N );
for ( size_t i = 0; i != m; i++ )
{
printf( "%d ", num[i] );
}
putchar( '\n' );
return 0;
}
The program output is
1 2 3 3 4 4 5 5 5
1 2 3 4 5
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.
My function prototype is
int** rotate(int **arr, int row, int col, int fl);
where arr is the two dimensional array, row and col is the number of row and columns of the 2D array respectively, fl is a flag variable. If the value of fl is 0 then the array will be rotated right, if fl is 1 then the array will be rotated left.
I have called the function as follows:
int **res= rotate(arr, row, col, fl);
But I got one warning and one note
[Warning] passing argument 1 of 'rotate' from incompatible pointer type.
[Note] expected 'int **' but argument is of type 'int (*)[20]'
A pointer to a pointer is different from a pointer to an array. Array-to-pointer decaying can only happen on the left-most side (e.g. int [3][20] to int (*)[20]).
Change your function declaration to
int** rotate(int (*arr)[20], int row, int col, int fl);
or more obviously,
int** rotate(int arr[][20], int row, int col, int fl);
Note you have to fix the size at compile-time.
If your compiler supports variable length arrays then the function declaration can look the following way
void rotate( size_t row, size_t col, int arr[][col], int fl);
or
void rotate( size_t row, size_t col, int arr[][col], _Bool fl);
In this case you can use arrays with different sizes.
Here is a demonstrative program
#include <stdio.h>
void rotate( size_t row, size_t col, int a[][col], _Bool fl )
{
for ( size_t i = 0; i < ( fl ? row : col ); i++ )
{
for ( size_t j = 0; j < ( fl ? col : row ); j++ )
{
printf( "%d ", a[fl ? i : j][fl ? j : i] );
}
putchar( '\n' );
}
}
#define N1 3
int main(void)
{
int a[][3] =
{
{ 1, 2, 3 },
{ 4, 5, 6 }
};
rotate( sizeof( a ) / sizeof( *a ), N1, a, 0 );
putchar( '\n' );
rotate( sizeof( a ) / sizeof( *a ), N1, a, 1 );
putchar( '\n' );
return 0;
}
Its output is
1 4
2 5
3 6
1 2 3
4 5 6
Otherwise if within the function you are going to create new arrays then the function can look as it is shown in the following demonstrative program.
#include <stdio.h>
#include <stdlib.h>
int ** rotate( size_t, size_t, int a[][*], _Bool fl );
int ** rotate( size_t row, size_t col, int a[][col], _Bool fl )
{
int **p = malloc( col * sizeof( int * ) );
for ( size_t i = 0; i < col; i++ )
{
p[i] = ( int * )malloc( row * sizeof( int ) );
}
if ( fl )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
p[col - j - 1][i] = a[i][j];
}
}
}
else
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
p[j][i] = a[row - i - 1][j];
}
}
}
return p;
}
#define M 2
#define N 3
int main(void)
{
int a[M][N] =
{
{ 1, 2, 3 },
{ 4, 5, 6 }
};
int **p = rotate( M, N, a, 0 );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < M; j++ )
{
printf( "%d ", p[i][j] );
}
putchar( '\n' );
}
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
free( p[i] );
}
free( p );
p = rotate( M, N, a, 1 );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < M; j++ )
{
printf( "%d ", p[i][j] );
}
putchar( '\n' );
}
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
free( p[i] );
}
free( p );
return 0;
}
Its output is
4 1
5 2
6 3
3 6
2 5
1 4
From the example, I assume that you are using a static definition of arr.
The Pointer to pointer is not the same as a 2D array.
Change
int** rotate(int **arr, int row, int col, int fl);
to
int** rotate(int arr[][20], int row, int col, int fl);
Note that the no of columns will have to be defined before compilation.
I have a function that requires an array as the argument and returns the same array after modifying it.
The compiling is giving me an error where I pass the argument and call the function.
Why is this so?
int solve(int a[9][9])
{
...
return a;
}
int main()
{
int a[9][9];
a = solve(a); <error here>
}
For starters arrays do not have the assignment operator. Array designators are non-modifiable lvalues.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
... A modifiable lvalue is an lvalue that does not have array type,
does not have an incomplete type, does not have a const
qualified type, and if it is a structure or union, does not have any
member (including, recursively, any member or element of all contained
aggregates or unions) with a const qualified type.
Secondly parameters declared like arrays are adjusted to pointers to their element types.
From the C Standard (6.7.6.3 Function declarators (including prototypes))
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’, where the type qualifiers (if any)
are those specified within the [ and ] of the array type derivation...
For example this function declaration
void f(int a[9][9]);
is adjusted to
void f(int ( *a )[9]);
Thirdly functions may not have arrays as the return type. But they may return pointers.
From the C Standard (6.9.1 Function definitions)
3 The return type of a function shall be void or a complete object
type other than array type.
So for example the function solve can be declared like
int ( * solve(int a[9][9]) )[9]
{
// ...
return a;
}
And if the function changes elements of the array in any case it does not make sense to write
int a[9][9];
a = solve(a);
You can just write
int a[9][9];
solve(a);
or
int a[9][9];
int ( *p )[9] = solve(a);
Here is a demonstrative program
#include <stdio.h>
#define M 2
#define N 3
int ( * f( int ( *a )[N], size_t n ) )[N]
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ ) a[i][j] *= 10;
}
return a;
}
int main(void)
{
int a[M][N] =
{
{ 1, 2, 3 },
{ 4, 5, 6 }
};
f( a, M );
for ( size_t i = 0; i < M; i++ )
{
for ( size_t j = 0; j < N; j++ ) printf( "%d ", a[i][j] );
putchar( '\n' );
}
putchar( '\n' );
int ( *p )[N] = f( a, M );
for ( size_t i = 0; i < M; i++ )
{
for ( size_t j = 0; j < N; j++ ) printf( "%d ", p[i][j] );
putchar( '\n' );
}
putchar( '\n' );
f( p, M );
for ( size_t i = 0; i < M; i++ )
{
for ( size_t j = 0; j < N; j++ ) printf( "%d ", p[i][j] );
putchar( '\n' );
}
putchar( '\n' );
return 0;
}
Its output is
10 20 30
40 50 60
100 200 300
400 500 600
1000 2000 3000
4000 5000 6000
To simplify the function declaration you could introduce a typedef name.
For example
typedef int( *PArray )[N];
PArray f( int ( *a )[N], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ ) a[i][j] *= 10;
}
return a;
}
Or even like this
typedef int( *PArray )[N];
PArray f( PArray a, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ ) a[i][j] *= 10;
}
return a;
}