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.
Related
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
I want to decrement an array from last element in C. I first wrote the following code to increment an array from the first element:
#include<stdio.h>
int x[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *pointer, count;
int main (void) {
pointer = x;
for (count = 0; count < 11; count++)
printf("%d\n", *pointer++);
return 0;
}
This works fine. But then I tried to decrement the elements by modifying the code to this:
#include<stdio.h>
int x[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *pointer, count;
int main (void) {
pointer = x[10];
for (count = 0; count < 11; count++)
printf("%d\n", *pointer--);
return 0;
}
But of course I am doing something wrong. I'd appreciate it very much if you could help me to understand my mistake.
You have two options which are equivalent.
pointer = &x[10];
pointer = x + 10;
Either will achieve the effect of making the pointer point at the 10th element of x.
pointer = x[10]; should be pointer = &x[10];.
You're setting pointer to the integer value x[10]. What you want to do is set pointer to the address of the last element in x.
If I have a an array of ints, how could I directly edit each int?
int i = arr + 1; // Getting the integer in pos 1
i is just a copy, correct? If I set i = 4, then arr + 1 would still be 1.
Would this work?
int *i = &(arr + 1);
*i = 4;
You should use the array operators:
int i = arr[1];
arr[1] = 4;
Change your code to this:
int *i = arr + 1;
*i = 4;
and it will work. Arrays in C are just pointers to first element in the array.
So this arr + 0 will give address of first element in array and this arr + 1 is an address of second element.
You've got:
int arr[4] = {0, 1, 2, 3};
Want to edit it further?
arr[0] = 42;
// arr[] = {42, 1, 2, 3};
Want to change all of them at once? There's:
for(int i = 0; i < 4; ++i)
arr[i] = i * 2;
// arr[] = {0, 2, 4, 6};
And don't forget memset()!
memset(arr, 42, 4);
// arr[] = {42, 42, 42, 42};
Want to change everything but the first element to 7?
memset(&arr[1], 7, 4 - 1);
// arr[] = {42, 7, 7, 7};
Would you like to know somethin' about pointers? (Here's a more useful link.)
See this? (If you can't, please stop reading this. Thanks!)
int *ptr = &arr[1];
It's equivalent to:
int *ptr = arr + 1;
Which is also equivalent to:
int *ptr = arr;
ptr = ptr + 1;
OK, now that we've got that down, let's show you a more efficient for-loop than the one I did above:
int *ptr = arr;
for(int i = 0; i < 4; ++i)
{
*ptr = i << 2;
// i * 2 == i << 2
++ptr;
}
// arr[] = {0, 2, 4, 6};
Not that you should code like that; the compiler will handle it for you, most likely.
Would you like another answer in the form of a series of questions?
Array indexing operators can do what you need.
arr[3] = 101; //assignment to array
int x = arr[37]; //get value from array
etc.
No need for for that memory arithmetic here..
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);
I want to have an variable-length array contained within a structure, but am having trouble initializing it correctly.
struct Grid {
int rows;
int cols;
int grid[];
}
int main() {
struct Grid testgrid = {1, 3, {4, 5, 6}};
}
Everything I try gives me an 'error: non-static initialization of a flexible array member' error.
Here is my version:
#include <stdio.h>
struct matrix {
int rows;
int cols;
int **val;
} a = { .rows=3, .cols=1,
.val = (int*[3]){ (int[1]){1},
(int[1]){2},
(int[1]){3} } },
b = { .rows=3, .cols=4,
.val = (int*[3]){ (int[4]){1, 2, 3, 4},
(int[4]){5, 6, 7, 8},
(int[4]){9,10,11,12} } };
void print_matrix( char *name, struct matrix *m ){
for( int row=0;row<m->rows;row++ )
for( int col=0;col<m->cols;col++ )
printf( "%s[%i][%i]: %i\n", name, row, col, m->val[row][col] );
puts("");
}
int main(){
print_matrix( "a", &a );
print_matrix( "b", &b );
}
You can make that work in gcc by making the struct either static or global, but it turns out that initializing flexible array members is non-conforming and so it is likely to not work except with gcc. Here is a way to do it that just uses C99-conforming features...
#include <stdlib.h>
#include <stdarg.h>
typedef struct Grid {
int rows;
int cols;
int grid[];
} *Grid;
Grid newGrid(int, int, ...);
Grid newGrid(int rows, int cols, ...)
{
Grid g;
va_list ap;
int i, n = rows * cols;
if((g = malloc(sizeof(struct Grid) + rows * cols * sizeof(int))) == NULL)
return NULL;
g->rows = rows;
g->cols = cols;
va_start(ap, cols);
for(i = 0; i < n; ++i)
g->grid[i] = va_arg(ap, int);
va_end(ap);
return g;
}
.
.
.
Grid g1, g2, g3;
g1 = newGrid(1, 1, 123);
g2 = newGrid(2, 3, 1, 1, 1,
2, 2, 2);
g3 = newGrid(4, 5, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20);
You don't have a variable length array (VLA) in your structure. What you have in your structure is called a flexible array member. Flexible array member has absolutely nothing to do with VLA. Flexible array members in C exist to legalize and support the good-old "struct hack" idiom, which is based on dynamic allocation of memory for struct objects with trailing arrays of different size.
Flexible array members cannot be initialized with aggregate initializers, which is what you seem to attempt in your code. What you are trying to do here is simply impossible. There's no such feature in C.
Meanwhile, the text of the error message generated by your compiler seems to suggest that it supports something like this as an extension. This might be true, but keep in mind that this is in no way a standard C feature.
I do not believe that this is possible or supported. As DigitalRoss points out, you can initialize from a literal in the case of static arrays... though I'm still not sure if this is included in the Standard or just a common extension. I can't seem to find a clause in the Standard that supports literal initialization of flexible arrays though I can see that gcc explicitly supports it.
A version using malloc:
#include <stdio.h>
#include <stdlib.h>
typedef struct Grid {
int rows;
int cols;
int *grid;
} Grid;
/* Should validate params */
Grid
buildGrid(int rows, int cols, int vec[]) {
Grid grid;
grid.rows = rows;
grid.cols = cols;
int i;
if ( (grid.grid = malloc(sizeof(vec))) == NULL ) {
/* do something.*/
}
for(i = 0; i < sizeof(vec) ; i++ ) {
grid.grid[i] = vec[i];
}
return grid;
}