Adding new item to an array of structs in C - c

I have some structs as following:
typedef struct {
char debutAge[15];
char finAge[15];
} Age;
typedef struct {
char type[15];
char composants[50];
Age utilisation;
} Categorie;
typedef struct {
int code;
char nom[30];
float prix;
Categorie med;
int quantitie;
} Medicament;
#define MAX 100
typedef Medicament Pharmacie[MAX];
Pharmacie P;
int nb=0;
In my main function, I'm trying to add a new element to the Pharmacie P array, this is what I tried:
void main()
{
Medicament m = Saisir();
ajouterMedicament(P, nb, m);
afficherMedicaments();
}
int ajouterMedicament(Pharmacie *ph, int *nb, Medicament m) {
int i;
for (i = 0; i < *nb; i++) {
if (m.code == ph[i].code) {
ph[i].prix = m.prix;
ph[i].quantitie = m.quantitie;
}
return 1;
}
if (*nb < MAX) {
ph[*nb] = m;
*nb += 1;
return 1;
}
return 0;
}
But I'm getting an error on this line: mif (m.code == ph[i].code) { :
expression must have struct or union type
How can I solve this ?

You don't need to declare the first argument as Pharmacie *. Pharmacie is a typedef for an array, so you don't need to add *.
int ajouterMedicament(Pharmacie ph, int *nb, Medicament m) {
And in the call, you need to pass a pointer to nb so it can be updated:
ajouterMedicament(P, &nb, m);
In general it gets confusing when you use typedef for pointer types, and you ran into that. I recommend not doing that. See Is it a good idea to typedef pointers?

Related

Changing a double pointer which is in a struct

I'm trying to change the x value in this code but I'm getting segmentation fault.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int **x;
} Type;
int main() {
int a = 1;
Type *type = malloc(sizeof(Type));
type->x[0] = &a;
return 0;
}
if you want an array of pointers to ints
int main() {
int a = 1;
Type *type = malloc(sizeof(Type));
type->x = malloc(sizeof(int*) * 10)) ;// say we need 10
type->x[0] = &a;
return 0;
}

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 do I call a function inside a struct?

I have this code:
int suma(int);
int produs(int);
struct calcul{
int suma();
int produs();
}
suma()=1+2+..n;// return S
produs()=1*2*..n;// return P
I want to call it in main with
calcul sp. How do I call function inside a struct?
If I give n a struct type n=5; the result to be sp(15,120).
Thanks!!!
I guess you want something like:
struct calcul
{
int suma(int n)
{
int result = 0;
for (int i = 1; i <= n; ++i)
result += n;
return result;
}
//... similar for produs
};
int main()
{
calcul sp;
int x = sp.suma(10);
};
int suma(int);
int produs(int);
and
struct calcul{
int suma();
int produs();
};
are two completely different sets of functions, even though they have the same name. The functions in your struct are member functions and can only be called on an instance of your struct. You would do it like so:
int main()
{
calcul x;
int a = x.suma(0);
int b = x.produs(1);
}

vector/arraylist in C

I am trying to implement a vector or arraylist in C. The code does not have a main, so I am compiling it with gcc -c file.c . I have two questions, the first being how to implement an insert function for the arraylist, and the second being why I receive the error that list-> is not a function.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
typedef struct ArrayList {
int *data;
int capacity;
int size;
ArrayList *list;
ArrayList ArrayList_init(int);
int insert(ArrayList *, int , int);
int set(ArrayList*, int, int);
int destroy(ArrayList *);
int print(ArrayList *);
int append(ArrayList *, int);
int valueOf( ArrayList *, int);
int size(ArrayList *);
int capacity(ArrayList *);
} ArrayList;
ArrayList * ArrayList_Init( int n )
{
ArrayList->data = malloc(sizeof(n) * ArrayList->capacity);
}
int append( ArrayList * list, int val )
{
if (list->size >= list->capacity)
return 1;
else
Arraylist->data[list->size++] = value;
return 0;
}
int print( ArrayList * list )
{
printf("%d\n", list->data);
return 0;
}
int set( ArrayList * list, int val, int index )
{
while(index >= list->size)
append(ArrayList, 0);
return 0;
if (index < 0 || index >= size)
return 1;
}
int destroy( ArrayList * list )
{
free(list->data);
return 0;
}
int insert(ArrayList * list, int val, int index)
{
return 0;
}
int valueOf( ArrayList * list, int element )
{
int x;
x = list->data[element];
return x;
}
int size(ArrayList * list)
{
return list->size;
}
int capacity(ArrayList * list)
{
return list->capacity;
}
int main(void)
{
int n = 3;
int i;
int stat; // Error code
int size;
int val = 0;
int capacity;
// allocate list
ArrayList *list = NULL;
list = ArrayList_Init(n);
printf("ArrayList initialized to %d elements\n", n);
printf("Size of List = %d\n", list->size(list));
printf("Capacity of List = %d\n", list->capacity(list));
// Fill initial values
list->set(list, val++, 0);
list->set(list, val++, 1);
list->set(list, val++, 2);
}
Thank you
First of all if you declare a function that returns something it must do so.
I think your ArrayList_Init should more look like this (I am assuming you want to store integers)
ArrayList * ArrayList_Init( int n )
{
ArrayList * list = malloc(ArrayList);
list->data = malloc(sizeof(int) * n);
list->capacity = n;
list->size=0;
return list;
}
In append as well as in Init you are trying to access a type.
Arraylist->data[list->size++] = value;
but it is supposed to be
list->data[list->size++] = value;
For your insert you can do something similiar to the following:
int insert( ArrayList * list, int val ,int position)
{
if (list->size >= list->capacity){
int * temp = malloc(sizeof(int) * list->capacity *2);
int i;
for(i=0;i<position-1;i++){
temp[i]=list->data[i];
}
for(i=postion-1;i<list->size;i++){
temp[i+1]=list->data[i];
}
free(list->data);
list->data=temp;
list->capacity *=2;
}else{
for(i=list->size;i>postion-1;i--){
list->data[i]=list->data[i-1];
}
}
list->data[position-1]=val;
list->size++;
return 1;
}
You probably want to do something similar in append because otherwise you just have a static array. The idea of a vector is that it grows and shrinks automatically.
Edit:
In C you cannot just declare a prototype of a function inside a struct and than access it.
The only way you can do something similar to what you want to do is by storing a pointer to each of the functions inside your struct. Have a look at the following post.
Define functions in structs

Need help using qsort with an array of structs

Now, I have seen various examples, but I don't get what they mean.
Here's my structure
typedef struct profile{
char gender[1];
double soc;
. . .
} PROFILE;
where soc is social security number that I'm going to be sorting by.
I know you need a compare function, but I don't know how to come up with the exact thing I need.
Here is an example of using qsort for an array of structs in C
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int price;
int id;
} order;
int compare(const void *a, const void *b) {
order *orderA = (order *)a;
order *orderB = (order *)b;
return (orderB->price - orderA->price);
}
int main() {
order list[6];
srand(time(NULL));
printf("Before sorting\n");
for (int i = 0; i < 6; i++) {
list[i].price = rand() % 10;
list[i].id = i;
printf("Order id = %d Price = %d\n", list[i].id, list[i].price);
}
qsort(list, 6, sizeof(order), compare);
printf("AFTER sorting\n");
for (int n = 0; n < 6; n++) {
printf("Order id = %d Price = %d\n", list[n].id, list[n].price);
}
return 0;
}
hope it helps
katerina dimitris
(all regards to pitsi)
Your Soc should almost certainly not be of type double, but anyway here's an example of what a compare function needs to return:
int compare(const void *p1, const void *p2)
{
const struct profile *elem1 = p1;
const struct profile *elem2 = p2;
if (elem1->soc < elem2->soc)
return -1;
else if (elem1->soc > elem2->soc)
return 1;
else
return 0;
}
Thanks for pointing out the const void *.
Here is a complete example (archived): Sorting Structures with the C qsort() Function
The strict version of a comparator takes two constant void pointers:
int compare(const void *v1, const void *v2)
{
const struct profile *p1 = v1;
const struct profile *p2 = v2;
if (p1->gender > p2->gender)
return(+1);
else if (p1->gender < p2->gender)
return(-1);
else if (p1->soc > p2->soc)
return(+1);
else if (p1->soc < p2->soc)
return(-1);
else
return(0);
}
This compares the gender field first, then the soc field. This is how you handle any multipart comparison.
To sort the array, use qsort() and pass a comparison function.
Here is one that produces the correct result for all possible values of the price member:
typedef struct profile {
char gender[1];
double soc;
int price;
...
} PROFILE;
int compare_price(const void *a, const void *b) {
const PROFILE *oa = a;
const PROFILE *ob = b;
return (oa->price > ob->price) - (oa->price < ob->price);
}
int compare_soc(const void *a, const void *b) {
const PROFILE *oa = a;
const PROFILE *ob = b;
return (oa->soc > ob->soc) - (oa->soc < ob->soc);
}
Notes:
the simple subtraction of values produces incorrect results if the difference does not fit in the int type. For example -2 and INT_MAX cannot be correctly compared with the subtraction method. It would not work for floating point values either.
the above method can be used for all comparable types, including double except for NaN.
If you wish to handle NaN, here is how to group them at the end:
#include <math.h>
int compare_soc_nan_at_the_end(const void *a, const void *b) {
const PROFILE *oa = a;
const PROFILE *ob = b;
if (isnan(oa->soc)) {
return isnan(ob->soc) ? 0 : 1;
} else
if (isnan(ob->soc)) {
return -1;
} else {
return (oa->soc > ob->soc) - (oa->soc < ob->soc);
}
}

Resources