2

I am trying to check if two arrays contain the same elements. Since I don't know if the input file is sorted correctly I want to use qsort() to sort the array first and them compare it against the array cmpvalues.

However I can't get qsort to sort the array like the array cmpvalues. The array where the values are stored should be sorted like the array cmpvalues so that it's a lot easier to compare.

#include <stdio.h>

#define MAXCOLR   14
#define MAXLINE  100
#define MAXCHR  1024   
#define _GNU_SOURCE

typedef struct {
    char color[MAXCOLR];
    int value;
} colorval_t;

int cmpfunc(const void *a, const void *b) {
    int aa, bb;
    aa = *(int *)a;
    bb = *(int *)b; 
    return (aa - bb);   
}

int main(int argc, char **argv) {
    size_t n;
    int cmpvalues[] = {
        65,
         2,
         3,
         4,
         5,
         6,
         7,
         8,
         9,
        10,
        74,
        81,
        75,
        65,
         2,
         3,
         4,
         5,
         6,
         7,
         8,
         9,
        10,
        74,
        81,
        75
    };
    size_t ndx = 0;
    char buf[MAXCHR];
    colorval_t arr[MAXLINE] = {{ .color = "" }};

    FILE *fp = argc > 1 ? fopen(argv[1], "r") : stdin;

    if (!fp) { 
        perror("file open failed");
        return 1;
    }

    while (ndx < MAXLINE && fgets(buf, MAXCHR, fp)) {
        char c;
        if (sscanf(buf, "%13s %d", arr[ndx].color, &arr[ndx].value) == 2)
            ndx++;
        else if (sscanf(buf, "%13s %c", arr[ndx].color, &c) == 2) {
            arr[ndx].value = c;
            ndx++;
        }
    }
    if (fp != stdin)
        fclose(fp);   

    for (size_t i = 0; i < ndx; i++)
        printf("arr[%2zu] : %s %d\n", i, arr[i].color, arr[i].value);

    //sorts the array
    qsort(arr, 26, sizeof(arr[26]), cmpfunc);
    for (n = 0 ; n < 26; n++) {   
        printf("%d ", arr[n].value);
    }

    //checks if arrays have the same element
    int j;
    for (j = 0; j < 26; j++) {
        if (arr[j].value != cmpvalues[j]) {
            printf("wrong");
            break;
        }
    }
    return 0;
}

input:

RED A
RED 2
RED 3
RED 4
RED 5
RED 6
RED 7
RED 8
RED 9
RED 10
RED J
RED Q
RED K
BLACK 10
BLACK J
BLACK Q
BLACK K
BLACK A
BLACK 2
BLACK 3
BLACK 4
BLACK 5
BLACK 6
BLACK 7
BLACK 8
BLACK 9
1
  • 1
    You pass colorval_t * to qsort, yet your cmpfunc expects int* argument. The cmpfunc does not sort according to your cmpvalues array just only subtracts the ints. You need to change it to compare coloarval_t values and also take the color into account. You need to define _GNU_SOURCE before any #include statement for it to work. You are just lucky sizeof(arr[26]) works and is valid, however I can guess it doesn't mean what you think it means. You have posted the input to your program - please post the output of your program and the expected output of you program. Commented Dec 23, 2018 at 18:57

1 Answer 1

1

Your comparison function is wrong.

The qsort function passes pointers to the elements in the array you sort, so if you have an array of colorval_t then the arguments are of type colorval_t *.

Since you treat the pointers are int * you have a mismatch, and that will lead to undefined behavior.

That means your comparison function should look something like

int cmpfunc (const void * a, const void * b) {
    colorval_t *first = (colorval_t *) a;
    colorval_t *second = (colorval_t *) b;

    return first->value - second->value;
}
Sign up to request clarification or add additional context in comments.

2 Comments

return first->value - second->value; is incorrect: subtracting int values coud overflow, causing undefined behavior. You could instead write: return (first->value > second->value) - (first->value < second->value); which is defined for all arithmetic types.
It is also advisable to avoid removing constness to prevent warnings: use const colorval_t *first = (const colorval_t *)a;...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.