2012-01-20 17 views
5

Sto cercando di risolvere un tipo di concurrent_vector, dove hits_object è:Come ordinare vettore di puntatore a struct

struct hits_object{ 
     unsigned long int hash; 
     int position; 
}; 

Ecco il codice che sto utilizzando:

concurrent_vector<hits_object*> hits; 

for(i=0;...){ 
    hits_object *obj=(hits_object*)malloc(sizeof(hits_object)); 
    obj->position=i; 
    obj->hash=_prevHash[tid]; 
    hits[i]=obj; 
} 

Ora ho riempito uno concurrent_vector<hits_object*> chiamato hits.

Ma voglio ordinare questo concurrent_vector sulla proprietà position !!!

Ecco un esempio di ciò che è all'interno di una tipica colpi oggetto:

0 1106579628979812621 
4237 1978650773053442200 
512 3993899825106178560 
4749 739461489314544830 
1024 1629056397321528633 
5261 593672691728388007 
1536 5320457688954994196 
5773 9017584181485751685 
2048 4321435111178287982 
6285 7119721556722067586 
2560 7464213275487369093 
6797 5363778283295017380 
3072 255404511111217936 
7309 5944699400741478979 
3584 1069999863423687408 
7821 3050974832468442286 
4096 5230358938835592022 
8333 5235649807131532071 

Voglio risolvere la questione sulla base della prima colonna ("posizione" di tipo int). La seconda colonna è "hash" di tipo unsigned long int.

Ora ho provato a fare quanto segue:

std::sort(hits.begin(),hits.end(),compareByPosition);

dove compareByPosition è definito come:

int compareByPosition(const void *elem1,const void *elem2) 
{ 
    return ((hits_object*)elem1)->position > ((hits_object*)elem2)->position? 1 : -1; 
} 

ma io continuo a ricevere errori di segmentazione quando ho messo nella linea std::sort(hits.begin(),hits.end(),compareByPosition);

Si prega di aiuto!

+0

http : //stackoverflow.com/questions/328955/how-to-use- stdsort-with-a-vector-of-structures-and-compare-function –

+3

1/Sei sicuro di aver davvero bisogno di memorizzare i puntatori? Secondo il codice che ci hai fornito, direi che memorizzare i valori sarebbe probabilmente più facile e meno soggetto a errori. Se vuoi davvero memorizzare i puntatori, puoi dare un'occhiata a [Boost Pointer Container Library] (http://www.boost.org/doc/libs/release/libs/ptr_container/doc/ptr_container.html), o in ['boost :: indirect_iterator'] (http://www.boost.org/doc/libs/release/libs/iterator/doc/indirect_iterator.html). 2/Non dovresti usare 'malloc' per creare le tue istanze, usa' new' invece: 'malloc' non costruirà l'oggetto, solo allocare ... –

+2

... un po 'di memoria. 3/Per aggiungere elementi nel tuo contenitore, dovresti probabilmente usare 'push_back' o un metodo simile, a meno che il contenitore non sia già pieno. L'operatore '[]' viene utilizzato per accedere agli elementi già presenti nel contenitore, non per aggiungerne di nuovi. Il codice che hai dato dati in scrittura ad un certo punto in memoria che non era riservato (beh, supponendo che 'concurrent_vector' sia simile a' std :: vector' e ai mi piace). –

risposta

7

tua funzione di confronto deve restituire un valore booleano 0 o 1, non un intero 1 o -1, e dovrebbe avere una firma fortemente tipizzato:

bool compareByPosition(const hits_object *elem1, const hits_object *elem2) 
{ 
    return elem1->position < elem2->position; 
} 

L'errore si stava vedendo sono dovuti a std::sort interpretando tutto ciò che è diverso da zero restituito dalla funzione comp come true, il che significa che il lato sinistro è inferiore al lato destro.

NOTA: questa risposta è stata pesantemente modificata a seguito di conversazioni con sbi e Mike Seymour.

+1

In realtà, ha funzionato perfettamente per me! Sono ordinati i miei dati sulla posizione – Eamorr

+1

@MikeSeymour Questo deriva direttamente da [esempio di esempio] (http://www.cplusplus.com/reference/algorithm/sort/) su cplusplus.com. Non pensavo che fosse affatto confuso: in un certo senso (anche se non esattamente), è simile ai puntatori che passano invece degli iteratori agli algoritmi di STL. – dasblinkenlight

+1

@sbi Oh, non ho nemmeno prestato attenzione al passaggio dell'OP "void *" come parametri! Certo che hai ragione, sembra confuso. Ho modificato la risposta per risolvere questo problema. Grazie! – dasblinkenlight

4

Il terzo argomento si passa alla std::sort() deve avere una firma simile a, e la semantica di, operator<():

bool is_smaller_position(const hits_object* lhs, const hits_object* rhs) 
{ 
    return lhs->position < rhs->position; 
} 

Quando si memorizza puntatori in un vettore, non si può sovraccaricare operator<(), perché piccolo-che è corretto per tutti i tipi built-in.


Su un sidenote: Do not use malloc() in C++, utilizzare new invece. Inoltre, mi chiedo perché non stai utilizzando gli oggetti anziché puntatori. Infine, se concurrent_vector è qualcosa come std::vector, è necessario espanderlo in modo esplicito per accogliere nuovi oggetti.Questo è ciò che il codice sarà quindi simile:

concurrent_vector<hits_object*> hits; 

for(i=0;...){ 
    hits_object obj; 
    obj.position=i; 
    obj.hash=_prevHash[tid]; 
    hits.push_back(obj); 
} 
+0

"o si passa un terzo argomento a std :: sort()" Non è quello che fa l'OP? – dasblinkenlight

+0

Penso che resterò con un terzo argomento. Quel sovraccarico mi sembra un po 'non intuitivo! Grazie per il tuo commento. – Eamorr

+0

È un vettore di * puntatori * alle strutture. Quindi, la risposta di dasblinkenlight è più corretta. Forse cambi '' & 'a' * '? –

5

senza sapere cosa concurrent_vector è, non posso essere sicuro che cosa sta causando l'errore di segmentazione. Supponendo che sia simile a std::vector, è necessario popolarlo con hits.push_back(obj) anziché hits[i] = j; non è possibile utilizzare [] per accedere a elementi oltre la fine di un vettore o per accedere a un vettore vuoto.

La funzione di confronto dovrebbe essere equivalente a a < b, restituendo un valore booleano; non è una funzione di confronto in stile C che restituisce valori negativi, positivi o pari a zero. Inoltre, poiché sort è un modello, non sono necessari argomenti in stile C void *; tutto è fortemente tipizzato:

bool compareByPosition(hits_object const * elem1, hits_object const * elem2) { 
    return elem1->position < elem2->position; 
} 

Inoltre, di solito non si desidera utilizzare new (e certamente mai malloc) per creare oggetti per memorizzare in un vettore; il contenitore più semplice e sicuro sarebbe vector<hits_object> (e un comparatore che prende i riferimenti, piuttosto che i puntatori, come argomenti). Se davvero devi memorizzare puntatori (perché gli oggetti sono costosi da copiare e non movibili, o perché hai bisogno di polimorfismo - nessuno dei quali si applica al tuo esempio), usa puntatori intelligenti come std::unique_ptr o assicurati di averli delete una volta fatto con loro.

5

int (*)(void*, void*) è il comparatore per la funzione C qsort(). In C++ std::sort() il prototipo al comparatore è:

bool cmp(const hits_object* lhs, const hits_object* rhs) 
{ 
    return lhs->position < rhs->position; 
} 

std::sort(hits.begin(), hits.end(), &cmp); 

D'altra parte, è possibile utilizzare std::pair struct, che di default a confronto i suoi primi campi:

typedef std::pair<int position, unsigned long int hash> hits_object; 
// ... 
std::sort(hits.begin(), hits.end()); 
+0

Questa cosa 'std :: pair' non funzionerebbe con un vettore di puntatori.': ('Altrimenti questa è la migliore risposta.' + 1' da me. – sbi

+0

Oh, ho dimenticato che è vettore di puntatori.: / – Archie

0

Ciò non guardare a destra:

for(i=0;...){ 
    hits_object *obj=(hits_object*)malloc(sizeof(hits_object)); 
    obj->position=i; 
    obj->hash=_prevHash[tid]; 
    hits[i]=obj; 
} 

qui si sta già ordinando l'array in base a 'i' perché si imposta grado di i, così come diventa l'indice di colpi!

anche perché utilizzando malloc, si dovrebbe usare nuovo (/ delete). Potresti quindi creare un semplice costruttore per la struttura per inizializzare l'oggetto hits_

ad es.

struct hits_object 
{ 
    int position; 
    unsigned int hash; 

    hits_object(int p, unsigned int h) : position(p), hash(h) {;} 
}; 

poi scrivere invece

hits_object* obj = new hits_object(i, _prevHash[tid]); 

o anche

hits.push_back( new hits_object(i, _prevHash[tid])); 

Infine, la funzione di confronto dovrebbe usare lo stesso tipo di dati come vettore per i suoi argomenti

bool cmp(hits_object* p1, hits_object* p2) 
{ 
    return p1->position < p2->position; 
} 
Problemi correlati