-
Better way to do this?
I wonder if there is a better way of doing this. I don't lik the repetetive code in sorted_asc and sorted_desc.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
bool sorted_asc(void *data, size_t size, size_t datasize,
int (*compare)(const void *a, const void* b))
{
unsigned char *p = data;
for (int i = 0; i < size - 1 ; i++)
{
if(compare(p + i * datasize, p + ((i + 1) * datasize)) > 0)
return false;
}
return true;
}
bool sorted_desc(void *data, size_t size, size_t datasize,
int (*compare)(const void *a, const void* b))
{
unsigned char *p = data;
for (int i = 0; i < size - 1 ; i++)
{
if(compare(p + i * datasize, p + ((i + 1) * datasize)) < 0)
return false;
}
return true;
}
/* sorted - check if an array is sorted - either in descending or
* ascending order
*
* Possible use:
* assert(sorted(...));
* qsort(...)
* or
* assert(!sorted(...))
* qsort(...)
*/
bool sorted(void *data, size_t size, size_t datasize,
int (*compare)(const void *a, const void* b))
{
return sorted_asc(data, size, datasize, compare) ||
sorted_desc(data, size, datasize, compare);
}
int compare_int(const void *a, const void *b)
{
const int *i1 = a;
const int *i2 = b;
return *i1 - *i2;
}
int main(int argc, char **argv)
{
int a1[] = {1,2,3,4,5};
int a2[] = {5,4,3,2,1};
int a3[] = {3,2,1,4,5};
assert(sorted_asc(a1, 5, sizeof(int), compare_int));
assert(sorted_desc(a2, 5, sizeof(int), compare_int));
assert(!sorted(a3, 5, sizeof(int), compare_int));
assert(sorted(a1, 5, sizeof(int), compare_int));
assert(sorted(a2, 5, sizeof(int), compare_int));
printf("ALL TESTS PASSED\n");
return EXIT_SUCCESS;
}
-
It's hard for me to imagine a use case where I cared that an array was sorted but didn't care whether it was ascending or descending. Probably not worth a dedicated function.
You could define separate compare_int_asc and compare_int_desc functions and pass the desired one.
Consider a typedef:
Code:
typedef int (*Compare)(const void *a, const void* b);
void *data should be const void *data.
i should be size_t.
Don't define argc and argv if you aren't using them.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
typedef int (*Compare)(const void *a, const void* b);
bool sorted(const void *data, size_t size, size_t datasize, Compare compare) {
const unsigned char *p = data;
for (size_t i = 0; i < size - 1; i++)
if (compare(p + i * datasize, p + (i + 1) * datasize) > 0)
return false;
return true;
}
int compare_int_asc(const void *a, const void *b) {
const int *ia = a, *ib = b;
return *ia - *ib;
}
int compare_int_desc(const void *a, const void *b) {
const int *ia = a, *ib = b;
return *ib - *ia;
}
int main() {
int a1[] = {1,2,3,4,5};
int a2[] = {5,4,3,2,1};
int a3[] = {3,2,1,4,5};
assert(sorted(a1, 5, sizeof(int), compare_int_asc));
assert(sorted(a2, 5, sizeof(int), compare_int_desc));
assert(!(sorted(a3, 5, sizeof(int), compare_int_asc)
|| sorted(a3, 5, sizeof(int), compare_int_desc)));
printf("ALL TESTS PASSED\n");
return 0;
}
-
Thank you John. I like your solution much better.