Написание сортировки без учета регистра с использованием qsort - PullRequest
0 голосов
/ 22 сентября 2019

Я пытаюсь написать сортировку без учета регистра с помощью qsort.Однако у меня возникают проблемы при преобразовании const void * в const char * для сравнения строк.Вот что у меня есть:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

int case_insensitive_string_sort (const void * a, const void  *b) {

    int a_len = strlen(a);
    char a_char, b_char;
    printf("%d", a_len);

    for (int i=0; i<=a_len; i++) {
        a_char = tolower((char*) a[i]);
        b_char = tolower((char*) b[i]);
        if (a_char != b_char)
            return b_char - a_char;
    }

    return 0;

}

int main(int argc, char *argv[]) {

    // example doing the comparison with known input to see if it works
    // int a = case_insensitive_string_sort("axxx", "ab");

    qsort(argv, argc, sizeof(argv[0]), case_insensitive_string_sort);
    for (int i=0; i<argc; i++)
        printf("<%s>, ", argv[i]);

  }

Как мне правильно это сделать?

1 Ответ

1 голос
/ 22 сентября 2019

У вас наверняка возникнут проблемы

, преобразовывающие const void * в const char * для сравнения строк.

, поскольку сортируемый вами массив (argv) - это массив char*, а не массив char.А функция сравнения, используемая qsort, снабжена указателями на сортируемые объекты, а не на сами объекты.[Примечание 1]

Таким образом, если бы ваша функция сравнения получала char * (приведение к void *), вы бы сравнивали символы.Так как вы на самом деле сравниваете строки символов - то есть массивы символов - вы должны ожидать char** (приведение к void*).

Один довольно уродливый способ обработки, который будет:

> a_char = tolower(((char**) a)[i]);

Но я предпочитаю приводить аргументы один раз в верхней части функции:

int my_compare(void* va, void* vb) {
  char** a = va;
  char** b = vb;
  /* ... */
}

Я не делаю этого для эффективности;он, вероятно, производит тот же код.Я делаю это потому, что мне легче читать.

Заметки

  1. C не может передать объект неизвестного типа по значению.Но вы можете передать указатель объекту неизвестного типа, приведя указатель к void*, при условии, что вызываемая функция имеет способ узнать, каким был исходный тип указателя.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...