Вопрос

Проект класса включает в себя сортировку массива строк, при этом каждая строка содержит одинаковое количество столбцов, например:

Cartwright   Wendy    93
Williamson   Mark     81
Thompson     Mark     100
Anderson     John     76
Turner       Dennis   56

Программа принимает аргумент командной строки, по которому следует сортировать столбец, и должна распечатывать отсортированные строки без изменений.

Я хотел бы использовать strtok, чтобы разбить копии каждой строки на столбцы и создать структуры для каждой строки следующим образом:

struct line {
    char * line;
    char column_to_sort_on[MAX_COLUMN];
}

Моя проблема заключается в указателе функции сравнения, который qsort принимает в качестве аргумента.Если я правильно понимаю, функция сравнения должна принимать два указателя const void к элементам, которые нужно отсортировать, и верните int.Это означает, что я не могу передавать указатели на структуры в функцию сравнения, потому что это не то, что будет сортировать qsort.Я не могу передать номер столбца для сортировки в функцию сравнения, поскольку она может принимать только два аргумента.Как я могу обойти это, чтобы отсортировать эти строки по определенным столбцам?

редактировать: Сортировка ограничивается qsort или моей собственной, если я действительно этого хочу.Дайте выбор, я выбираю qsort.:)

редактировать № 2:Похоже, что консенсус заключается в том, чтобы либо использовать глобальную переменную для номера столбца, либо просто использовать qsort для сортировки массива структур.Я не думал просто сортировать структуры и использовать указатель в них для вывода исходной строки.Думаю, именно это я и сделаю.Спасибо всем за помощь!

Это было полезно?

Решение

Вы можете передать структуры следующим образом:

struct line {
    char * line;
    char column_to_sort_on[MAX_COLUMN];
}
...

line*  Lines[max_lines]; // here you store the structs

int
cmp_lines( const void *elem1, const void *elem2 )
{
    line*  line1 = *(line**)elem1;
    line*  line2 = *(line**)elem2;
    // do the comparisons
}

qsort(Lines, max_lines, sizeof(line*), cmp_lines);

Другие советы

Предполагая, что вы не ограничены использованием qsort, вы можете использовать std::sort с объектом-функтором, который хранит номер столбца.Если вам нужно использовать qsort, одним из быстрых и грязных решений будет сохранение номера столбца в глобальной переменной и использование его в функции сравнения.

Различные функции сравнения, каждая из которых принимает всю структуру, но каждая использует для сравнения только один столбец.

С++ или С?Судя по вашим тегам, я предполагаю, что это C++.Давайте попробуем способ STL.

Вы должны использовать std::sort вместо qsort. std::sort может принимать не только указатель на функцию (по сравнению с ее альтернативой C), но и любой объект это можно вызвать как функцию.Возможно, вы знаете, что экземпляры классов можно вызывать как функции с помощью operator().Тогда решение простое:создайте класс-функтор, который будет создавать различные функции при построении.Тогда вызов сортировки будет выглядеть так:

std::sort(array, array+size, comparator(2 /* sort by column #2 */));

Класс функтора эффективно создает так называемое «замыкание»:динамически создаваемый функциональный объект, который имеет локальные переменные, но не разделяет их с другими функциональными объектами, созданными таким образом.Это будет выглядеть так:

class comparator{
  private: unsigned int field_n;
  public: comparator(unsigned int _field_n) : field_n(_field_n) {};
  public: int operator () (char const *  lhs, char const * rhs)
       { /* compare here fields with index field_n */ };
};

Обратите внимание, что вместо сравнения пустых указателей «функция» (т.е.экземпляр класса, который вы создаете) имеет char * параметры, чтобы не заморачиваться с приведением типов.

К сожалению, в C это невозможно сделать иначе, как создать глобальную переменную.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top