Passing structure elements as function argument - c

So I have a struct that I want to sort by each element, ascending and descending.
I'm creating 14 different sort function because I don't know how to pass struct element as a function argument.
I want to cut it to 2 sort function ascending & descending, so I don't have 14 functions.
How do I deal with this?? Thanks in advance!
struct propertySales{
unsigned int tanggal[3];
char pelanggan[30];
char jenisProperty[30];
char namaProperty[30];
int jumlahProperty;
double hargaProperty;
double totalPembayaran;
}Arr[100], compare[100], temp;
void sort_totalPembayaran_descending(){
int currentIndex=index_counter();
for(int i=0; i<(currentIndex-1); i++){
for (int j=0; j<(currentIndex-i-1); j++){
if (compare[j].totalPembayaran < compare[j+1].totalPembayaran){
swap(&compare[j], &compare[j+1]);
}
}
}
system("cls");
printf("Sorting berdasarkan total pembayaran (Descending)\n");
print_column();
print_data(compare);
}

If you wish to sort by the totalPembayaran field, then you want to create a comparison function which takes two void pointers to propertySales structs.
int compare_totalPembayaran_asc(const void *a, const void *b) {
struct propertySales *c = (struct propertySales *)a;
struct propertySales *d = (struct propertySales *)b;
if (c->totalPembayaran < d->totalPembayaran)
return -1;
else if (c->totalPembayaran > d->totalPembayaran)
return 1;
else
return 0;
}
Now you can provide this to qsort to sort your array in ascending order.
qsort(arr, 100, sizeof(propertySales), compare_totalPembayaran_asc);
Comparing in descending order just requires writing another comparison function and changing the values returned.
int compare_totalPembayaran_desc(const void *a, const void *b) {
struct propertySales *c = (struct propertySales *)a;
struct propertySales *d = (struct propertySales *)b;
if (c->totalPembayaran < d->totalPembayaran)
return ...;
else if (c->totalPembayaran > d->totalPembayaran)
return ...;
else
return 0;
}

Related

Insert in Binary search tree recursively using comparison function in C

I am using nested structures to create a BST but I have a problem while inserting because I use a comparison function to do so!
here is my comparison function
int compare_doubles(const void* a, const void* b)
{
const double* a_ = (const double*)a;
const double* b_ = (const double*)b;
return (*a_ > *b_) - (*a_ < *b_);
}
int compare_int(const void* a, const void* b)
{
const int* a_ = (const int*)a;
const int* b_ = (const int*)b;
return (*a_ > *b_) - (*a_ < *b_);
}
and here is the structures
typedef struct tree_t BinarySearchTree; //opaque structure declared on BinarySearchTree.h
struct tree_t{
int (*comparison)(const void *, const void *);
struct tree_t* lchild;
struct tree_t* rchild;
struct t_node* noeud;
};
struct t_node{
const void *key;
const void *data;
City *city;
};
and this is my function to create a new BST
BinarySearchTree* newBST(int comparison_fn_t(const void *, const void *))
{
BinarySearchTree *t = (struct tree_t *)malloc(sizeof(struct tree_t));
t->comparison = comparison_fn_t;
t->lchild = t->rchild = NULL;
t->noeud = NULL;
return t;
}
This is my insertion function
BinarySearchTree* insertInBST(BinarySearchTree* bst, const void* key, const void* value) {
BinarySearchTree *t = bst;
if (bst->noeud == NULL)
{
struct t_node* n = (struct t_node *)malloc(sizeof(struct t_node));
t->noeud = n;
t->noeud->data = value;
t->noeud->key = key;
return t;
}
if ((bst->comparison(&key,&(bst->noeud->key))) < 0){
bst->lchild = insertInBST(bst->lchild, key, value);
}
else if ((bst->comparison(&key,&(bst->noeud->key))) >= 0){ // handle duplicate keys
bst->rchild = insertInBST(bst->rchild, key, value);
}
return bst;
}
when I try to run my code using these tests I get segfault (core dumped)
this is my main function
int main()
{
int *t =15;
int *g = 13;
int *j =15;
int *k = 13;
BinarySearchTree *root = newBST(&compare_doubles);
insertInBST(root, k,j);
insertInBST(root, t, g);
}```
Your comparison function is overly complicated (*a_ > *b_) - (*a_ < *b_) as you mix comparison (<, >) and arithmetic (-) operations. #WhozCraig suggested (a < b) ? -1 : (b < a).
You need to define struct City.
You need to #include <stdlib.h> for malloc.
In main you are casting integers to pointers. The compiler warning for the first case is:
warning: initialization of ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
As in int t = 15; int g = 13 and later insertInBST(root, &t, &g)
In main you use the wrong compare function (doubles instead of int).
I ran your code through gdb and it crashes in if (bst->noeud == 0) because insertInBST(root, t, g) invokes bst->rchild = insertInBST(bst->rchild, key, value) but bst->rchild is NULL.
In insertInBST, you only need to do the comparison once to figure out if you need the left or right branch.

qsort a double pointer pointing to an array of struct pointers

Hi I am very new in learning C programming language and have trouble understanding this problem. I want to qsort a double pointer pointing to an array of struct[person] pointers. I need to sort the struct pointer according to multiple criteria. (age in ascending order, both name and height should be in descending order). I wonder if my syntax is correct in the following comparison function and qsort call.
struct person {
int age;
float height;
char name[20];
};
struct person **arr = malloc(sizeof(struct person)*10);
..... this part is just initialisation
qsort(arr, 10,sizeof(struct person*), compareFunction);
int compareFunction(const void *a, const void *b){
struct person* p1 = (struct person*) a;
struct person* p2 = (struct person*) b;
if(p1 - >age > p2-> age){
return 1;
} else if (p1 -> age < p2 <-age){
return -1;
}
if (strcmp(p1 - >name, p2 ->name)<0){
return 1;
} else if (strcmp(p1-> name , p2->name)>0){
return -1;
}
if (p1 -> height < p2 ->height){
return 1;
} else if (p1 - > height > p2 ->height){
return -1;
}
return 0;
}
-> used to access a structure member with structure pointer.
structure_pointer->structure_member
where as for structure variable we use '.' operator.
structure_variable.structure_member
your compareFunction can be modified to
int compareFunction(const void *a, const void *b){
if(a->age > b->age){
return 1;
} else if (a->age < b->age){
return -1;
}
if (strcmp(a->name, b->name)<0){
return 1;
} else if (strcmp(a->name, b->name)>0){
return -1;
}
if (a->height < b->height){
return 1;
} else if (a->height > b->height){
return -1;
}
return 0;
}

Sort Struct records

I have a structure that contains a field for student names. I'd like to order the names alphabetically. Here is the list of names that are stored into the name field of the structure:
Thui Bhu
Ariana B. Smith
Emily Gonzales
Jennifer L
Maria Jones
Bill Gates
Escobar Morris
Anne Latner
Here is the way I am defining the structure:
struct studentData {
char name[30];
int quiz1; int quiz2;
int quiz3; int quiz4;
int mid1; int mid2;
int finalexam;
} ;
Here is the code I have tried using to sort:
void SortNames(struct studentData *record, int reccount)
{
int j,i;
struct studentData temp;
for(i = 1; i < reccount; i++)
{
j = i - 1;
while( j >= 0 && strcmp( record[j+1].name, record[j].name) < 0 )
{
temp = record[j + 1]; /*errors*/
record[j+1] = record[j];
record[j] = temp; /*errors*/
j--;
}
printf("%s",record[j].name);
}
return;
}
This is the output that I am getting:
Ariana B. SmithEmily GonzalesJennifer LAriana B. SmithEmily Gonzales
Please help! I am open to using any built-in functions.
Call qsort().
#include <stdlib.h>
#include <string.h>
int cmp(const void *l, const void *r)
{
return strcmp(((struct studentData*)l)->name, ((struct studentData*)r)->name);
}
void SortNames(struct studentData *record, int reccount)
{
int i;
qsort(record, reccount, sizeof(struct studentData), cmp);
for (i = 0; i < reccount; ++i) {
printf("%s\n", record[i].name);
}
}
Unless you need to create your own sort routine, the best approach is probably using the qsort function to sort the structs by name. When using qsort your task is simply to create a comparator funciton that takes a void pointer to type struct studentData and creates a way to compare by the member of interest (here name)
The qsort comparison funciton returns type int. For your struct it would look something like:
/* qsort struct comparision function (struct studentData by name) */
int struct_cmp_by_name (const void *a, const void *b)
{
struct studentData *ia = (struct studentData *)a;
struct studentData *ib = (struct studentData *)b;
return strcmp (ia->name, ib->name);
}
(Note - you don't have qutie enough code posted to be exact, but it will be close to being) called in your code as:
qsort (record, number_structs, sizeof (struct studentData), struct_cmp_by_name);
This will sort records by the member name.

Sorting dynamic array in a structure with C qsort ()

I have a problem to sort an array (dynamically allocated) in a structure. Firstly, the idea was to order the array i in the structure in an ascendant order. Then I was thinking to order the array i maintaining instead the array j with the same "relationship" obtained when it was constructed the initial structure. I try to work for the first idea, but without any result with qsort.So this is my code... Any ideas? I think there is a problem in the construction of the comparing function..
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int M =10;
int N =30;
int K = 10;
struct element {
int *i;
int *j;
int k;
};
struct element *create_structure();
void print_element(struct element *);
int compare (const void *, const void * );
struct element * sort(struct element *);
main()
{
srand(time(NULL));
struct element *lista;
int count;
lista=create_structure();
print_element(lista);
printf("\n");
lista=sort(lista);
}
struct element *create_structure()
{
int aux1,aux2,count,load;
struct element *structure;
structure = (struct element *) malloc (M*sizeof(struct element *));
structure->k=K;
structure->i= (int *)malloc(structure->k*sizeof(int));
structure->j=(int *)malloc (structure->k*sizeof(int));
for (count = 0; count < K; count ++)
{
aux1=rand()%N;
(structure->i)[count]=aux1;
do
{
aux2=rand()%N;
}while(aux2==aux1);
(structure->j)[count]=aux2;
}
return (structure);
}
void print_element(struct element *lista)
{
int count;
for(count = 0; count < K; count ++)
{
printf("%d %d\n",lista->i[count],lista->j[count]);
}
}
int compare(const void *a, const void *b)
{
struct element *ia = (struct element *)a;
struct element *ib = (struct element *)b;
int *ptr1=(ia->i);
int *ptr2=(ib->i);
return (*ptr1-*ptr2);
}
struct element * sort(struct element *list)
{
qsort(list, sizeof(list->i)/ sizeof(int) , sizeof(list->i), compare);
//qsort(list->i, K, sizeof(list->i), compare);
print_element(list);
return (list);
}
Sorry for being late to the party ! :)
So let's start first by mentioning the wrong statements in your code
>> First
in function create_structure() you want to allocate memory for your structure pointer
struct element *structure; // here your structure pointer is
//pointing to memory space of type struct element
structure = (struct element *) malloc (M*sizeof(struct element *));
|------------------------|
|
V
Here you are allocating memory space of type struct element* which is
wrong ! instead it must be sizeof(struct element)
Concerning the while loop in the same function I found that it is totally useless
aux1=rand()%N;
(structure->i)[count]=aux1; // the value is in aux1 variable
do
{
aux2=rand()%N;
}while(aux2==aux1); // the loop try to get the same value of aux1
// or you have just stored it in aux1
(structure->j)[count]=aux2; // it is easy to delete the while loop and
// change aux2 by aux1
>> Second
Concerning the sort
qsort(list, sizeof(list->i)/ sizeof(int) , sizeof(list->i), compare);
|-----|
|
V
It is not an adress of the array so it is Wrong !
after knowing the major problems here is a version of code based on your own code which works perfectly
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int M =10;
int N =30;
int K = 10;
struct element {
int *i;
int *j;
int k;
};
struct element *create_structure();
void print_element(struct element *);
int compare (const void *, const void * );
void sort(struct element *); // changed the return value of sort
// to void as the argument will be changed directly because it is a
// pointer
int main()
{
srand(time(NULL));
struct element *lista;
lista=create_structure();
printf("\n--------- i --- j ---------\n\n");
print_element(lista);
printf("\n---------------------------\n");
sort(lista);
print_element(lista);
return 0;
}
struct element *create_structure()
{
int aux1=0,count=0;
struct element *structure;
// Changed the allocation of structure pointer
structure = (struct element *) malloc (sizeof(struct element));
structure->k=K;
structure->i= (int *)malloc(K*sizeof(int));
structure->j=(int *)malloc (K*sizeof(int));
for (count = 0; count < K; count ++)
{
aux1=rand()%N;
// we kept only the first aux1 and copied it in the two arrays
(structure->i)[count]=aux1;
(structure->j)[count]=aux1;
}
return (structure);
}
void print_element(struct element *lista)
{
int count=0;
for(count = 0; count < K; count++)
{
printf("row=%2d : %2d %2d\n",count+1,(lista->i)[count],(lista->j)[count]);
}
}
int compare(const void *a, const void *b)
{
// compare the values of two case of array pointed by i of type int
return *(int*)a-*(int*)b;
}
void sort(struct element *list)
{
// we will sort the array pointed by i which contains K elements
// of type int and size sizeof(int) by using the compare function
qsort(list->i, K , sizeof(int), compare);
}
Hope it helps ! :)
Note: Using this code in codeblocks v13.12 generates under linux (gcc version 4.8.2) wrong output !! [ It might be a BUG in Code::Blocks]
but using it with command line with gcc gives correct output !!

How to use binary search on 2 tables of sorted data in c

I am looking into how to use binary search in the c language.
I will begin with,
i have a struct
struct keyval{
unsigned short key[2];
unsigned short val[2];
};
as you can see this is a struct with 2 arrays of shorts which can hold 2 short values.
i then memory allocate to these structs. this enables me to store many of this type of struct in memory.
struct keyval *codes1 = malloc(sizeof(struct keyval)*(0x1000000));
struct keyval *codes2 = malloc(sizeof(struct keyval)*(0x1000000));
I go through some loops and populate codes1 with struct keyval's. and then in another loop i populate codes2 with struct keyval's also
this data will have been populated on the basis of an iterating key. so basically it will be automatically sorted by key value.
i then sort my data on the val value . using the c qsort function
and my own compare function
if the short in location 0 of the val array of one is less than the short in the same position of the other struct then return -1 and so on.
qsort(codes1,SIZE_OF_CODES1, sizeof(struct keyval), compare);
qsort(codes2,SIZE_OF_CODES2, sizeof(struct keyval), compare);
int compare(const void *a, const void *b){
struct keyval *ia = (struct keyval *)a;
struct keyval *ib = (struct keyval *)b;
if(ia->val[0] > ib->val[0]){
return 1;
}else if (ia->val[0] < ib->val[0]){
return -1;
}else{
return (ia->val[1] - ib->val[1]);
}
}
now this is where i am stuck
i need to be able to binary search for every value in codes1 against the values in codes2.
and when codes1[i].val == codes2[i].val i can print out the values of codes1[i].key
and then codes2.[i].key
my attempt is as such
while(e <= SIZE_OF_CODES1){
struct keyval *found = (struct keyval*) bsearch(&codes1[e],codes2,SIZE_OF_CODES2,sizeof(struct keyval),compare );
if(found){
printf("\n found key = %08x %04x value = %04x %04x", found -> key, found -> key[1],found->val[0],found ->val[1] );
}
e++;
}
the above code will not find if the data matches as, i am certain there are places in the code where it matches
//added edit
just did a debug, and i found that when the bsearch calls the compare function,everytime it is called all the values associated with ia are zero but ib is correct.
the sort method is correct
could someone point me in the right direction on how to implement a binary search , i am getting very stuck
my old compare function
int compare(const void *a, const void *b){
struct keyval *ia = (struct keyval *)a;
struct keyval *ib = (struct keyval *)b;
if(ia->val[0] > ib->val[0]){
return 1;
}else if(ia->val[0] < ib->val[0]){
return -1;
}else{
if(ia->val[1] > ib->val[1]){
return 1;
}else if(ia->val[1] < ib->val[1]){
return -1;
}else{
return 0;
}
}
}
to compare the lists as you describe, step through codes1, then do a bsearch() on codes2 for each entry in codes1. You can reuse compare. I am not sure if SIZE_OF_CODES1 and 2 are variables or defines, I am assuming they reflect the count of elements in each array.
struct keyval *src=codes1;
struct keyval *dest=code2;
struct keyval *p
int i=0;
while(i< SIZE_OF_CODES1)
{
if( (p=(struct keyval *)bsearch(src, dest, SIZE_OF_CODES2, sizeof(struct keyval), compare))!=NULL)
printf("duplicate codes1: %d %d codes2: %d %d\n", src->key,src->val, p->key, p->val);
i++
}

Resources