I need to swap the values of 2 arrays in a function. The problem is I can change anything in the main, just the function itself. It should recive 2 integer arrays, and swap those. The problem is, that I don't know the size of the arrays, and for my understading they can even be in diffrent sizes. Trying this code:
int main()
{
int size = 4; //Please notice that I'm using this only to print the array
int a[] = {1,2,3,4};
int b[] = {5,6,7,8};
printArr(a,"a",size);
printArr(b,"b",size);
swapArray(a,b);
printf("Swapped:\n");
printArr(a,"a",size);
printArr(b,"b",size);
}
and this function:
void swapArray(int **a,int **b)
{
int *p = *a;
*a = *b;
*b = p;
}
while printArr simply prints the array:
void printArr(int arr[],char name[],int size)
{
printf("%s:\t",name);
for(int i=0;i<size;i++){
printf("%d\t",arr[i]);
}
printf("\n");
}
I got a really weird result:
a: 1 2 3 4
b: 5 6 7 8
Swapped:
a: 5 6 3 4
b: 1 2 7 8
I would like to understand why it happens, and not only a working solution.
Thank you :)
In this call
swapArray(a,b);
the argument expressions have the type int * while the function parameters have the type int **. There is no implicit conversion from the type int * to the type int **. So the compiler shall issue a diagnostic message.
In any case the swap function as it is implemented does not make sense. Your program has undefined behavior at least because it tries to swap pointers instead of the arrays themselves.
Take into account that arrays are not pointers though in expressions with rare exceptions they indeed are implicitly converted to pointers to their first elements.
To swap elements of two arrays you have to swap each pair of elemenets separatly.
And you have to supply the number of elements in the arrays. Otherwise the arrays need to have a sentinel value.
Here is a demonstrative program that shows how the function swap can be defined.
#include <stdio.h>
void printArr( const int a[], size_t n, const char *s )
{
printf( "%s:\t", s );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
void swapArray( int *a, int *b, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
int tmp = a[i];
a[i] = b[i];
b[i] = tmp;
}
}
int main(void)
{
enum { N = 4 };
int a[N] = { 1, 2, 3, 4 };
int b[N] = { 5, 6, 7, 8 };
printArr( a, N, "a" );
printArr( b, N, "b" );
putchar( '\n' );
swapArray( a, b, N );
printArr( a, N, "a" );
printArr( b, N, "b" );
putchar( '\n' );
return 0;
}
Its output is
a: 1 2 3 4
b: 5 6 7 8
a: 5 6 7 8
b: 1 2 3 4
You could swap visual representations of original arrays using pointers. But in this case the arrays themselves will not be swapped.
Consider the following program.
#include <stdio.h>
void printArr( const int a[], size_t n, const char *s )
{
printf( "%s:\t", s );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
void swapArray( int **a, int **b )
{
int *tmp = *a;
*a = *b;
*b = tmp;
}
int main(void)
{
enum { N = 4 };
int a[N] = { 1, 2, 3, 4 };
int b[N] = { 5, 6, 7, 8 };
printArr( a, N, "a" );
printArr( b, N, "b" );
putchar( '\n' );
int *pa = a;
int *pb = b;
swapArray( &pa, &pb );
printArr( pa, N, "pa" );
printArr( pb, N, "pb" );
putchar( '\n' );
printArr( a, N, "a" );
printArr( b, N, "b" );
putchar( '\n' );
return 0;
}
Its output is
a: 1 2 3 4
b: 5 6 7 8
pa: 5 6 7 8
pb: 1 2 3 4
a: 1 2 3 4
b: 5 6 7 8
As you see the arrays were not swapped. However the pointers that point to first elements of the arrays were swapped. Using the pointers you can simulate swapping of arrays.
Opposite to C C++ has a template function std::swap for arrays that can be called indeed simply like
std::swap( a, b );
I guess on your platform the size of the pointer is 64 bit, and the size of an in is 32 bit.
When calling swapArray, the compiler implicitly reinterprets your arrays of int as an array of pointers. (These are pointers to int but this is irrelevant here).
swapArray then just swaps the first element of these pointer arrays.
Luckily your original int arrays are large enough so that no illegal access happens.
Since pointer is 64 bit is corresponds to two int which get swapped.
In C an array is not a single "thing" you can swap. You will need to swap it element-by-element.
The only case in which you can swap these array "things" in one time is if they are pointers to arrays.
int *a = malloc(n*sizeof(int));
int *b = malloc(n*sizeof(int));
int *tmp;
tmp=a; a=b; b=tmp;
The problem is, that I don't know the size of the arrays, and for my
understading they can even be in diffrent sizes.
Then let's do it with different sizes! But I don't want to support a "C&P behaviour" and hence I won't provide a complete program. I just provide some short cuts and explain them.
As already shown in the other answers you need to specify the size of an array x[] if you pass it to a function like e.g. swapArray().
But in your main() you are statically defining your two arrays. Let me do it this way:
int a[] = { 1, 2, 3 };
int b[] = { 5, 6, 7, 8, 9 };
Here we defined two arrays statically with different sizes. But the sizes are known. The compiler knows them at build/compile time. There's a build time operator sizeof() which returns the size of a type or a variable at compile time. Hence we can use sizeof(a) to get the size of array a.
But there's one light issue: The "unit" returned by sizeof() is bytes and not elements. Hence we must divide it by the size of the type (here: int) to get the actual number of elements in the array:
size_t size_a = sizeof(a) / sizeof(int);
(Actually this means that for e.g. size_a it will end up with 12 / 4 which will actually write a 3 as a pre-calculated value in your compiled program. I assume here that int takes up 4 bytes.)
For your swapping function you must pass the lower value of both size_a and size_b. We can simply get the minimum value with this:
size_t size_min = (size_a < size_b) ? size_a : size_b;
In case that size_a is smaller then size_a is taken. Otherwise size_b. This is calculated at run time. (If you want to do this at build time because of static values then you need to use preprocessor directives.)
Calling printArr() is straight forward, just pass the correct size:
printArr(b,"b",size_b);
And for swap we use size_min:
swapArray(a, b, size_min);
That's it for handling arrays with different sizes.
A very simple swapArray() could look like this:
void swapArray(int a[],int b[], size_t size) { // or int *a, int *b...
while (size > 0) {
size--;
int tmp = a[size];
a[size] = b[size];
b[size] = tmp;
}
}
We don't need to define an additional loop variable because we can simply use size and decrease it until it reaches 0.
Related
I need to check between two arrays if they are reversed, e.g. A[3] = {1, 2, 3} and B[3] = {3, 2, 1}
Returning zero if A is not the reverse of B of a given length, and 1 otherwise.
Here is what I managed to do for now
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int* input_array(int);
int areReversed(int*, int*, int);
int main()
{
int n = 0;
int* A, * B;
printf("please enter the size of arrays: \n");
scanf("%d", &n);
printf("please enter elements of the first array: \n");
A = input_array(n);
printf("please enter elements of the second array: \n");
B = input_array(n);
areReversed(A, B, n) ? printf("Arrays are the opposite to one another.\n") : printf("Arrays are not the opposite to one another.\n");
free(A); free(B);
}
int areReversed(int* A, int* B, int n) {
int i = 0, j = n-1;
int reverse = 0;
if (n > 1)
{
for (i = 0, j = 0; i < n && j >= 0; i++, j--)
{
if (A[i] == B[j])
{
return areReversed(A + 1, B + 1, n);
}
if (A[i] != B[j])
return 0;
}
return 1;
}
}
`
but sadly its not working and I have tried so many things...
even if you can give hints its will be awesome
areReversed can be simply:
int areReversed(int *A, int *B, int n)
{
return n == 0 || A[0] == B[n-1] && areReversed(A+1, B, n-1);
}
This works:
If n is zero, the two arrays are trivially reverses of each other, since both are empty. (We expect n is not negative.)
Otherwise, we compare the first element of A to the last element of B. If they are unequal, this == and the && fail (produce zero for “false”), and “false” is returned, since the arrays are not reverses of each other.
If they are equal, we also require the rest of the arrays to be reversed, which is handled by a recursive case: The last n-1 elements of A (starting at A+1) must be the reverse of the first n-1 elements of B (starting at B).
With recursion the key is:
To have a robust terminating condition that will be met, and which has a definitive answer.
The problem is a function of a smaller but identical problem.
In this case, the terminating condition is when the length of the arrays n is zero (return true), or when A[0] != B[n-1] (return false)
For an array length n where the two opposite ends are equal (A[0] == B[n-1]), A may be the reverse of B, so you turn the problem into a smaller one and test that. The smaller problem is "one-in" from each end of each array - i.e.:
areReversed( &A[1], B, n - 1 ) ;
If you were doing this iteratively rather then recursively, the "smaller" test after comparing A[0] with B[n-1] would be to compare A[1] with B[n-2]. In recursion only one pair is tested, but the recursive call modifies the parameters to achieve the same effect. So here the recursive call's A is the parent calls &A[1] (or A + 1 if you like - I don't), and the array length is one shorter so that the recursive call's B[n-1] is the parent calls B[n-2].
So:
#include <stdio.h>
#include <stdbool.h>
bool areReversed( int* A, int* B, int n)
{
int is_reverse = false ;
if( n == 0 )
{
is_reverse = true ;
}
else if( A[0] == B[n-1] )
{
is_reverse = areReversed( &A[1], B, n - 1 ) ;
}
return is_reverse ;
}
int main()
{
int A1[] = {1, 2, 5, 14, 9, 3} ;
int B1[] = {3, 9, 14, 5, 2, 1} ;
int A2[] = {1, 2, 5, 14, 9, 3} ;
int B2[] = {3, 9, 14, 5, 2, 7} ;
bool R1 = areReversed( A1, B1, sizeof(A1) / sizeof(*A1) ) ;
bool R2 = areReversed( A2, B2, sizeof(A2) / sizeof(*A2) ) ;
printf( "A1 %s the reverse and B1\n", R1 ? "is" : "is not" ) ;
printf( "A2 %s the reverse and B2\n", R2 ? "is" : "is not" ) ;
}
Outputs:
A1 is the reverse and B1
A2 is not the reverse and B2
And to demonstrate its function with an odd number of elements:
int A1[] = {1, 2, 5, 99, 14, 9, 3} ;
int B1[] = {3, 9, 14, 101, 5, 2, 1} ;
int A2[] = {1, 2, 5, 100, 14, 9, 3} ;
int B2[] = {3, 9, 14, 100, 5, 2, 1} ;
Output then is:
A1 is not the reverse and B1
A2 is the reverse and B2
I recommend that to understand recursion, you use your debugger to step through the code, stepping into each recursive call to observe the "smaller problem" and the meeting the terminating condition, and stepping-out to observe the "unwinding" of the algorithm and final return. In any event you should learn effective use of a debugger - it is a great learning tool to observe the precise behaviour of code and state of variables as well as a debugging aid.
I would also suggest that while a simple function such as this is a useful way of exploring recursion as a concept, it is also trivially implemented using iteration and should probably be done that way in practice. Some problems are much less amenable to iteration and lend themselves to recursion. I'd reserve recursion for such problems - binary search trees, and flood-fill for example spring to mind, though even then recursion is not required, merely simpler.
The problem with recursion is that it has a non-deterministic call-stack requirement and the call-stack is a finite resource - you can literally get a _stack-overflow. In your test case where the data is provided at runtime and is of unlimited length, a malicious or unwary user could cause a stack-overflow with no means in your code to protect against such an attack or misuse.
Let's at first start with your function declaration.
int areReversed(int*, int*, int);
Within the function the passed arrays are not changed are they?
So the corresponding first two function parameters should be declared with the qualifier const
int areReversed( const int *, const int *, int);
Also sizes of entities in C are values of the type size_t. So the third parameter should have the type size_t
int areReversed( const int *, const int *, size_t );
And at last it is a bad idea to use upper case letters as identifiers.
Further, the function returns logical true if either the third parameter is equal to 0 or when the first element of the first array is equal to the last element of the second array and this condition is valid for other elements of the two arrays in recursive calls of the function. Thus it is enough to write only one return statement with the logical expression as described above.
So the function can be defined the following way
int areReversed( const int *a, const int *b, size_t n )
{
return n == 0 || ( a[0] == b[n - 1] && areReversed( a + 1, b, n - 1 ) );
}
But you can reduce the number of recursive calls of the function if you will compare the first element of the first array with the last element of the second array and vice versa when you will compare the last element of the first array with the first element of the second array.
In this case the function will look the following way.
int areReversed( const int *a, const int *b, size_t n )
{
return ( n == 0 ) ||
( n == 1 && a[0] == b[0] ) ||
( a[0] == b[n - 1] && a[n - 1] == b[0] && areReversed( a + 1, b + 1, n - 2 ) );
}
But what to do if the arrays have a different element type?
In this case you have to write another function when for example the array element type is for example double. And moreover you will have to name the function differently that will only confuse readers of your code.
Unfortunately you may not overload functions in C as you may do in C++.
In this case the approach to solve the problem is the same as the approach used in such C standard functions as bsearch and qsort.
That is in this case you have to deal with pointers of the type const void * and to use an auxiliary function that will convert the pointers of the type const void * to the appropriate pointer types.
In this case a general function can look the following way as it is shown in the demonstration program below..
#include <stdio.h>
int areReversed( const void *a, const void *b,
size_t nmemb, size_t size,
int cmp( const void *, const void * ) )
{
return ( nmemb == 0 ) ||
( nmemb == 1 && cmp( a, b ) ) ||
( cmp( a, ( const char * )b + ( nmemb - 1 ) * size ) &&
cmp( b, ( const char * )a + ( nmemb - 1 ) * size ) &&
areReversed( ( const char * )a + size, ( const char * )b + size, nmemb - 2, size, cmp ) );
}
static inline int cmp( const void *a, const void *b )
{
return *( const int * )a == *( const int * )b;
}
int main( void )
{
enum { N = 7 };
int a[N] = { 1, 4, 6, 7, 5, 3, 2 };
int b[N] = { 2, 3, 5, 7, 6, 4, 1 };
printf( "The arrays are reversed relative to each other is %s.\n",
areReversed( a, b, N, sizeof( int ), cmp ) ? "true" : "false" );
}
Opposite to C in C++ you could just use the standard algorithm std::equal . For example a non-recursive function can look like
#include <iostream>
#include <iterator>
#include <algorithm>
template <typename T1, typename T2>
bool areReversed( const T1 &a, const T2 &b )
{
return std::size( a ) == std::size( b ) &&
std::equal( std::begin( a ), std::end( a ), std::rbegin( b ) );
}
int main()
{
enum { N = 7 };
int a[N] = { 1, 4, 6, 7, 5, 3, 2 };
int b[N] = { 2, 3, 5, 7, 6, 4, 1 };
std::cout << "The arrays are reversed relative to each other is "
<< ( areReversed( a, b ) ? "true" : "false" ) << '\n';
}
Bear in mind that if you say that you know C and you do not know C++ and vice versa that you know C++ and you do not know C then usually it means that you know neither C nor C++.:)
I was trying to swap two arrays using pointers.
What I wanted was to swap using a call by reference.
This code I wrote is given below
#include <stdio.h>
#include <stdlib.h>
void swap(int **a, int **b) {
int *temp = (int*)malloc(5*sizeof(int));
temp = *a;
*a = *b;
*b = temp;
}
int main() {
int arr1[] = {1, 2, 3, 4, 5};
int arr2[] = {6, 7, 8, 9, 10};
swap((int**)&arr1, (int**)&arr2);
for(int i=0; i<5; i++) printf("%d\t", arr1[i]);
printf("\n");
for(int i=0; i<5; i++) printf("%d\t", arr2[i]);
printf("\n");
}
The output of the code is:
6 7 3 4 5
1 2 8 9 10
instead of:
6 7 8 9 10
1 2 3 4 5
What did I do wrong?
In this call
swap((int**)&arr1, (int**)&arr2);
the passed pointers point to first elements of the arrays arr1 and arr2.
So within the function swap
void swap(int **a, int **b) {
int *temp = (int*)malloc(5*sizeof(int));
temp = *a;
*a = *b;
*b = temp;
}
dereferencing the pointers like for example
*a
results in reading the first two elements of the array arr1 as a pointer because in your system sizeof( int * ) is equal to 2 * sizeof( int ).
That is values of first two elements of the arrays are interpreted as values of pointers.
And the obtained output confirms that
6 7 3 4 5
1 2 8 9 10
^^^^^
Moreover the function has a memory leak because at first memory was allocated dynamically and its address was assigned to the pointer temp and then the pointer was reassigned
int *temp = (int*)malloc(5*sizeof(int));
temp = *a;
So the address of the allocated memory was lost and the memory was not freed.
You can not swap arrays such a way. You need to swap each pair of elements of the arrays.
The function can look for example the following way
void swap( int *a, int *b, size_t n )
{
for ( int *p = a; p != a + n; ++p, ++b )
{
int temp = *p;
*p = *b;
*b = temp;
}
}
And the function is called like
swap( arr1, arr2, 5 );
A less flexible function can look the following way
void swap( int ( *a )[5], int ( *b )[5] )
{
for ( int *p1 = *a, *p2 = *b; p1 != *a + 5; ++p1, ++p2 )
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
}
And the function is called like
swap( &arr1, &arr2 );
First of all lets fix your swap function:
void swap(int **pparr1, int **pparr2)
{
int *temp = *pparr1;
*pparr1 = *pparr2;
*pparr2 = temp;
}
This function now swaps the two pointers that parr1 and parr2 are pointing to.
Then lest update the way to call this function:
int *parr1 = arr1; // Make parr1 point to the first element of arr1
int *parr2 = arr2; // Make parr2 point to the first element of arr2
// Swap the two pointers
swap(&parr1, &parr2);
And then we print using the pointers instead of the arrays:
printf("arr1 = [ ");
for (unsigned i = 0; i < 5; ++i)
{
printf("%d ", parr1[i]);
}
printf("]\n");
printf("arr2 = [ ");
for (unsigned i = 0; i < 5; ++i)
{
printf("%d ", parr2[i]);
}
printf("]\n");
This will print the arrays as if they were swapped, but in fact the arrays themselves are not swapped. You can verify by printing using the arrays arr1 and arr2 themselves.
If you want to swap the actual contents of the arrays, you need a loop to actually swap the elements themselves:
// Function to swap two integer values
void swap(int *p1, int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
// Function to swap two arrays
void swap_arrays(int *pa1, int *pa2, size_t size)
{
for (size_t i = 0; i < size; ++i)
{
// Swap each separate element of the arrays
swap(&pa1[i], &pa2[i]);
}
}
Call like
swap_arrays(arr1, arr2, 5);
After this the contents of the arrays themselves have been swapped.
swap((int**)&arr1, (int**)&arr2);
It looks like your idea is to have swap swap the address of arr1 with the address of arr2. Variables in C, including arrays, do not work this way, and this idea cannot possibly work.
arr1 is a name for the array. It is not the address of the array, nor is it a variable whose value is the address of the array. There is no pointer to the array that can be swapped with a pointer to the array arr2.
When the compiler processes int arr1[] = {1, 2, 3, 4, 5};, it creates an array of five int, and then it uses arr1 to refer to that array. Wherever arr1 is used, the compiler creates code that will refer to the array. It does not do this by storing the address of the array in some memory location you can swap with another address. It has ways to access the array using registers and processor instructions set up for that.
In swap((int**)&arr1, (int**)&arr2);, you take the addresses of arr1 and arr2 and convert them to int **. The address of arr1 is the address where its contents are. What is at that address in memory is the int elements, not a pointer. So the int ** type does not make sense for this; the address of arr1 is not the address of an int *.
The reason you get the output you do is that int objects are four bytes in your C implementation and int * objects are eight bytes. So when temp = *a; attempts to get the int * that a should be pointing to, it gets the first eight bytes in arr1. Then *a = *b; replaces those eight bytes with the first eight bytes in arr2. And *b = temp; replaces the first eight bytes in arr2 with the saved eight bytes from arr1.
Note that, in these three statements, temp is used to hold eight bytes from arr1. The value it was given in int *temp = (int*)malloc(5*sizeof(int)); is lost when temp is assigned another value in temp = *a;.
Also note that this behavior you observed in this instance is not specified by the C standard, and different behavior can result in other circumstances, including alignment errors and surprising transformations of the program by compiler optimization.
You cannot assign whole arrays to each other in a single operation using =; you must either use a library function like memcpy or assign each element individually.
Under most circumstances, expressions of type "N-element array of T" will be converted, or "decay", to expressions of type "pointer to T" and the value will be a pointer to the first element. If you called the function as
swap( arr1, arr2 );
it would be equivalent to writing
swap( &arr1[0], &arr2[0] );
So you're already passing the arrays "by reference", just not in the way you're probably thinking.
The easiest way to do what you want would be something like this:
void swap( int *a, int *b, size_t count )
{
for ( size_t i = 0; i < count; i++ )
{
int tmp = a[i];
a[i] = b[i];
b[i] = tmp;
}
}
Alternately, you could use memcpy with a temporary array:
void swap( int *a, int *b, size_t count )
{
int tmp[count]; // C99 or later
memcpy( tmp, a, count );
memcpy( a, b, count );
memcpy( b, tmp, count );
}
In this case tmp is a variable-length array, whose size is provided by a runtime value. VLAs are useful for things like this if the array size isn't too big, but they're only available for C99 and later, and are optional after C2011. If your arrays are very large or VLAs aren't available, then this would be a case for dynamic memory:
void swap( int *a, int *b, size_t count )
{
int *tmp = calloc( count, sizeof *tmp );
if ( tmp )
{
memcpy( tmp, a, count );
memcpy( a, b, count );
memcpy( b, tmp, count );
free( tmp );
}
}
The first method (swapping each element individually) would be my preference. It avoids any kind of dynamic memory management, it's straightforward, it's not making a bunch of library calls, etc.
In all three cases, you'd call it as
swap( arr1, arr2, 5 );
Beware explicit casts, especially pointer casts - they're usually a sign you're doing something wrong.
I'd like to increase each element in the array by one in another function than the main function. Then, I'd like to call this function and print in the main function.
#include <stdio.h>
int function(int array2[5]) {
int i;
while(i<4) {
array2[i]=array2[i]+1;
i++;
}
return array2[5];
}
int main() {
int array[5]={1,2,3,4,5};
int answer;
answer[5]=function(array[5]);
int j;
while(j<4) {
printf("%d \n",answer[j]);
j++;
}
return 0;
}
Some important things to know:
When you pass an array in C, you don't make a copy. It is the same array, so modifying the array that is passed in modifies the original.
The [] are operators and not part of the variable name.
The [] work differently in declaring a type than when used in an expression. array[5] gives you the 6th element in array, but int array[5] declares an array with 5 elements.
Accessing an element beyond the end of the allocated array has undefined behavior, but usually will crash.
If you declare a variable int answer it is not an array, and cannot become an array. It is just one int
If you want to make a copy of an array, you need to explicitly copy. There are standard libraries that might do it, but you should learn to copy each element, one by one, to the new array.
The return type int of the function does not make a sense.
int function(int array2[5]) {
And moreover you are trying to return the non-existent 6-th element of an array with only 5 elements.
return array2[5];
Within the function you are using uninitialized variable i
int function(int array2[5]) {
int i;
while(i<4) {
//...
that results in undefined behavior. Also the used magic number 4 does not make a sense at least because you are trying to pass to the function an array with 5 elements.
The function should be declared with a second parameter that specifiers the number of elements in the passed array. This function declaration
int function(int array2[5]);
does not mean that the passed to the function array has exactly 5 elements. The compiler will adjust the parameter declaration of the function to pointer to the array element type like
int function(int *array2);
In this statement in main
int answer;
answer[5]=function(array[5]);
you are using the subscript operator with an object of the scalar type int. So the compiler shall issue an error message.
Here is a demonstrative program that shows how the function can be defined.
#include <stdio.h>
void function( int a[], size_t n )
{
for ( ; n--; ++a )
{
++*a;
}
}
int main(void)
{
int a[] = { 1, 2, 3, 4, 5 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
function( a, N );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
return 0;
}
The program output is
1 2 3 4 5
2 3 4 5 6
There you go. I suppose this is what you want:
#include <stdio.h>
// Since the array named parameters are scoped only within its function,
// they are apart from your array in the main.
void function(int array[], int len) {
int i = 0;
while(i<len) {
array[i]=array[i]+1;
i++;
}
}
// Or alternatively you can process the array using a pointer
void functionWithPointer(int *array, int len) {
int i = 0;
while(i<len) {
*(array+i) = *(array+i)+1;
i++;
}
}
int main() {
int array[]={1,2,3,4,5};
// int answer; // Not necessary
int length = sizeof(array) / sizeof(int); // !!!ATTENTION
function(array, length);
// The array values updated by 1
printf("Array values after 1st update\n");
for(int k=0; k<length; k++) {
printf("%d \n",array[k]);
}
functionWithPointer(array, length);
// The array values updated by 1 again
printf("Array values after 2nd update\n");
int j;
while(j<length) {
printf("%d \n",array[j]);
j++;
}
return 0;
}
Here is the output:
Array values after 1st update
2
3
4
5
6
Array values after 2nd update
3
4
5
6
7
I'm learning C language, and I'm confused in 2D array pointer.
I have the following declaration
int a[3][5];
int *b[3][3];
int (*c)[3][5];
int *(d[3][5]);
int (*e[3])[5];
could anyone help me clarify
if there're valid declaration or not
the sizeof a,b,c,d,e (assume on 64-bit machine, address id 8 bytes)
what they point to
how to access the element in the 2D array
I'm totally confused about the usage of pointer in 2D array.....and I guess some of them are equivalent...but some might not be good practice
These
int a[3][5];
int *b[3][5];
(I think you mean indeed int *b[3][5] instead of int *b[3][3] as it is written in your question)
two declarations of two-dimensional arrays.
Elements of the first array have type int.
Elements of the second array have type int *.
To access elements of the arrays you can use for example subscripting like
a[i][j] or b[i][j] where i is an index in the range [0,3) and j is an index in the range [0, 5).
For the second array to access objects pointed to by the elements of the array you can use expressions like *b[i][j]
sizeof( a ) is equal to 3 * sizeof( int[5] ) that in turn is equal to 3 * 5 * sizeof( int ).
sizeof( b ) is equal to 3 * sizeof( int *[5] ) that in turn is equal to 3 * 5 * sizeof( int *).
This
int (*c)[3][5];
is a declaration of a pointer to a two-dimensional array of the type int[3][5].
You can write for example
int (*c)[3][5] = &a;
where a is the two-dimensional array declared above.
To access elements of the pointed array you can use this syntax
( *c )[i][j]
This
int *(d[3][5]);
a declaration of a two-dimensional array elements of which have type int *.
This declaration is equivalent to the declaration shown above that is to
int *b[3][5];
You may enclose declarators in parentheses. So you could even write the declaration of the array d like
int * (((d)[3])[5]);
This
int (*e[3])[5];
is a declaration of an array with 3 elements of pointers to arrays of the type int[5].
Using the typedef
typedef int T[5];
the array declaration can be rewritten like
T * e[3];
Here a demonstrative program that shows how elements of the array e can be accessed.
#include <stdio.h>
int main( void )
{
int a1[5] = { 1, 2, 3, 4, 5 };
int a2[5] = { 10, 20, 30, 40, 50 };
int a3[5] = { 100, 200, 300, 400, 500 };
int(*e[3])[5] = { &a1, &a2, &a3 };
for (size_t i = 0; i < sizeof( e ) / sizeof( *e ); i++)
{
for (int j = 0; j < sizeof(*e[i]) / sizeof(**e[i]); j++)
{
printf( "%3d ", ( *e[i] )[j] );
}
putchar( '\n' );
}
return 0;
}
The program output is
1 2 3 4 5
10 20 30 40 50
100 200 300 400 500
I was writing a program to concatenate two arrays in C. I am allocating memory for a third array and using memcpy to copy the bytes from the two arrays to the third. The test output is:
1 2 3 4 5 0 0 0 0 0
Is there anything wrong with this approach?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int *array_concat(const void *a, int an,
const void *b, int bn)
{
int *p = malloc(sizeof(int) * (an + bn));
memcpy(p, a, an*sizeof(int));
memcpy(p + an*sizeof(int), b, bn*sizeof(int));
return p;
}
// testing
const int a[] = { 1, 2, 3, 4, 5 };
const int b[] = { 6, 7, 8, 9, 0 };
int main(void)
{
unsigned int i;
int *c = array_concat(a, 5, b, 5);
for(i = 0; i < 10; i++)
printf("%d\n", c[i]);
free(c);
return 0;
}
memcpy(p + an*sizeof(int),...
this second memcpy, you are trying to add 5 * sizeof(int) to an int pointer, p. However, when you add to a pointer, it already knows that it has to deal with sizeof(type), so you don't have to tell it.
memcpy(p + an,...
Remove the multiplication *sizeof(int) from the 1st argument of memcpy. Keep it in the argument of malloc and the 3rd argument of memcpy.
This is because p + an points to an int which is an ints to the right from p -- that is, the int which is an*sizeof(int) bytes to the right from p.
p is a pointer to int. When you add an integer to a pointer to an int, the compiler multiplies the integer by the size of an integer. The net result is to multiply by the size of an integer twice: what you're getting is "p + an*sizeof(int)" is p + (number of elements in a) * (number of bytes in an int) * (number of bytes in an int).
memcpy(p + an*sizeof(int), b, bn*sizeof(int));
should be:
memcpy(p + an, b, bn*sizeof(int));
You should remove sizeof(int) from second memcpy where you use pointer arithmetic (+).
Compiler doing this by itself depending on type of pointer.
you should see the definition of the memcpy, which copy's n "bytes" from the src to the dst area. so,you just need to times sizeof(int) only for the 3rd argument. and for "c", it's a pointer of int type, so, it does know that "+an" means move p forward to the an+1 int position.
Merging can be done by sorting the elements of the elements which are going to be merged code for merging two arrays
#include<stdio.h>
void sort(int arr[],int size){ // sorting function
int i,j,temp;
for(i=0;i<size;i++){
for(j=i;j<size;j++){
if(arr[i]>arr[j]){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
int main(){
int a[10],b[10],c[10];
int n,i,k=0,j=0;
printf("Enter the size of the array:");
scanf("%d",&n);
for(i=0;i<n;i++){
printf("Enter the element of array A at index %d:",i); //input array A
scanf("%d",&a[i]);
}
sort(a,n);
for(i=0;i<n;i++){
printf("Enter the element of array B at index %d:",i); //Input array B
scanf("%d",&b[i]);
}
sort(b,n);
for(i=0;i<(n+n);i++){ // merging the two arrays
if(a[k]<b[j]){
c[i] = a[k];
k++;
}
else{
c[i] = b[j];
j++;
}
}
printf("Merged Array :\n");
for(i=0;i<(n+n);i++){
printf("c -> %d ",c[i]);
}
return 0;
}
Reference C program to Merge Two Arrays after Sorting