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.
Related
I need to write a function that replaces 2 "numeric numbers", of otherwise unknown type.
I don't know the exact type and I can only use 2 parameters.
So this is what I have tried:
void swap(void *p1, void *p2)
{
char p;
char * q1 = (char *)p1;
char * q2 = (char *)p2;
for (int i = 0; i < sizeof(long double); i++)
{
p = q1[i];
q1[i] = q2[i];
q2[i] = p;
}
}
Usage:
double a = 100123000000.2;
double b = 100065450000.3;
printf("a: %1f, b: %1f\n", a, b);
swap(&a, &b)
printf("a: %1f, b: %1f\n", a, b);
This works fine but my question is what if my number is bigger then long double (or there is no one..)
Is my solution OK?
This works fine but my question is what if my number is bigger (?)
Is my solution is OK ?
Code will have trouble unless it knows the exact size. So, no, OP's solution is not OK.
Somehow void swap() needs to know the size of the data to swap.
i can only use 2 parameters.
Code can cheat and put all the data into 1 argument as a compound literal, since C99.
typedef struct {
void *a;
void *b;
size_t sz;
} swap_T;
// Only 1 parameter!!
void swap(swap_T sw) {
unsigned char * q1 = sw.a;
unsigned char * q2 = sw.b;
while (sw.sz > 0) {
sw.sz--;
unsigned char p = q1[sw.sz];
q1[sw.sz] = q2[sw.sz];
q2[sw.sz] = p;
}
}
int main(void) {
double a = 100123000000.2;
double b = 100065450000.3;
printf("a: %g, b: %g\n", a, b);
swap(((swap_T ) { &a, &b, sizeof a } )); // Compound literal
printf("a: %g, b: %g\n", a, b);
return 0;
}
Output
a: 1.00123e+11, b: 1.00065e+11
a: 1.00065e+11, b: 1.00123e+11
Code could wrap the swap(((swap_T ) { &a, &b, sizeof a } )) in a macro that looks like a function call of 2
#define SWAP(a,b) (swap(((swap_T ) { &(a), &(b), sizeof (a) } )))
...
SWAP(a,b);
As long as a is not an expression with a variable logic array (VLA) and with side-effects, the macro should work fine.
Of course, best if a,b are the same type.
Your program should try to retrieve sizeof of its argument to know how many bytes to swap - perhaps as a third argument - you have no way of telling otherwise how big an argument is. With current function you will overwrite memory which will end up badly - especially in a bigger program. For example, consider a following program.
#include <stdio.h>
int main() {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
swap(&a[0], &a[4]);
for (int i = 0; i < 8; i++) {
printf("%d\n", a[i]);
}
}
Which will return 5, 6, 7, 8, 1, 2, 3, 4 - which clearly isn't expected - only 0th and 4th array elements should have been swapped.
It's possible to hide getting size behind a macro if needed.
#define SWAP(a, b) swap(&(a), &(b), sizeof(a))
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.
I have a 2 dimensional array that I am trying to sort in ascending order. For example, say the array looks like this:
4, 5
2, 6
7, 2
8, 4
I would like it to look like this:
2, 6
4, 5
7, 2
8, 4
The code that I have so far:
int temp = 0;
for(int m = 0; m<=nonZeroLength-1; m++){
for(int n = m+1; n<=nonZeroLength-1; n++){
if(nonZeroScoreSorcting[m] > nonZeroScoreSorcting[m+1]){
temp = nonZeroScoreSorcting[m];
strcpy(nonZeroScoreSorcting[m], nonZeroScoreSorcting[n]);
strcpy(nonZeroScoreSorcting[n], temp);
}
}
}
Assume that nonZeroLength has a value of 4 for this example. I am using strcpy() because I read that that is the only way to change elements of an array in C. When I run the program I get the following error:
passing argument 1 of ‘strcpy’ from incompatible pointer type [-Wincompatible-pointer-types]
I have also tried the regular assign method:
if(nonZeroScoreSorcting[m] > nonZeroScoreSorcting[m+1]){
temp = nonZeroScoreSorcting[m];
nonZeroScoreSorcting[m] = nonZeroScoreSorcting[n];
nonZeroScoreSorcting[n] = temp;
}
If you do in fact have a 2D array of int as you indicate, the key to sorting the array by row is understanding that during the sort, you will need to swap rows, not simply values. This is how you preserve the row-wise relationship during the sort.
You cannot do that treating each row of int as a string and attempting a row-wise copy using strcpy. This will result in Undefined Behavior when strcpy accesses values in the src argument outside the array bounds looking for a nul-terminating character that isn't present.
(though technically, providing a properly sized array for each src and dest and sizing 'n' in strncpy to copy 2 * sizeof(int) bytes can copy rows by virtue of limiting the read to n chars where no nul-terminating character is present -- but DON'T do it -- that's what memcpy (or memmove) is for).
Though the recommended way to sort in C is using the qsort function provided in stdlib.h, you can provide whatever sort algorithm you want. It will likely not be anywhere close to the efficiency of qsort, and certainly will be nowhere near as thoroughly tested. A simple row-sort using the slow old insertion sort could be done as follows:
#include <stdio.h>
#include <string.h>
int main (void) {
int a[][2] = {{ 4, 5 },
{ 2, 6 },
{ 7, 2 },
{ 8, 4 }},
n = sizeof a / sizeof *a,
col = sizeof *a / sizeof **a;
for (int i = 0; i < n; i++) /* insertion sort of a by row */
for (int j = i; j > 0 && *a[j] < *a[j-1]; j--) {
int tmp[col]; /* temporary VLA */
memcpy (tmp, a[j], sizeof *a);
memcpy (a[j], a[j-1], sizeof *a);
memcpy (a[j-1], tmp, sizeof *a);
}
for (int (*p)[2] = a; p < a + n; p++) /* output results */
printf ("%d, %d\n", (*p)[0], (*p)[1]);
return 0;
}
Example Use/Output
$ ./bin/inssort2d
2, 6
4, 5
7, 2
8, 4
With qsort most new C programmers are stumped by having to write a compare function to pass to qsort to let it do its job. It is really not that difficult at all. You know qsort will pass pointers to two of whatever you are sorting as arguments to your compare function.
In this case you will be sorting rows of integers (1D arrays of integers) based on the first element of each row. So qsort will compare two int * (pointers to int). You only care about the first element in each array (which you can obtain simply by dereferencing the pointer). A compare here can be a simple:
int cmp (const void *a, const void *b)
{
/* (a > b) - (a < b) */
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
}
(note: by using the result of the two inequalities you protect against over/underflow that could occur if you simply returned the result of a subtraction alone).
The complete qsort implementation would be:
#include <stdio.h>
#include <stdlib.h>
int cmp (const void *a, const void *b)
{
/* (a > b) - (a < b) */
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
}
int main (void) {
int a[][2] = {{ 4, 5 },
{ 2, 6 },
{ 7, 2 },
{ 8, 4 }},
n = sizeof a / sizeof *a;
qsort (a, n, sizeof *a, cmp); /* qsort array of pointers */
for (int (*p)[2] = a; p < a + n; p++) /* output results */
printf ("%d, %d\n", (*p)[0], (*p)[1]);
return 0;
}
(output is the same)
Look over both methods and know that qsort is the preferred method, but for learning, there is nothing wrong with doing it by hand to gain experience. Let me know if you have further questions.
Suppose I have a function:
void add(int a, int b , int c);
and I have an array which contains 3 integer values:
int L[] = {1,2,3};
Now I want to pass these values to add without writing add(L[0],L[1],L[2]).
I mean is there a way of creating a Single input from multiple inputs and passing it to the function which will treat that single input as multiple inputs ??.
You could try this
int L[] = {1,2,3};
add(L, 3);
where
void add(int *x, int length)
{
// use x[0], x[1], etc.
}
But I am not sure why you are having problem with your current approach.
Another option would probably be to encapsulate those three integers into a structure and pass the structure along.
If you mean something like Python
def foo(a, b, c):
return a + b + c
x = (1, 2, 3)
print(foo(*x)) # the '*' does the magic of calling foo with 1, 2, 3
then this is not possible in portable C.
What you can do is change the interface of foo to accept an array of arguments, e.g.
int sum(int *data, int n) {
int tot = 0;
for (int i=0; i<n; i++) {
tot += data[i];
}
return tot;
}
can call it with
int x[] = {10, 20, 30, 40};
int res = sum(x, 4);
If you cannot change the function definitions and you have many of them with the same signature what you can do is use function pointers to factor out the call:
int sum3(int a, int b, int c) {
return a+b+c;
}
int mul3(int a, int b, int c) {
return a*b*c;
}
int call_int_int3(int(*f)(int, int, int), int* args) {
return f(args[0], args[1], args[2]);
}
...
int data[] = {10, 20, 30};
int sum = call_int_int3(sum3, data);
int prod = call_int_int3(mul3, data);
but you will need a different wrapper for each distinct signature (number and type of arguments and type of return value).
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.