I am wondering if it is possible to get part of an array in c, with list slicing. In python it van be done in de next code. I like to do this in c.
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = a[3:5]
print(b)
Output: [4, 5]
You can use a struct as an array wrapper in the slice function. This way you can return the extracted slice from the function without bothering with malloc and free for dynamic memory allocation. Here's a basic outline.
#define MAX 100
typedef struct{
int myarr[MAX];
int mysize;
} wrapper;
wrapper slice(const int* arr, int size, int include, int exclude) {
wrapper result = { .myarr = {0}, .mysize = 0 };
if (include >= 0 && exclude <= size) {
int count = 0;
for (int i = include; i < exclude; i++) {
result.myarr[count] = arr[i];
count++;
}
result.mysize = exclude - include;
return result;
}
else {
printf("Array index out-of-bounds\n");
result.mysize = -1;
return result;
}
}
This can then be called on any array as follows:
int source[10] = {0,1,2,3,4,5,6,7,8,9};
wrapper s = slice(source, 10, 5, 10);
It will take quite a bit more work to implement the full Python slice functionality, though (here there's no third term to set the step size, nor are the various negative values implemented).
Well, you could start with something like the following:
// Get half-open range of values from array (includes first index,
// excludes last). Parameter 'source' is the source array, 'from'
// and 'to' are the range ends, and `target` is the destination
// buffer. If you provide buffer, make sure it's big enough. If
// you pass in NULL, a buffer will be allocated for you.
// Will return buffer address or NULL if either range is invalid
// or memory could not be allocated.
int *sliceIntArray(int *source, int from, int to, int *target) {
// Invalid, return null.
if (to <= from) {
return NULL;
}
// Only allocate if target buffer not given by caller.
if (target == NULL) {
target = malloc((to - from) * sizeof(int));
if (target == NULL) {
return NULL;
}
}
// Copy the data and return it.
memcpy(target, &(source[from]), (to - from) * sizeof(int));
return target;
}
This lets you pass in a buffer if you already have it, or it will allocate one for you if you don't (which you will need to free() at some point):
int naturals[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int slice1[2];
sliceIntArray(naturals, 3, 5, slice1);
// Use slice1 for whatever nefarious purpose you have :-)
int *slice2 = sliceIntArray(naturals, 3, 5, NULL);
// Use slice2 similarly, just make sure you free it when done.
free(slice2);
No, you can't.
You can create a new array and copy it, though:
int src[10] = { ... };
int dest[3];
memcpy(dest, src + 3, sizeof(src[0]) * 2);
In a short simple function:
int* slice(int a[], size_t start, size_t end)
{
return memcpy(malloc(sizeof(int)*(end-start)), a+start, sizeof(int)*(end-start));
}
Example usage:
#include <stdio.h>
int main(void) {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *b = slice(a,3,5);
for(int i=0; i<2; ++i)
{
printf("b[%d] = %d\n", i, b[i]);
}
return 0;
}
Output:
b[0] = 4
b[1] = 5
Related
I have a structure.
typedef struct Heap {
int length;
int size;
int A[];
} Heap;
I am trying to make a shallow copy of a given array and store it in this struct. Such that when the array is altered or elements are swapped this is mirrored in the original array.
Heap * build_max_heap(int A[], int length) {
Heap * heap = malloc(sizeof(Heap) + length*sizeof(int *));
*heap = (Heap) { length, length };
memcpy(heap->A, A, length*sizeof(int *));
/*
for(int i = floor(((heap->length)-1)/2); i >= 0; --i) {
max_heapify(heap, i);
}
*/
return heap;
}
int main() {
int A[] = {0, 3, 7, 61, 3, 40, 4, -1, 8, 10};
Heap * heap = build_max_heap(A, 10);
A[0] = 100;
for(int i = 0; i < 10; ++i) {
printf("%i, ", A[i]);
}
printf("\n");
for(int i = 0; i < 10; ++i) {
printf("%i, ", heap->A[i]);
}
return 0;
}
Currently the following is returned.
100, 3, 7, 61, 3, 40, 4, -1, 8, 10,
0, 3, 7, 61, 3, 40, 4, -1, 8, 10,
My expected result would be
100, 3, 7, 61, 3, 40, 4, -1, 8, 10,
100, 3, 7, 61, 3, 40, 4, -1, 8, 10,
Similarly heap->A[0] = 100; should have the same effect. I am also not sure whether length*sizeof(int *) is correct or should instead be length*sizeof(int) however I imagine this will be resolved by answering the former.
Code
Shallow copy amounts to copying the references instead of the values. However, this requires defining the struct a bit differently:
typedef struct Heap {
int length;
int size;
int *A;
} Heap;
This way, the values of the array A are not contained immediately after the struct, and we have the freedom to assign any pointer to it. Then, we simply init the heap as:
Heap * build_max_heap(int A[], int length) {
Heap * heap = malloc(sizeof(Heap));
*heap = (Heap) { length, length, A };
/* ... heapify code etc ... */
return heap;
}
But you must use this with caution - this implies that if you create two heaps out of A, they will influence each other. It is still best practice to create a copy.
Your idea was good- the realization not.
typedef struct Heap {
size_t length;
size_t size;
int A[];
} Heap;
Heap *build_max_heap(int *A, size_t length) {
Heap * heap = malloc(sizeof(*heap) + length*sizeof(*A));
*heap = (Heap) { length, length };
memcpy(heap-> A, A, length*sizeof(*A));
/* another stuff */
return heap;
}
This kind of structs with data ad the end of the struct is in a very common use. I allows only one allocatiion (and one free) instead of two. It is also more efficient as it does not require reading the pointer A and then dereferencing it.
I created a function which should return an array of indexes of some specific number.
The function attributes are: size of array , array, number and a pointer.
In the example below I get different values. There are two places where I check the values:
1) After the Insertion: Which looks correct
2) during Iteration over the returned array: Which returns different values, including addresses(why?)
These are the returned values:
During insertion:
3
11
17
20
21
23
6
Pointed array size : 6
During iteration:
3
11
17
21
2334102057621532978
3617293411120723765
int main()
{
size_t sizeToBeReturned;
int arrayOfInt[] = {12, 15, 2, 8, 13, 3, 14, 1, 13, 6, 0, 8, 14, 15, 14, 14, 2, 8, 0, 15, 8, 8, 9, 8, 0, 14};
size_t size = sizeof(arrayOfInt) / sizeof(int);
size_t *returnedArray = find_all(size, arrayOfInt, 8, &sizeToBeReturned);
for (int i = 0; i < sizeToBeReturned; i++) {
printf("%ld\n", returnedArray[i]);
//when I iterate the returned array, the values comes massed up
}
return 0;
}
size_t *find_all(size_t a, const int array[a], int number, size_t * z)
{
//printf("Array size: %zu\n", a);
size_t *toReturnArray = NULL;
size_t sizeOfArray = 0;
for (size_t i = 0; i < a; i++) {
if (array[i] == number) {
if (toReturnArray == NULL) {
toReturnArray = (size_t *) malloc(sizeof(int));
} else {
toReturnArray = realloc(toReturnArray, (sizeOfArray) * sizeof(int));
}
toReturnArray[sizeOfArray] = i;
printf("%ld\n", toReturnArray[sizeOfArray]);
//Here I can see the correct value
sizeOfArray++;
}
}
printf("%ld\n", sizeOfArray);
*z = sizeOfArray;
return toReturnArray;
}
You allocate as a dynamic array of int but you consider it
as a dynamic array of size_t (larger) while reading/writing.
toReturnArray = (size_t *) malloc(sizeof(size_t)); // not sizeof(int)
toReturnArray = realloc(toReturnArray, (sizeOfArray+1) * sizeof(size_t)); // not sizeof(int)
If on your system, for example, sizeof(int) is 4 and sizeof(size_t)
is 8, then the allocated memory is half the necessary size.
And something else I didn't see (thanks M Oehm) is the missing +1 in realloc().
By the way, realloc() accepts a null pointer (then behaves like
malloc()) so the test is not necessary: just use the line with realloc().
I'm trying to assign an array to one of the fields of a typedef struct and I can't find a way to do it practically.
I've searched for this problem but all I seem to find is answers for char * arrays which is not what I'm looking for, I'm just trying to assign an array to an int array, and looking for a practical way for the code below to work without having to initialize all the variables in the struct (they will be initialized later, but I just want to set the array variable):
typedef struct {
int array[5];
int number;
} Rot;
Rot RA;
void config()
{
RA.array = {1, 2, 3, 4, 5}; //This returns an "expected expression before "{"" error
int arr[5];
int i;
for (i = 0; i < 5; i++)
{
arr[i] = i + 1;
}
RA.array = arr; //I understand why this fails, but I need to do this in a practical way
}
Please assume that config is called later and the struct and RA are all accessible to it.
RA.array = {1, 2, 3, 4, 5};
memcpy(RA.array, (int[]){1, 2, 3, 4, 5}, sizeof RA.array);
RA.array = arr;
memcpy(RA.array, arr, sizeof arr); // better: sizeof RA.array
You can use memcpy as shown in another answer. Or alternatively, copy the whole struct and not just the array, using a temporary variable in the form of a compound literal:
RA = (Rot) { {1, 2, 3, 4, 5}, 0 };
This is possible because while C doesn't allow run-time assignment of arrays, it does allow it of structs.
You can use memcpy as shown in another answer, or copy the whole struct as shown in another answer (although your question states that you just want to set the array, not the remainder of the struct).
Another option is to embed just the array into another struct:
typedef struct {
int elem[5];
} RotArr;
typedef struct {
RotArr arr;
int number;
} Rot;
Then you can access element i of the array in Rot RA as RA.arr.elem[i]. Also, you can assign values to a whole RotArr object. The remainder of your code could look something like this:
Rot RA;
void config(void)
{
RA.arr = (RotArr){{1, 2, 3, 4, 5}};
RotArr arr;
int i;
for (i = 0; i < 5; i++)
{
arr.elem[i] = i + 1;
}
RA.arr = arr;
}
Note that (RotArr){{1, 2, 3, 4, 5}} is a compound literal value of RotArr type. It could also be written as (RotArr){ .elem = {1, 2, 3, 4, 5} } or (RotArr){ .elem = { [0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5 } } to be absolutely clear which parts of the compound literal are being set explicitly (any remaining parts will be set to 0), but since it only has a single member, these forms of the compound literal value are a bit over-the-top.
The following works according to C syntax. Not sure this is what you wanted.
#include <string.h>
#include <stdio.h>
typedef struct {
int array[5];
int number;
} Rot;
Rot RA = {{1,2,3,4,5}};
void main()
{
RA = (Rot) {{5, 6, 7, 8, 9}};
int arr[5];
int i;
for (i = 0; i < 5; i++)
{
arr[i] = i + 1;
}
memmove(RA.array, arr, sizeof(RA.array));
// OR
int l = sizeof(arr)/sizeof(arr[0]);
for(int i =0 ; i < l ; ++i) {
*(RA.array + i) = *(arr + i);
printf("%d\n",RA.array[i]);
}
}
Moreover, use memmove since that allows memory overlap.
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);
}
}
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);