writing to an array of structs - c

I have the following code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct Example
{
uint16_t a;
uint16_t b;
} ExampleStruct;
void derp(struct Example * bar[], uint8_t i)
{
uint8_t c;
for(c = 0; c < i; ++c)
{
bar[c]->a = 1;
bar[c]->b = 2;
}
}
int main()
{
struct Example * foo;
uint8_t i = 3;
foo = malloc(i*sizeof(ExampleStruct));
derp(&foo, i);
free(foo);
return 0;
}
I get segfaults and all debuggers tell me that code stopped working due to
bar[c]->a = 1;
I tried to rearrange this into all of the following
(*bar)[c]->a = 1;
(*bar[c])->a = 1;
bar[c].a = 1;
(*bar)[c].a = 1;
and with no success. What am I doing wrong? I don't understand why is this failing, and I don't understand why the addresses of bar[0], bar[1] and bar[2] are so far away from each other, when each just takes 2 bytes.

There's no need to pass &foo. Keep it simple:
// In a function declaration, it's (almost) always a pointer, not an array.
// "struct Example bar[]" means *exactly* the same thing in this context.
void init(struct Example * bar, int n) {
int i;
for (i = 0; i < n; ++i) {
bar[i].a = 1;
bar[i].b = 2;
}
}
int main() {
int n = 3;
struct Example * foo = malloc(n*sizeof(struct Example));
init(foo, n); // passes the address of the array - &a[0] - to init
printf("The second element is {%u, %u}\n", foo[1].a, foo[1].b);
free(foo);
return 0;
}
output:
The second element is {1, 2}

Some changes were required since you were trying to pass array of objects:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
typedef struct Example
{
uint16_t a;
uint16_t b;
} ExampleStruct;
void derp(struct Example * bar[], uint8_t i)
{
uint8_t c;
for(c = 0; c < i; ++c)
{
bar[c]->a = 1;
bar[c]->b = 2;
}
}
int main()
{
struct Example * foo[3];
uint8_t i = 3, c;
for(i = 0; i < 3; i++)
foo[i] = malloc(sizeof(ExampleStruct));
derp(foo, i);
for(c = 0; c < i; ++c)
{
printf("\n%" PRIu16 " %" PRIu16 ,foo[c]->a,foo[c]->b);
}
for(i = 0; i < 3; i++)
free(foo[i]);
return 0;
}
struct Example * foo; can hold a single pointer to an object of type struct Example. While struct Example * bar[] can hold an array of pointers to objects of type struct Example.
In your original program, this will seg fault when c is greater than 0 since you did not allocate any pointers to an object of type struct Example.
bar[c]->a = 1;
bar[c]->b = 2;
For static objects:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
typedef struct Example
{
uint16_t a;
uint16_t b;
} ExampleStruct;
void derp(struct Example bar[], uint8_t i)
{
uint8_t c;
for(c = 0; c < i; ++c)
{
bar[c].a = 1;
bar[c].b = 2;
}
}
int main()
{
struct Example foo[3];
uint8_t i = 3, c;
derp(foo, i);
for(c = 0; c < i; ++c)
{
printf("\n%" PRIu16 " %" PRIu16 ,foo[c].a,foo[c].b); //accessing in main
}
return 0;
}

Related

using qsort function to sort a struct

so I need to use qsort() to sort an array that contains a structure
#include <stdio.h>
// =========
struct pair
{
int encounters;
};// pair{}
int compaireEncounters(const void*, const void*);
int main()
{
struct pair* working[5];
working[0]->encounters = 10;
working[1]->encounters = 3;
working[2]->encounters = 1;
qsort(working, 5, sizeof(struct pair), compareEncounters);
int i = 0;
while (i < 3)
{
printf("%d \n", working[i]->encounters)
i++;
}
}
int compaireEncounters(const void* av, const void* bv)
{
int a = ((struct pair*)av)->encounters;
int b = ((struct pair*)bc)->encounters;
return(a > b);
}
I am trying to get the output:
1
3
10
but instead i get a segmentation fault core dump.
What is the issue here?
You must assign pointers to valid buffers before dereferencing pointers.
In this case, working should be an array of the structure, not an array of pointers.
Also don't forget to initialize all elements to be sorted.
There are also more mistakes in your code:
qsort is used without including proper header (stdlib.h)
Undeclared compareEncounters is used in the main function.
A semicolon is missing after the printf() statement.
Undeclared bc is used in the compaireEncounters function.
Fixed code:
#include <stdio.h>
#include <stdlib.h>
// =========
struct pair{
int encounters;
};// pair{}
int compaireEncounters(const void* , const void*);
int main() {
struct pair working[5];
working[0].encounters = 10;
working[1].encounters = 3;
working[2].encounters = 1;
working[3].encounters = 334;
working[4].encounters = 42;
qsort(working, 5, sizeof(struct pair), compaireEncounters);
int i = 0;
while (i < 3) {
printf("%d \n", working[i].encounters);
i++;
}
}
int compaireEncounters(const void* av, const void* bv){
int a = ((struct pair*)av)->encounters;
int b = ((struct pair*)bv)->encounters;
return(a > b);
}
If you want to work with an array of pointers,
Allocate buffers and assign them before dereferencing.
Fix the element size for qsort().
Fix compaireEncounters to compare the pointers to the structure.
#include <stdio.h>
#include <stdlib.h>
// =========
struct pair{
int encounters;
};// pair{}
int compaireEncounters(const void* , const void*);
int main() {
struct pair* working[5];
working[0] = malloc(sizeof(*working[0])); working[0]->encounters = 10;
working[1] = malloc(sizeof(*working[1])); working[1]->encounters = 3;
working[2] = malloc(sizeof(*working[2])); working[2]->encounters = 1;
working[3] = malloc(sizeof(*working[3])); working[3]->encounters = 334;
working[4] = malloc(sizeof(*working[4])); working[4]->encounters = 42;
qsort(working, 5, sizeof(*working), compaireEncounters);
int i = 0;
while (i < 3) {
printf("%d \n", working[i]->encounters);
i++;
}
}
int compaireEncounters(const void* av, const void* bv){
int a = (*(struct pair**)av)->encounters;
int b = (*(struct pair**)bv)->encounters;
return(a > b);
}

How to create, modify, and return array of pointers in a function in C?

Here's a very basic example of what I'm trying to do (note that this segmentation faults)
#include <stdio.h>
#include <stdlib.h>
typedef struct foo {
int *bar;
} Foo;
Foo **fooPointers() {
Foo **test = (Foo**) malloc(sizeof(struct foo) * 3);
for(int i = 0; i < 3; i++) {
Foo *curr = *(test + i);
int *num = &i;
curr->bar = num;
}
return test;
}
int main() {
fooPointers();
return 0;
}
the goal is to create an array of pointers of Foo, give each element meaningful values, and then return the pointer array.
Is anyone able to point me in the right direction as to why this doesn't work and how I can accomplish this task?
#include <stdio.h>
#include <stdlib.h>
typedef struct foo
{
int *bar;
} Foo;
Foo **fooPointers()
{
Foo **test = malloc(sizeof(Foo*) * 3); // should be `sizeof(Foo*)`
static int k[] = {0,1,2}; // new array
for(int j=0;j<3;j++)
{
test[j] = malloc(3*sizeof(Foo)); // No need to cast output of malloc
}
for (int i = 0; i < 3; i++)
{
Foo *curr = *(test + i);
//int *num = &i;
curr->bar = &k[i]; // storing different addresses.
}
return test;
}
int main()
{
Foo **kk;
kk = fooPointers();
for(int i=0;i<3;i++)
{
printf("%d\n", *(kk[i]->bar)); //printng the values.
}
return 0;
}
The output is :
0
1
2

c sorting large struct array and printing to screen

I'm having trouble sorting a struct array and then printing it to screen. When I run the code in Visual Studio 2012, it doesn't print AT ALL. I've spent hours figuring it out, and debugging mode is very buggy. I really need to know why it isn't doing what I tell it to do.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct RandStruct
{
int year;
char string[31];
int frequency;
};
struct RandStruct randArray[150000];
int main(void)
{
int i, j;
for (i = 0; i < 150000; i++)
{
randArray[i].year = 150000 - i;
strcpy(randArray[i].string, "test");
randArray[i].frequency = i;
}
for (i = 1; i < 150000; i++)
{
for (j = 0; j < 150000 - i; j++)
{
if (randArray[j].year > randArray[j+1].year)
{
struct RandStruct temp = randArray[j];
randArray[j] = randArray[j+1];
randArray[j+1] = temp;
}
}
}
for (i = 0; i < 150000; i++)
{
printf("%d,%s,%d\n", randArray[i].year, randArray[i].string, randArray[i].frequency);
}
return 0;
}
For sorting, you should use the qsort function instead of reinventing the wheel.
#include <stdlib.h>
int my_compar(const void *a, const void *b) {
const struct RandStruct *aa = a;
const struct RandStruct *bb = b;
if(aa->year < bb->year) return -1;
if(aa->year == bb->year) return 0;
return 1;
}
int main(void) {
... other stuff ...
size_t size = sizeof(struct RandStruct);
qsort(randArray, sizeof(randArray)/size, size, my_compar);
}

Copying struct problems [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Assume: struct foo_t { int X,Y,Z; }. Some function take an array of struct foo_t and set some values to it; something like this:
void foo(struct foo_t *f, size_t limit, size_t *result_length)
{
int i = 0;
struct foo_t a;
a.X = 5;
//...
struct foo_t b;
b.X = 10;
// ...
struct foo_t c;
c.X = 4;
//...
f[i++] = a;
f[i++] = b;
f[i++] = c;
*result_length = i;
}
and then:
struct foo_t buf[12];
struct foo_t positive[12];
struct foo_t negative[12];
size_t len;
foo(buf, sizeof(buf)/sizeof(buf[0]), &len);
int c,positive_len,negative_len;
for(c = positive_len = negative_len = 0; c < len; c++)
{
if(buf[c].X < 8)
positive[positive_len++] = buf[c];
else
negative[negative_len++] = buf[c];
}
And finally:
puts("POSITIVE:");
int i;
for(i = 0; i < positive_len; i++)
printf("%d\n", positive[i].X);
puts("NEGATIVE:");
for(i = 0; i < negative_len; i++)
printf("%d\n", nagative[i].X);
The problem is the following: instead of getting "POSITIVE:\n4\n5", "NEGATIVE:10" I'm getting 5 and 5 and 10 isn't printed. In other words, only the last value set. Why is this happening? I've reduced significantly my code to try to get some help here because the real function is around 300 lines of code that includes database management, etc; If really needed I will post here. Before to use = operator, I'd used memcpy() to do copy of struct to my positive/negative arrays.
You have a typo in your code:
struct foo_t c;
b.X = 4; // this should be c.X = 4;
//...
You have two typos/bugs in the example above:
You are not setting c
struct foo_t c;
b.X = 4;
The variable in this printf is misspelled
for(i = 0; i < negative_len; i++)
printf("%d\n", nagative[i].X);
There were a couple errors. Some were spelling and "c" is never assigned to in your "foo" function.
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
typedef struct foo_t
{
int X, Y, Z;
}foo_t;
void foo(struct foo_t *f, size_t limit, size_t *result_length)
{
int i = 0;
struct foo_t a, b, c;
a.X = 5;
//...
b.X = 10;
// ...
c.X = 4; // CHANGE HERE FROM "B" to "C".
//...
f[i++] = a;
f[i++] = b;
f[i++] = c;
*result_length = i;
}
int main(int argc, char** argv)
{
// CORRECTED ALL SPELLING ERRORS!!! (POSITIVE / NEGATIVE)
struct foo_t buf[12];
struct foo_t positive[12];
struct foo_t negative[12];
size_t len;
int c, positive_len, negative_len;
foo(buf, sizeof(buf)/sizeof(buf[0]), &len);
for(c = positive_len = negative_len = 0; c < len; c++)
{
if(buf[c].X < 8)
positive[positive_len++] = buf[c];
else
negative[negative_len++] = buf[c];
}
{ // <-- IGNORE THIS BADNESS
int i;
puts("POSITIVE:");
for(i = 0; i < positive_len; i++)
printf("%d\n", positive[i].X);
puts("NEGATIVE:");
for(i = 0; i < negative_len; i++)
printf("%d\n", negative[i].X);
}
getchar();
}
This is an SSCCE (Short, Self-Contained, Complete Example) generated from your code:
#include <stdio.h>
struct foo_t { int X; };
static void foo(struct foo_t *f, size_t limit, size_t *result_length)
{
size_t i = 0;
struct foo_t a;
a.X = 5;
struct foo_t b;
b.X = 10;
struct foo_t c;
c.X = 4;
if (i < limit)
f[i++] = a;
if (i < limit)
f[i++] = b;
if (i < limit)
f[i++] = c;
*result_length = i;
}
int main(void)
{
struct foo_t buf[12];
struct foo_t positive[12];
struct foo_t negative[12];
size_t len;
foo(buf, sizeof(buf)/sizeof(buf[0]), &len);
size_t c,positive_len,negative_len;
for (c = positive_len = negative_len = 0; c < len; c++)
{
if (buf[c].X < 8)
positive[positive_len++] = buf[c];
else
negative[negative_len++] = buf[c];
}
puts("POSITIVE:");
for (size_t i = 0; i < positive_len; i++)
printf("%d\n", positive[i].X);
puts("NEGATIVE:");
for (size_t i = 0; i < negative_len; i++)
printf("%d\n", negative[i].X);
}
It produces:
POSITIVE:
5
4
NEGATIVE:
10
I had to fix nagative to negative and postive to positive. I initialized c.X. I used limit to ensure no overflow (and fix the warning). I changed the various int counter variables to size_t to avoid warnings about signed vs unsigned comparisons. I eliminated the Y and Z members from the structure since they aren't used in this minimal example.

Dynamic array in struct calloc or pointers failing, C

I'm attempting to complete an assignment on sparse matrices in C. I have a sparse matrix held as a list of values and coordinates and am converting it to Yale format.
I have run into a strange memory allocation issue that no one seems to have seen before. My code is:
yale* convertMatrix(matrix_list* input){
int matrix_elements = input->elements;
int matrix_rows = input->m;
yale* yale = (struct y*)calloc(1, sizeof(yale));
int* A = (int*)calloc(matrix_elements, sizeof(int));
int* IA = (int*)calloc(matrix_rows + 1, sizeof(int));
int* JA = (int*)calloc(matrix_elements, sizeof(int));
printf("%d elements\n",matrix_elements);
yale->A = A; // Value
yale->IA = IA; // Row (X)
yale->JA = JA; // Column (Y)
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
list* tmp_list = input->first;
for(int i = 0, j = 0, tmp_y = 0; i < matrix_elements && tmp_list!=NULL; i++){
printf("Input Value: %d \n",tmp_list->point.value);
A[i] = tmp_list->point.value;
// Initialise the first row
if(i == 0) IA[0] = tmp_list->point.x;
else{
// Add a new row index
if(tmp_y != tmp_list->point.x){
j++;
IA[j] = i;
tmp_y = tmp_list->point.x;
}
}
JA[i] = tmp_list->point.y;
tmp_list = tmp_list->next;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%d,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->JA[i]);
return yale;
}
And here is the struct for yale:
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
But the program segfaults at the first relevant printf on the first iteration of the loop.
printf("%d,",yale->A[i]);
I'm positive:
matrix_elements is an integer (9 in my test case)
matrix_rows is an integer
A / IA / JA are all filled with correct values (if you swap yale->A for A in the printf, it works fine).
Directly callocing the array to the struct pointers doesn't affect the result.
Mallocing, callocing, not typecasting, all no effect.
Thanks to Xcode and gdb I can also see that at the point of the segfault. The structure pointers do NOT seem to point to the arrays
I suggest you run your code under Valgrind. This should report the buffer overflow error. (A buffer overflow is where you write past the end of an array).
I also recommend you write some unit tests for your code. They can be very helpful detecting bugs. In particular, I suggest you write a test with a 3x3 input matrix with a value in every position. Check that the values you get out are what you expect.
To get it compiled, I need to prepend this to the snippet:
#include <stdlib.h>
#include <stdio.h>
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
typedef struct list {
struct list *next;
struct point { int x,y,value; } point;
} list;
typedef struct matrix_list {
int elements;
int m;
int n;
struct list *first;
int *point;
} matrix_list;
UPDATE: I transformed the program into something more readable (IMHO). I don't have the faintest idea what the IA and JA are supposed to do, but the below fragment should be equivalent to the OP.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
struct y {
unsigned int n;
unsigned int m;
unsigned int elements;
unsigned int *IA;
unsigned int *JA;
int *A;
} ;
struct list {
struct list *next;
struct point { unsigned int x,y; int value; } point;
} ;
struct matrix_list {
unsigned int elements;
unsigned int m;
unsigned int n;
struct list *first;
} ;
struct y *convertMatrix(struct matrix_list* input)
{
unsigned int matrix_elements = input->elements;
unsigned int matrix_rows = input->m;
unsigned int ii,jj,tmp_y;
struct y *yale ;
struct list *tmp_list ;
yale = calloc(1, sizeof *yale);
assert (yale != NULL);
printf("%u elements\n",matrix_elements);
yale->A = calloc(matrix_elements, sizeof *yale->A);
assert (yale->A != NULL);
yale->IA = calloc(matrix_rows + 1, sizeof *yale->IA);
assert (yale->IA != NULL);
yale->JA = calloc(matrix_elements, sizeof *yale->JA);
assert (yale->JA != NULL);
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
// Initialise the first row, set start condition
// FIXME: this ignores the empty list or size=0 cases
yale->IA[0] = tmp_y = input->first->point.x;
ii = jj = 0;
for(tmp_list = input->first ;tmp_list; tmp_list = tmp_list->next) {
printf("Input Value: %d \n",tmp_list->point.value);
yale->A[ii] = tmp_list->point.value;
// Add a new row index
if(tmp_y != tmp_list->point.x){
jj++;
yale->IA[jj] = ii;
tmp_y = tmp_list->point.x;
}
yale->JA[ii] = tmp_list->point.y;
if (++ii >= matrix_elements ) break;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%u,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%u,",yale->JA[i]);
return yale;
}
Note: I moved the (ii == 0) {} condition out of the loop, and replaced the one-letter indices by there two-letter equivalents. Also: all the indices are unsigned (as they should be)

Resources