Qsort baseado em uma coluna em uma c-corda?
Pergunta
Um projecto classe envolve a triagem de uma matriz de cadeias, com cada cadeia contendo um número igual de colunas assim:
Cartwright Wendy 93 Williamson Mark 81 Thompson Mark 100 Anderson John 76 Turner Dennis 56
O programa aceita um argumento de linha de comando para o qual coluna para classificar, e deve imprimir as cordas ordenadas não modificado.
Eu gostaria de usar strtok para quebrar cópias de cada corda em colunas, e torná-estruturas para cada linha como esta:
struct line {
char * line;
char column_to_sort_on[MAX_COLUMN];
}
Meu problema é no ponteiro de função de comparação que qsort toma como arg. Se bem entendi, a função de comparação deve levar dois ponteiros void const para os itens a serem classificados , e retornar um int. Isso significa que eu não pode passar ponteiros para estruturas para a função de comparação, porque não é isso que qsort será a classificação. Eu não posso passar o número da coluna para classificar para a função de comparação, porque ele só pode ter dois argumentos. Como posso obter em torno deste para classificar essas seqüências com base em colunas específicas?
Editar: A ordenação é limitado a qsort ou meu próprio se eu realmente quero. Dê a escolha, eu escolho qsort. :)
edição # 2: O consenso parece ser utilizar uma variável global para o número de coluna, ou apenas qsort uso para classificar uma matriz de estruturas. Eu não tinha pensado de apenas classificar as estruturas, e usando o ponteiro neles para imprimir a string original. Eu acho que é o que vou fazer. Obrigado pela ajuda todos!
Solução
Você pode passar as estruturas como esta:
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);
Outras dicas
Assumindo que você não está limitado a usar qsort, você pode usar std :: sort, com um objeto functor que armazena o número da coluna. Se você tem que usar qsort, uma solução rápida e suja seria armazenar o número da coluna em uma variável global e da utilização que na função comparisson.
diferentes funções de comparação, os quais levam toda a estrutura, mas cada um usa apenas uma coluna para comparation.
C ++ ou C? Baseado em suas tags, eu suponho que de C ++. Vamos maneira tentativa STL.
Você deve usar std::sort
vez de qsort
. std::sort
pode levar não só ponteiro de função (em comparação com a sua alternativa C), mas qualquer objeto que pode ser chamado como função. Você pode saber que instâncias de classe pode ser chamado como funções com operator()
. Em seguida, a solução é simples: criar uma classe "functor" que vai criar funções diferentes sobre a construção. A chamada tipo iria então ficar assim:
std::sort(array, array+size, comparator(2 /* sort by column #2 */));
A classe functor efetivamente cria o chamado "fechamento": um objeto funcional criados dinamicamente que tem variáveis ??locais, mas não compartilhá-los com outros objetos funcionais criados desta forma. Ele ficaria assim:
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 */ };
};
Note que em vez de "função" de comparação ponteiros void (ou seja, a instância da classe que você cria) tem parâmetros char *
, para que você não se preocupar-se com o tipo de fundição.
Em C, infelizmente, você não pode fazer isso a outra maneira de criar uma variável global.