Sorting data from struct alphabetically? [duplicate] - c

Is there any library function available in C standard library to do sort?

qsort() is the function you're looking for. You call it with a pointer to your array of data, the number of elements in that array, the size of each element and a comparison function.
It does its magic and your array is sorted in-place. An example follows:
#include <stdio.h>
#include <stdlib.h>
int comp (const void * elem1, const void * elem2)
{
int f = *((int*)elem1);
int s = *((int*)elem2);
if (f > s) return 1;
if (f < s) return -1;
return 0;
}
int main(int argc, char* argv[])
{
int x[] = {4,5,2,3,1,0,9,8,6,7};
qsort (x, sizeof(x)/sizeof(*x), sizeof(*x), comp);
for (int i = 0 ; i < 10 ; i++)
printf ("%d ", x[i]);
return 0;
}

C/C++ standard library <stdlib.h> contains qsort function.
This is not the best quick sort implementation in the world but it fast enough and VERY
EASY to be used... the formal syntax of qsort is:
qsort(<arrayname>,<size>,sizeof(<elementsize>),compare_function);
The only thing that you need to implement is the compare_function, which takes in two
arguments of type "const void", which can be cast to appropriate data structure, and then
return one of these three values:
negative, if a should be before b
0, if a equal to b
positive, if a should be after b
1. Comparing a list of integers:
simply cast a and b to integers
if x < y,x-y is negative, x == y, x-y = 0, x > y, x-y is positive
x-y is a shortcut way to do it :)
reverse *x - *y to *y - *x for sorting in decreasing/reverse order
int compare_function(const void *a,const void *b) {
int *x = (int *) a;
int *y = (int *) b;
return *x - *y;
}
2. Comparing a list of strings:
For comparing string, you need strcmp function inside <string.h> lib.
strcmp will by default return -ve,0,ve appropriately... to sort in reverse order, just reverse the sign returned by strcmp
#include <string.h>
int compare_function(const void *a,const void *b) {
return (strcmp((char *)a,(char *)b));
}
3. Comparing floating point numbers:
int compare_function(const void *a,const void *b) {
double *x = (double *) a;
double *y = (double *) b;
// return *x - *y; // this is WRONG...
if (*x < *y) return -1;
else if (*x > *y) return 1; return 0;
}
4. Comparing records based on a key:
Sometimes you need to sort a more complex stuffs, such as record. Here is the simplest
way to do it using qsort library.
typedef struct {
int key;
double value;
} the_record;
int compare_function(const void *a,const void *b) {
the_record *x = (the_record *) a;
the_record *y = (the_record *) b;
return x->key - y->key;
}

For sure: qsort() is an implementation of a sort (not necessarily quicksort as its name might suggest).
Try man 3 qsort or have a read at http://linux.die.net/man/3/qsort

While not in the standard library exactly, https://github.com/swenson/sort has just two header files you can include to get access to a wide range of incredibly fast sorting routings, like so:
#define SORT_NAME int64
#define SORT_TYPE int64_t
#define SORT_CMP(x, y) ((x) - (y))
#include "sort.h"
/* You now have access to int64_quick_sort, int64_tim_sort, etc., e.g., */
int64_quick_sort(arr, 128); /* Assumes you have some int *arr or int arr[128]; */
This should be at least twice as fast as the standard library qsort, since it doesn't use function pointers, and has many other sorting algorithm options to choose from.
It's in C89, so should work in basically every C compiler.

try qsort in stdlib.h.

I think you are looking for qsort.
qsort function is the implementation of quicksort algorithm found in stdlib.h in C/C++.
Here is the syntax to call qsort function:
void qsort(void *base, size_t nmemb, size_t size,int (*compar)(const void *, const void *));
List of arguments:
base: pointer to the first element or base address of the array
nmemb: number of elements in the array
size: size in bytes of each element
compar: a function that compares two elements
Here is a code example which uses qsort to sort an array:
#include <stdio.h>
#include <stdlib.h>
int arr[] = { 33, 12, 6, 2, 76 };
// compare function, compares two elements
int compare (const void * num1, const void * num2) {
if(*(int*)num1 > *(int*)num2)
return 1;
else
return -1;
}
int main () {
int i;
printf("Before sorting the array: \n");
for( i = 0 ; i < 5; i++ ) {
printf("%d ", arr[i]);
}
// calling qsort
qsort(arr, 5, sizeof(int), compare);
printf("\nAfter sorting the array: \n");
for( i = 0 ; i < 5; i++ ) {
printf("%d ", arr[i]);
}
return 0;
}
You can type man 3 qsort in Linux/Mac terminal to get a detailed info about qsort.
Link to qsort man page

Use qsort() in <stdlib.h>.
#paxdiablo
The qsort() function conforms to ISO/IEC 9899:1990 (``ISO C90'').

There are several C sorting functions available in stdlib.h. You can do man 3 qsort on a unix machine to get a listing of them but they include:
heapsort
quicksort
mergesort

GNU qsort source in stdlib shows that it is quicksort.

Related

Suffix array using qsort() and strcmp

I have the following code to create a sorted suffix array but there is simply no output. I run the program and it halts for 1-2secs and then exits.
The code is based off the c++ answer on the following website: https://www.geeksforgeeks.org/suffix-array-set-1-introduction/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
struct suffix
{
int index;
char *suff;
};
int cmp(const void *a, const void *b)
{
const struct suffix *a1 = a;
const struct suffix *b1 = b;
return strcmp(a1->suff, b1->suff) < 0? 1 : 0;
}
int *buildSuffixArray(char *txt, int n)
{
struct suffix suffixes[n];
for (int i = 0; i < n; i++)
{
suffixes[i].index = i;
suffixes[i].suff = (txt+i);
}
qsort(suffixes, n, sizeof(int), cmp);
int *suffixArr = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
{
suffixArr[i] = suffixes[i].index;
}
return suffixArr;
}
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
{
printf("%d", arr[i]);
}
printf("\n");
}
int main()
{
char txt[] = "banana";
int n = strlen(txt);
int *suffixArr = buildSuffixArray(txt, n);
printf("following is suffix array for %s\n", txt);
printArr(suffixArr, n);
return 0;
}
Since there is no output, I assume that the problem is within the 'buildSuffixArray' function, specifically with qsort. I have tried fixing it but had no luck. Any help would be appreciated.
Summarizing the comments in the question from Weather Vane and Jonathan Leffler:
OP is passing the wrong element size to qsort(). qsort(suffixes, n, sizeof(int), cmp); should be qsort(suffixes, n, sizeof suffixes[0], cmp);. (Weather Vane).
The cmp function must return a negative value if the first argument sorts before the second argument, zero if they sort equal, or a positive value if the first argument sorts after the second argument. OP's cmp function returns 1 if the first argument is less than the second argument, otherwise 0. This will screw up any sorting by qsort(). (Jonathan Leffler)
It appears that the cmp function written by OP was based on the C++ code from Suffix Array | Set 1 (Introduction). In particular, OP's return strcmp(a1->suff, b1->suff) < 0? 1 : 0; is based on the similar return strcmp(a.suff, b.suff) < 0? 1 : 0; in the C++ code. The problem is that the C++ code uses std::sort(), not qsort() and the rules for the return value of the comparison functions are different.
As Jonathan Leffler points out, it would be sufficient for OP's cmp function to return the value from strcmp() directly:
return strcmp(a->suff, b->suff);
OP's printArr() function prints the integers in the array with no separation between each number. The correction is trivial.

How to use the sort function in C programming

Hello guys i have a situation here am trying to sort out numbers in C language but i seem to struggle to put a sort function can you please help me with this following souce code that prints out number and supose to sort them but i cant...please help:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num1 = 8, num2 = 6, num3 = 2, num4 = 4, num5 = 1;
printf("%d %d %d %d %d", num1, num2, num3, num4, num5);
// qsort(); THIS IS WHAT I STRUGGLE WITH AT THE MOMENT
return 0;
} // THIS CODE PRINTS OUT NUMBERS BUT ARE NOT SORTED...SO I NEED TO SORT THEM PLEASE
// YOUR HELP WILL BE MUCH APPRECIATED
// I NEED TO KNOW HOW TO USE THE SORT(qsort) FUNCTION
qsort() does one thing and it does it exceptionally well, it sorts arrays, and does so very efficiently. As noted in the comments, before you can use qsort() you will need to collect your values in an array rather than separate variables. Once you have an array, using qsort() is trivial, your only responsibility using qsort is to write the compare() function.
New users of qsort() usually have their eyes roll back in their heads when they see the declaration for the function:
int compare (const void *a, const void *b) { ... }
It's actually quite simple. a and b are simply pointers to elements of the array to compare. Since qsort() can handle any type array, the parameter type are void pointers. If you have an array of int, a and b are just pointers int (e.g. int*). You simply need to write your compare function to cast a and b to int* and dereference to compare the int values with each other.
The return of compare() is either less than zero (a sorts before b), zero (a and b are equal) or greater than zero (b sorts before a). So a niave compare() can be as simple as:
int compare (const void *a, const void *b)
{
int x = *(int *)a,
y = *(int *)b;
return x - y;
}
However, there is always a potential for x - y to overflow with a large negative x and large y or large x and large negative y. So you generally try and use the differnce between two comparisons to eliminate the potential for overflow, e.g.
int compare (const void *a, const void *b)
{
int x = *(int *)a,
y = *(int *)b;
return (x > y) - (x < y);
}
Now if you take any value of a and b the return will either be -1, 0 or 1 providing the sort information for qsort() without chance of overflow.
A short example using your values could be written as:
#include <stdio.h>
#include <stdlib.h>
int compare (const void *a, const void *b)
{
int x = *(int *)a,
y = *(int *)b;
return (x > y) - (x < y);
}
void prn_arr (int *arr, size_t nmemb)
{
for (size_t i = 0; i < nmemb; i++)
printf (i ? ", %d" : "%d", arr[i]);
putchar ('\n');
}
int main()
{
int num[] = {8, 6, 2, 4, 1};
size_t nmemb = sizeof num / sizeof *num;
puts ("array before sort:\n");
prn_arr (num, nmemb);
qsort (num, nmemb, sizeof *num, compare);
puts ("\narray after sort:\n");
prn_arr (num, nmemb);
}
Example Use/Output
$ ./bin/qsortnum
array before sort:
8, 6, 2, 4, 1
array after sort:
1, 2, 4, 6, 8
Look things over and let me know if you have further questions.

Using qsort in C on an array of strings

I can't figure out how to use qsort. I want to sort an array of strings. Like so:
John Adam
Adam -> John
Stacy Stacy
However, nothing I do seems to work. I've tried copying exactly what others have used (about 5 different qsort functions from various sources) and nothing has worked. I have one for int's that works (backwards but at least it works).
Here's the necessary code I have:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char name[80];
int age;
} RECORD;
RECORD record[25];
int main (int argc, char *argv[80]){ // Using command line to get my strings
int i = 2, j;
for(j = 0; j < (argc / 2); j++) //Converting and storing my ages
{
record[j].age = atoi(argv[i]);
i = i + 2;
}
int p, q = 1;
for(p = 0; p < (argc / 2); p++)
{
strcpy(record[p].name, argv[q]);
q = q + 2;
}
}
int compareByName(const void* a, const void* b) //The qsort that doesn't work at all
{
const char *ia = (const char *)a;
const char *ib = (const char *)b;
return strncmp(ia, ib, 25);
}
int compareByAge (const void * a, const void * b) //My other qsort that works backwards
{
RECORD *RECORDA = (RECORD *)a;
RECORD *RECORDB = (RECORD *)b;
return ( RECORDB->age - RECORDA->age );
}
void printRecords(RECORD r[], int num){
//printing stuff here
double size = sizeof r[0];
double count = sizeof(r)/size; //My qsort with size stuff, doesn't work
qsort(r, count, size, compareByName); // if I do it the same as the other
qsort (r, 25, sizeof(RECORD), compareByAge); //My other qsort that works backwards
//more printing stuff here
}
You don't have an array of strings, you have an array of RECORDs, and it sounds like you want to sort that array based on the strings in the name array of the records. So you want something like:
int compareByName(const void *a_, const void *b_) {
RECORD *a = a_, *b = b_;
return strcmp(a->name, b->name);
}
and then you sort with
qsort (r, 25, sizeof(RECORD), compareByName);
Okay, I see several issues here.
It's worth noting that sizeof is evaluated at compile time, so you can't use sizeof(r) to determine the size of a dynamically-sized array you were passed. I'm going to guess that's why num is passed in to printRecords.
As #Chris points out, you're sorting RECORD structures rather than character pointers, so the comparison function and the qsort call both need to take that into account.
You have the subtraction reversed in the age comparison - it needs to return a negative number if the left side is less than the right side, so use RECORDA->age - RECORDB->age.
First off (this is why your strings aren't sorting), double count = sizeof(r)/size; is wrong. sizeof(r) isn't doing what you expect it to. You'll need to pass the size of the array to printRecords() as described in this question:
How to get the length of array in C? is "sizeof" is one of the solution?
Second off,
int compareByAge (const void * a, const void * b) //My other qsort that works backwards is backwards because you're doing it backwards. Comparator functions always return A - B, not B - A.

compare function for anagram program

hey guys i have this code here but i cannot understand what the cmpfunc function does actually i don't understand the return statement can someone explain it to me ? than
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main()
{
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
Start with a qsort description - here it is.
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
So you need to write a function with such inputs and output to use in qsort.
int cmpfunc (const void * a, const void * b)
is ok, but inputs are *void and you need to compare integers in your case. So you will need to convert types. That's why there are
*(int*)a
Finally, return values of cmpfunc must match requirements from qsort description.
In article I mentioned at the begging of this post you can find this implementation:
int compareMyType (const void * a, const void * b)
{
if ( *(MyType*)a < *(MyType*)b ) return -1;
if ( *(MyType*)a == *(MyType*)b ) return 0;
if ( *(MyType*)a > *(MyType*)b ) return 1;
}
Your version is just a proper simplification of it.
cmpfnc is comparing the values of of pointers provided. It uses void* so that any kind of data can be passed to it and compared after being converted. First it converts the void* values to int* and then deferences them via * to subtract the integers they are pointing at
When you want to sort an array of some kind you need a comparison function.
the comparison function is used by qsort in order to compare two objects in the array. In this case the compare function compares two integers.

string_comparator in C

Okay so I need to several quite long strings in C. So I say to myself "why, you'd better use that handy dandy qsort function! Better write yourself a string_comparator for it!"
So of course I do and here she is:
int string_comparator(const void* el1, const void* el2) {
char* x = (char*) el1;
char* y = (char*) el2;
int str_len = strlen(x);
int i = 0;
for (; i < str_len; i++) {
//when there are non-equal chars
if (x[i] != y[i]) {
break;
}
}
return x[i] - y[i];
}
So of course I pass my handy dandy string_comparator function to the C qsort function as such:
qsort(list.words, list.num_words, sizeof(char*), string_comparator);
list is a struct that holds a char** (words) and ints which refer to the number of words held by it (such as num_words)
Now I have the problem where my list is not getting sorted alphabetically like I had hoped! I put a bunch of printf statements in my comparator and it printed out garbage values for the strings every time so I'm fairly sure that is the problem. But why is that the problem?? I've used qsort before (never to sort words..just sorting characters) and from what I understand this should work...What's going wrong here?
I appreciate any suggestions!
This is a common mistake when using qsort(). Here are the corrections:
char *x = *(char **) el1;
char *y = *(char **) el2;
Because list.words has type char **, not type char *, right?
Another example of qsort()
Here's how you sort an array of int with qsort():
int int_comparator(const void *el1, const void *el2)
{
int x = *(int *) el1;
int y = *(int *) el2;
return x - y;
}
void sort_ints(int *a, size_t n)
{
// these two lines are both "correct"
// the second line is more "obviously correct"
// qsort(a, n, sizeof(int), int_comparator);
qsort(a, n, sizeof(*a), int_comparator);
}
Now, if you go through and replace int with char *, you have to replace int * with char **.

Resources