Pass in part of an array as function argument - c

I have an array int arr[5] = {10, 2, 3, 5, 1}, and I want to pass in the last 4 elements (basically from index 1 to index4) into an argument as an array (so: [2, 3, 5, 1]). Is there a way to do this very simply (like how in Ruby you would be able to do arr[1..4]), or would I have to use a for loop?

You can manually increment the pointer by 1:
your_function(arr + 1)
Pointer arithmetic in C implicitly accounts for the size of the elements, so adding 1 will actually add 1 * sizeof(int)
For a closer analogue to array slicing from other languages, try this function:
int *slice_array(int *array, int start, int end) {
int numElements = (end - start + 1)
int numBytes = sizeof(int) * numElements;
int *slice = malloc(numBytes);
memcpy(slice, array + start, numBytes)
return slice;
}
It makes a slice of the array between the given start and end indices. Remember to free() the slice once you're done with it!

Answer
Given you current code:
int arr[5] = {10, 2, 3, 5, 1};
You can duplicate the range 1..4 by:
int arr_dup[4];
memcpy(arr_dup,arr+1,sizeof(int)*4);
Remember that your function definition should be a pointer, example:
void a_function(int *arr_arg); //Call via a_function(arr_dup);
Explanation
Arrays in c implemented as pointers (aka variables that hold memory addresses).
If you do arithmetic on the pointer, it will advance to the respective element. Example:
ptr + 1 //Next Element
ptr - 1 //Previous Element

#include <stdio.h>
#include <stdlib.h>
void my_function(int arr_size, int *arr)
{
int i;
for(i=0; i < arr_size; i++)
{
printf("[%d]:%d\n", i, arr[i]);
}
}
int main(int argc, char **argv)
{
int arr[] = { 10, 2, 3, 5, 1 };
(void)my_function(4, &arr[1]); /* TODO > use more flexible indexing */
return EXIT_SUCCESS;
}

I think you can use memcpy,memcpy can copy data byte to byte.In memmory,our data is binary,so even int is 4 bytes,we can copy it byte to byte.
int dst[4];
memcpy(dst,&arr[1],size(int) * 4);

Related

How to find a missing value in an array? [duplicate]

This question already has answers here:
Why sizeof(param_array) is the size of pointer?
(8 answers)
Closed 9 months ago.
I am trying to find the smallest missing element of an array using function check, which has two arguments (n and array A). I can't understand why my function check is always returning one and the while loop is never closing.
#include <stdio.h>
bool check(int n, int A[])
{
for (int i = 0; i < sizeof(A); i++)
{
if(A[i] == n)
{
return 1;
}
}
return 0;
}
int main()
{
int A[] = {1, 3, 6, 4, 1, 2};
int n = 1;
while (check(n, A) == 1)
{
n++;
}
printf("%d is missing",n);
}
The compiler adjusts a parameter having an array type to pointer to the array element type.
So this function declaration
bool check(int n, int A[])
is equivalent to
bool check(int n, int *A );
And within the function the expression sizeof(A) is equivalent to the expression sizeof( int * ) and is equal to either 4 or 8 depending on the used system.
Thus this for loop
for (int i = 0; i < sizeof(A); i++)
invokes undefined behavior.
I know but still that's not why the while loop is never stopping.
Answering your above comment it seems that in the used system sizeof( int * ) is equal to 8 and the variable n is placed in memory after the array A as they defined in main
int A[] = {1, 3, 6, 4, 1, 2};
int n = 1;
As a result you get the infinite wile loop because in the for loop within the function the memory occupied by the variable n is checked and n is always equal to itself.
Thus the function always returns 1.
That is in the for loop the array is traversed as it has 8 elements like
int A[] = {1, 3, 6, 4, 1, 2, n, some_indeterminate_value };

How do you return the last element in an array in C?

How do I return the last element in an array? I thought this function would work, as it worked for a similar function that returned the first element.
int END(int arr[]) {
int last;
size_t s = sizeof(arr) / sizeof(arr[0]);
if (s != 0) {
last = arr[s - 1];
return last;
} else {
return -1 ; //END(arr);
}
}
int END(int arr[]) is adjusted to int END(int* arr), since you can't pass arrays as arguments in C. This means that sizeof(arr) is sizeof(int*), and your calculation for s is wrong.
You can use a macro for this, as the macro argument won't be turned into a pointer implicitly:
#define END(ARR) (ARR)[(sizeof(ARR) / sizeof((ARR)[0])) - 1u]
(Note that there are no arrays of size 0, so your -1 case is redundant)
You cannot use sizeof inside a function because sizeof(arr) will return the size of the pointer which is generally 8 bytes on a x86_64 architecture. I would not use -1 is an error value because -1 can be an element of the given array. I would prefer the C++ way of npos, returning the maximum value of the data type according to the system architecture.
I would recommend you to get the length of the array as a parameter of the function. Like this:
#include <stdio.h>
#include <limits.h>
int END(int *arr, size_t length); // fix prototype error
/*
#brief Returns the last element of the array `arr`.
#param arr array
#param length array's length
#returns If `arr` is NULL or empty returns INT_MAX, otherwise the last element.
*/
int END(int *arr, size_t length)
{
if (!arr || length == 0) // if arr is NULL
return INT_MAX;
else
return arr[length - 1]; // 0 based indexing system in C
}
int main(void)
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
size_t length = sizeof(arr) / sizeof(*arr);
printf("Last element of the array: %d\n", END(arr, length));
return 0;
}
Output:
Last element of the array: 10

len function gives two excess length

i have my length function to calculate the length of array, but it is giving two excess garbage numbers(negative). It must return 6 but it returns 8 due to garbage values.
#include<stdio.h>
int length(int *arr) {
int _length = 0;
while (*arr) {
_length++;
arr++;
}
return _length;
}
int main() {
int arr[] = {2, 1, 3, 4, 5, 6};
printf("%d\n", length(arr));
return 0;
}
You need some manner of termination condition. while (*arr) assumes that the array ends with zero which isn't the case, so you simply can't have a loop like that.
The size of this array is known at compile time so there's no need to calculate anything in run-time.
(sizeof arr / sizeof *arr) gives you the number of items in the array, as long as you place that code in the same scope as the array declaration.
Also, using that sizeof trick (which is an idiomatic way of determining the size) inside a function-like macro is a common solution:
#include <stdio.h>
#define length(arr) (sizeof(arr)/sizeof(*arr))
int main() {
int arr[] = {2, 1, 3, 4, 5, 6};
printf("%zu\n", length(arr));
return 0;
}

Length of 2D array[i]

I'm working in C, and am attempting to replicate the length member function that other languages (ie: C++) use to determine the length of an array or possibly vector of data. Is this something I can accomplish in C, or do I have to fall back onto examples like this:
int arraySize = sizeof(array) / sizeof(array[0]);
In general, in C, you use arrays as they are: a contiguous set of multiple pieces of data of the same type. You are generally expected to keep track of array sizes, along with the size of individual members, yourself.
In C++, for example, you have access to the Vector class, which encapsulates and handles all this record keeping for you.
In C, you would be expected to know exactly how big the array is. This is especially important in the case of pointer decay. Your initial example...
int arrayOfInts[6] = {1, 2, 3, 4, 5, 6};
int sizeOfArray = sizeof(arrayOfInts) / sizeof(int); // Success; Returns "6"
This works in this case, but it will fail if you were to pass the array to a function expecting an array of integers (as a pointer) as a function argument.
#include <stdio.h>
int getArraySize(int* arr);
int main(void) {
int arrayOfInts[6] = {1, 2, 3, 4, 5, 6};
int sizeOfArray = getArraySize(arrayOfInts);
return 0;
}
int getArraySize(int* arr) {
int ret;
ret = sizeof(arr) / sizeof(int); // FAILS, returns the size of a pointer-to-int, not the size of the array
return ret;
}
There are two ways to handle this: static definitions, or careful dynamic memory management.
// CASE 1: Trivial case, all arrays are of a static fixed size
#include <stdio.h>
#define ARR_SIZE (6)
int getArraySize(int* arr);
int main(void) {
int arrayOfInts[ARR_SIZE] = {1, 2, 3, 4, 5, 6};
int sizeOfArray = getArraySize(arrayOfInts);
return 0;
}
int getArraySize(int* arr) {
return ret ARR_SIZE;
}
// CASE 2: Managing sizes with dynamic allocation
#include <stdio.h>
#define ARR_SIZE (6)
int main(void) {
int sizeOfArray = ARR_SIZE;
int* arrayOfInts = malloc(sizeOfArray*sizeof(int));
if (arrayOfInts != NULL) {
// Success; initialize
int i;
for (i=0; i<sizeOfArray; i++) {
arrayOfInts[i] = i;
}
return 0;
} else {
// Failed; abort
sizeOfArray = 0;
return (-1);
}
}

Sorting a C array based on contents of another array

I'm trying to sort an array A whose elements are indexes. The indexes refer to another array B whose value will determine the order of A. So, I would like to sort A such that B[ A[i] ] is increasing.
For example:
A = [0, 1, 4, 5, 7]
B = [5, 3, 8, 2, 2, 7, 1, 6, 3, 9]
Sorted A would be
A' = [ 7, 4, 1, 0, 5 ]
Is this possible with C's built-in sort, or am I going to have to write my own implementation?
EDIT: These arrays are local function variables.
If you want to use qsort, the best thing to-do would be to re-wrap the indexes in A and the values in B into a struct, and then make a comparator based on a new array that struct. For instance:
typedef struct
{
int index_from_A;
int value_from_B;
} index_value_wrapper;
index_value_wrapper index_wrapper_array[5];
for (int i=0; i < 5; i++)
{
index_wrapper_array[i].index_from_A = A[i];
index_wrapper_array[i].value_from_B = B[A[i]];
}
int comparitor (const void* lhs, const void* rhs)
{
return (lhs.value_from_B - rhs.value_from_B);
}
Now you can run qsort on the struct array and from there you can extract the proper sorted sequence you desired for the original array A without having to use a custom sorting function.
If you have it available, qsort_r provides a way to do this. You can give it context information in an additional parameter. That context is passed to the comparison function. You can access that additional information to extract the desired sorting information.
The Microsoft compiler has a similar one: qsort_s
I think you can use qsort and a custom comparator
int comparator(const void *x, const void *y)
{
return ( b[*(int*)x] - b[*(int*)y] );
}
Create another array C of type struct { int a_value; int b_value}, initialise each element to the values of each index of a and the value looked up from b. Sort that, traverse the sorted C copying the a_values back into A.
Viola. No, that's a large violin. Voila!
Use your rule as the comparison function to qsort (as long as B is longer than A):
#include <stdio.h>
#include <stdlib.h>
int A[] = {0, 1, 4, 5, 7};
int B[]= {5, 3, 8, 2, 2, 7, 1, 6, 3, 9};
int my_cmp(const void *a_, const void *b_,void *arg_)
{
const int *a = a_, *b = b_;
if(B[*a] == B[*b])
return 0;
else if (B[*a] < B[*b])
return -1;
else
return 1;
}
int main(int argc,char *arga[])
{
int i;
qsort(A,sizeof A/sizeof A[0] ,sizeof A[0],my_cmp);
puts("Sorted A");
for(i = 0 ; i < sizeof A/sizeof A[0]; i++) {
printf("A[%d] : %d B[A[%d]] : %d\n",i,A[i],i,B[A[i]]);
}
return 0;
}
This gives:
$ ./a.out
Sorted A
A[0] : 4 B[A[0]] : 2
A[1] : 1 B[A[1]] : 3
A[2] : 0 B[A[2]] : 5
A[3] : 7 B[A[3]] : 6
A[4] : 5 B[A[4]] : 7
Available on many platforms is also qsort_r(on linux you'll have to #define _GNU_SOURCE before including <stdlib.h> to use it. Using that, you'd change the comparison function to e.g.
int my_cmp(const void *a_, const void *b_,void *arg_)
{
const int *a = a_, *b = b_, *arg = arg_;
if(arg[*a] == arg[*b])
return 0;
else if (arg[*a] < arg[*b])
return -1;
else
return 1;
}
And call qsort_r like
qsort_r(A,sizeof A/sizeof A[0] ,sizeof A[0],my_cmp,B);

Resources