compare function in inbuilt qsort function - c

I am trying to use the inbuilt qsort function in C to sort a structure
typedef struct abc{
long long int fir;
long long int sec;
}abc;
In the compare function I used the below code so that if the variable "fir" is same between any two elements in the array of structure abc then the sorting condition will depend on the variable "sec".
long long int cmp(const abc* e1, const abc* e2)
{
if(e1->fir==e2->fir)
return e1->sec-e2->sec;
else
return e1->fir-e2->fir;
}
The code doesn't seem to work properly.
What is the correct method to do it?

long long int cmp(const abc* e1, const abc* e2)
does not have the correct signature for a qsort comparison function, so your program has undefined behavior. You should set your compiler warning flags high, and it will warn you of such things.
Your actual test is fine as long as the subtraction can't overflow, which is probably not a problem for long long. Edit The subtraction is not fine here, precisely because the return value of cmp must be an int. The result of the subtraction long long, so if you have large values the result is too big to fit into an int and qsort is sure to produce the wrong order.
More generally, though, this is more accurate:
int cmp(const void* v1, const void* v2)
{
const struct abc* p1 = v1;
const struct abc* p2 = v2;
if (p1->fir < p2->fir)
return -1;
else if (p1->fir > p2->fir)
return 1;
else
return p1->sec < p2->sec? -1 : p1->sec > p2->sec? 1 : 0;
}

The built-in qsort you're using probably expects a "lower-than" (operator<) predicate, which is the normal terminology for C++. And yours returns true in both cases as long as the arguments aren't equal.
You have to return true IFF (if and only if) e1<e2.

Related

How to use qsort for structure members?

I am still learning about C programming, and I am having a bit of an issue with my program.
So my structure is declare in q.h file
#define MAXIMUM_LENGTH 80
struct Tsunami {
unsigned int day;
unsigned int month;
unsigned int year;
unsigned fatalities;
double height;
char location[MAXIMUM_LENGTH];
};
and the function that uses qsort is :
double get_median_height(const struct Tsunami* begin, size_t count)
{
double median = 0;
double compare1,compare2;
struct Tsunami* store = (struct Tsunami*) malloc (sizeof(struct Tsunami) * count);
for (int i = 0; i < (int)count; i++)
{
store[i].month = begin[i].month;
store[i].day = begin[i].day;
store[i].year = begin[i].year;
store[i].fatalities = begin[i].fatalities;
store[i].height = begin[i].height;
strcpy(store[i].location, begin[i].location);
}
qsort(store, count, sizeof(Tsunami), compare_events);
if(count % 2 == 0)
{
printf("%ld",count);
compare1 = store[(count/2)].height;
printf("%lf",compare1);
compare2 = store[(count/2) +1].height;
printf("%lf",compare2);
median = (compare1 + compare2)/2;
}
else
{
median = store[(count/2)].height;
}
free(store);
return median;
}
My compare_events code is
int compare_events(const void* first, const void* second)
{
struct Tsunami* first = (struct Tsunami*)first;
struct Tsunami* second = (struct Tsunami*)second;
return (second->height - first->height);
}
For some reason, it does not help me sort out the value of store.height from smallest to largest. Can someone explain to me why? and how should I use the qsort instead?
Your comparison function:
Is backwards. It's supposed to return a number less than zero if first < second, but yours does the opposite. So intuitively it should be return first->height - second->height. However...
As "chux - Reinstate Monica" alluded to in comments, your heights are of type double but the comparison function must return int. So your function implicitly converts their difference to an int, but this conversion always rounds toward zero. Thus any two heights that differ by less than 1 will have a difference less than 1, which will be rounded to zero and qsort will think the two Tsunamis are of equal height, and may put them in the array in any order.
What you really want is something like sign(first->height - second->height). Unfortunately C has no standard sign function, but you can find many possible implementations at Is there a standard sign function (signum, sgn) in C/C++?. (This will also fix another bug, which is that your function will not correctly compare heights whose difference doesn't fit in an int.)

c function to return one of two possible types

I currently use three different functions to return a numeric value (one returns a double, the other two return a long):
int main(void)
{
// lots of code
dRate = funcGetInterestRate();
lMonths = funcGetTerm();
lPrincipal = funcGetPrincipal();
// lots of code
return 0;
}
The three functions code is about 90% the same so I would like to consolidate into 1 function. I want to pass a value flag to a single function something like this:
if "1" passed, determine interest rate, return a double
if "2" passed, determine term of loan, return a long
if "3" passed, determine principal of loan, return a long
I only want to return 1 value ever from the function when it is called, but the value I want to return can be either a double or a long. I want to do something like this:
void funcFunction(value passed to determine either long or double)
{
// lots of code
if (foo)
return double value;
else
return long value;
}
Is there an easy way to do this?
A function's return type is fixed at compile time. You can't change the return type based on the parameters you pass in.
However, since your main goal is to remove repeated code in the functions and consolidate them, this can be addressed in a different way. In other words, this is an XY problem.
What you can do in your case is extract the common code in each of your three functions into a separate function, then the three original functions can call the common function to do most of the work, then extract the part they need and return that.
For example:
struct loan {
double rate;
long term;
long principal;
};
void calcLoan(struct loan *loan)
{
// do stuff
loan->rate = // some value
loan->term = // some value
loan->principal = // some value
}
double funcGetInterestRate()
{
struct loan loan;
calcLoan(&loan);
return loan.rate;
}
long funcGetTerm()
{
struct loan loan;
calcLoan(&loan);
return loan.term;
}
long funcGetPrincipal()
{
struct loan loan;
calcLoan(&loan);
return loan.principal;
}
No, C does not allow this. The return type is in the function declaration (which you have as void).
Slightly easier is to provide two pointers to variables and indicate which one to use in the return value:
int funcFunction(yourArgument, long *longResult, double *dblResult)
{
// lots of code
if (foo)
{
*dblResult = value;
return 1;
} else
{
*longResult = otherValue;
return 0;
}
}
(And possibly you can even use a union.)
However ... I had to use value and otherValue as inside the function you cannot use the same variable to hold either a long or a double. You can – again, with a union – but this is stressing the eaze of having only one single function to the breaking point.
You might consider returning some tagged union. The Glib GVariant type could be inspirational, and since Glib is free software, you could study its source code. See also this answer.
So you would declare some public struct with an anonymous union inside:
struct choice_st {
bool islong;
union {
long i; // valid when islong is true
double d; // valid when islong is false
}
}
and you could return a value of that struct choice_st.
struct choice_st res;
if (foo) {
res.islong = true;
res.i = somelong;
return res;
}
else {
res.islong = false;
res.d = somedouble;
return res;
}
You might also decide to use C dynamic memory allocation, return a freshly malloc-ed pointer to struct choice_st, and adopt a convention about who is responsible of free-ing that pointer. (BTW, GVariant is doing something similar to this).
You sort of can do this. It's easier to show than explain, but I'll add an explanation if this isn't clear:
void add_or_divide_by_xor(unsigned int a, unsigned int b, unsigned short c,
unsigned long *add, unsigned double *divide) {
unsigned int xor = a ^ b;
if (add != NULL) {
*add = xor + c;
}
if (divide != NULL) {
*divide = (double)xor / (double)c;
}
}
Called:
unsigned long add;
unsigned double divide;
add_or_divide_by_xor(5, 17, 4, &add, NULL);
add_or_divide_by_xor(17, 6, 4, NULL, &divide);
Depending on your platform, double might be a superset of long. You should already know whether this is true (because you know what your algorithms do, and what their possible output values are); if you don't, consider the following:
double can represent integers up to 253 exactly
long is either a 32-bit or a 64-bit type
So if your long values are 32-bit, you can just always return double from your functions, and cast it to long outside your functions, where needed.
You could try something like this.
#include <stdio.h>
void* func1(int key){
static double interest;
static long term;
static long principle;
//your common code to modify values of interest, term and principle
//
//Let us give them some dummy values for demonstration
interest = 34.29347;
term = 5843535;
principle = 7397930;
//conditions
if(key == 1){
return &interest;
}
else if(key == 2){
return &term;
}else if(key == 3){
return &principle;
}else printf("%s\n","error!!");
}
int main()
{
printf("%f\n",*(double*)func1(1));
printf("%ld\n",*(long*)func1(2));
printf("%ld\n",*(long*)func1(3));
func1(4);
return 0;
}
Output
34.293470
5843535
7397930
error!!

Returning error with unsigned values?

I'm making a data structure library. One function I am allowing users to call is:
unsigned int index(struct myDataStructure, void* value);
It searches my data structure and returns the index location of where that value exists in it.
ex.
{ 'A', 'D', 'C' }
char val1 = 'A';
unsigned int location = index(s, &val1); // location = 0
char val2 = 'C';
location = index(s, &val2); // location = 2
If the element does not exist in the list, then I don't know what to return. Here are the options that I've ruled out so far:
Using an Assert or system exit or exception to end the run-time. I don't think there would be much use in that because the user would have to call contains to make sure the element was in the structure before calling index()
Returning UINT_MAX or any constant in the range of 0 <= UINT_MAX. Those could be index values.
Changing the return type to long, so I can return -1. I don't want to switch data types.
Having the user pass in a **unsigned int so that I can either point it to NULL if does not exist or a real index value. This is not user friendly for people reading my API to understand.
The best solution I had was to do:
// Change return type to pointer.
unsigned int* index(struct myDataStructure, void* value)
{
static int val;
if (value exists...)
{
val = correct index value
return &val;
}
else
{
return NULL;
}
}
But I still feel like this solution is very poor.
You're right that returning a pointer to static is bad in many ways. It's not thread safe, and - worse - it invites users to do stuff like
int *aIndexLoc = index(data, &a);
int *bIndexLoc = index(data, &b);
if (aIndexLoc && bIndexLoc)
printf ("a's loc is %u; b's loc is %u\n", *aIndexLoc, *bIndexLoc);
And of course get the wrong answer.
First... If you want your library to be future-proof, then don't return unsigned for an array index. Return size_t.
Then... There are several idioms for dealing with error returns. The most common is to return an int or enum error code as the function value and the actual return value with a pointer arg. By convention, 0 means "okay" and non-zero values are various error codes. Also, if your data structure is more than a few bytes, don't pass a complete copy of it. Pass a pointer
typedef int ERROR;
ERROR index(size_t *result, struct myDataStructure *myStruct, void *valueToFind);
and thence something like:
size_t loc[1];
struct myDataStructure someData[1];
int aValue[1];
initialize(someData);
get(aValue);
ERROR error = index(loc, someData, aValue);
if (error) {
fprintf(stderr, "Couldn't find the value. Error code: %d\n", error);
return;
}
The 1-element array thing is a trick that lets you code the same way whether an object is allocated on the stack or heap. You can treat the name of the array as a pointer. E.g. someData->fieldName and *loc work just fine.
Several possibilities:
On error return (unsigned int) -1 using
unsigned int index(struct myDataStructure, void* value)
On error return -1 using
ssize_t index(struct myDataStructure, void* value)
(ssize_t is POSIX)
Pass in the address of an unsigned int to point to the result and return -1 on error and 0 on success, using
int index(struct myDataStructure, void* value, unsigned int * result)
Using
an assertion I feel is not appropriate here, as it ends your program.
a static buffer is coding style of the last millennium. It makes your library unusable in a multithreaded context.
You could pass a pointer to a bool that sets as true or false accordingly.
unsigned int index(struct myDataStructure, void *value, bool *ok);

qsort not sorting list of unsigned long ints

The following code is produced strange results when trying to sort of series of unsigned long ints. I have no idea why. It compiles warningless. The problem lies somewhere in my usage of qsort but I've scruntinzed that line for a few hours now. I think my comparison function is okay. I've tried semi-blindly trying all permutations I can think of to make sure I am passing the right arguments and still no dice. Any help locating my issue would be appreciated:
#include<stdio.h>
#include<stdlib.h>
#define LENGTH 10
static int cmpfunc (const void *a, const void *b) {
const unsigned long int x=*(const unsigned long int*)a, y=*(const unsigned long int*)b;
printf("x=%lu ",x); printf("y=%lu ",y);
if ( x==y ) {
puts("returning 0..."); return 0;
} else {
if ( x>y ) {
puts("returning 1..."); return 1;
} else {
puts("returning -1..."); return -1;
}
}
}
int main(void) {
/* declare the storage for our "array". Using malloc instead of [] because in
real program array size shall be dynamic */
unsigned long int *mystorage=malloc(LENGTH*sizeof(unsigned long int)); /* check for NULL */
/* fill up array with values in non-monotonic order and show the values */
for(unsigned long int counter=0;counter<LENGTH;counter++) {
*(mystorage+counter*sizeof(unsigned long int))=(unsigned long int)(counter*(LENGTH-counter));
printf("value is %lu\n",*(mystorage+counter*sizeof(unsigned long int)));
}
/* sort array */
qsort(mystorage, LENGTH, sizeof(unsigned long int), cmpfunc);
/* print out array again to see if it changed */
for(unsigned long int counter=0;counter<LENGTH;counter++) {
printf("value is %lu\n",*(mystorage+counter*sizeof(unsigned long int)));
}
exit(EXIT_SUCCESS);
}
*(mystorage+counter*sizeof(unsigned long int))
=
(unsigned long int)(counter*(LENGTH-counter));
... is incorrect. (I rearranged your whitespace a little.) It should be
mystorage[counter] =
counter*(LENGTH-counter); // the cast is redundant
The following three are equivalent:
mystorage[counter]
counter[mystorage] // yes, this weird thing is equivalent
*(mystorage+counter)
Compare the last line to your code. When you add a pointer and an integer, the compiler will already know to move by the correct number of bytes. Because you include the sizeof stuff, you have these two equivalent lines (that are different from the above three lines)
*(mystorage + counter*sizeof(unsigned long int))
mystorage[counter*sizeof(unsigned long int)]
It should be clear that these two will access outside the array bounds.
Your program is wrong in the part
for(unsigned long int counter=0;counter<LENGTH;counter++) {
*(mystorage+counter*sizeof(unsigned long int))=(unsigned long int)(counter*(LENGTH-counter));
printf("value is %lu\n",*(mystorage+counter*sizeof(unsigned long int)));
}
When you add some integers to pointer compiler automatically use address arithmetic, so you should not use *sizeof(unsigned long int). The same mistake in the printing loop. So use simple indexing mystorage[counter] or *(mystorage+counter)

C a comparator of int for an array of pointers

I'm following LCTHW tutorial and I have a task to do.
This is the data structure:
typedef struct DArray {
int end;
int max;
size_t element_size;
size_t expand_rate;
void **contents;
} DArray;
I have declared a typedef:
typedef int (*DArray_compare) (const void *a, const void *b);
When I create a sorting function, I pass to it a DArray_compare, the problem is that I can't figure out how to do an example of this comparator.
I tried to do something like this:
int compare(const void *a, const void *b)
{
int i = (int)*a;
int k = (int)*b;
printf("%d %d\n", i, k);
return i - k;
}
But I get an error:
error: operand of type 'void' where arithmetic or pointer type is required int i = (int)*a;
The question is: without changing the struct and the typedef of the comparator, I want to create a comparator that compares int, how can I do it?
int i = *(int*)a;
// This one has more parens to make it really obvious what your intent is.
int k = *((int*)b);
The second line (k=) is easiest to explain cos of all the brackets. You can rewrite it as follows:
// Cast b from a pointer to a void into a pointer to an int.
int *X = (int*)b;
// k = "what X is pointing to" or "the contents of X"
int k = *X;
edit:
I think ralu's comment is suggesting you change all the void* to int* which is a much safer solution if you have that power.
typedef int (*DArray_compare) (const int *a, const int *b);
int compare(const int *a, const int *b)
{
int i = *a;
int k = *b;
...
A comparison function for use with bsearch() or qsort() from the standard C library for arrays of DArray structures might look like:
int compare(const void *a, const void *b)
{
const DArray *d1 = a;
const DArray *d2 = b;
if (d1->end < d2->end)
return -1;
else if (d1->end > d2->end)
return +1;
else if (d1->max < d2->max)
return -1;
else if (d2->max > d2->max)
return +1;
else
return 0;
}
Clearly, if you need to compare other fields, you can add those comparisons into the framework above quite easily. The general structure of the function is my recommended way of writing such comparators. You can add explicit casts to the assignment lines if you wish; C++ would require them, but C does not.
Note that your typedef is of minimal relevance to the comparator itself (though the comparator as a function pointer should match that typedef). It is the type that a comparator should have, but you can't use that typedef name when writing the function. You could use the typedef in the implementation of the sort function and in its declaration.
I observed in a couple of places that returning the difference of two signed int values as the result of the comparator leads to undefined behaviour.
In a comment to a now deleted answer, AR89 asked:
Instead of the subtraction an if statement would be safer?
Yes. Consider what happens if you have 16-bit int values and you compare -30,000 and +30,000; you've got signed overflow, and you might get a positive value back from your comparator, even though the first value is less than the second. Analogous situations can occur with 32-bit or 64-bit integers. They're relatively unlikely; if you know that your values are well within range, you'd be OK. But for general purpose code, you should do the piecewise comparison:
if (i < k)
return -1;
else if (i > k)
return +1;
else
return 0;
as it works regardless of the values of i and k. Also note that the if comparison works reliably for unsigned int types too, whereas subtraction really doesn't work then (the result is always zero or positive).

Resources