Qsort основан на столбце в c-строке? - PullRequest
0 голосов
/ 19 сентября 2009

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

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 принимает в качестве аргумента. Если я правильно понимаю, функция сравнения должна взять два константных пустых указателя на сортируемые элементы и вернуть int. Это означает, что я не могу передать указатели на структуры в функцию сравнения, потому что это не то, что будет сортировать qsort. Я не могу передать номер столбца для сортировки в функцию сравнения, потому что он может принимать только два аргумента. Как я могу обойти это, чтобы отсортировать эти строки на основе определенных столбцов?

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

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

Ответы [ 4 ]

2 голосов
/ 19 сентября 2009

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

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);
2 голосов
/ 19 сентября 2009

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

2 голосов
/ 19 сентября 2009

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

1 голос
/ 19 сентября 2009

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

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

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

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

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 вы не можете сделать это иначе, чем создать глобальную переменную.

...