Qsort на основе столбца в строке c?
Вопрос
Проект класса включает в себя сортировку массива строк, при этом каждая строка содержит одинаковое количество столбцов, например:
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 это невозможно сделать иначе, как создать глобальную переменную.