Ordinamento stringhe utilizzando qsort
Domanda
Secondo questo sito
http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/
Ho fatto seguente programma che ordina le stringhe
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char list[5][4]={"dat","mai","lik","mar","ana"};
int main(int argc, char *argv[])
{
int x;
puts("sortirebamde:");
for (x=0;x>sizeof(list)/sizeof(char);x++)
printf("%s\n",list[x]);
qsort(&list,(sizeof(list)/sizeof(char)),sizeof(list[0]),strcmp);
system("PAUSE");
return EXIT_SUCCESS;
}
Ecco l'errore che ottengo
13 C:\Documents and Settings\LIBRARY\Desktop\string_sortireba.cpp invalid conversion from `int (*)(const char*, const char*)' to `int (*)(const void*, const void*)'
13 C:\Documents and Settings\LIBRARY\Desktop\string_sortireba.cpp initializing argument 4 of `void qsort(void*, size_t, size_t, int (*)(const void*, const void*))'
Si prega di aiuto
Soluzione
Si prega di notare: Non è facile memorizzare le stringhe C in due array di caratteri dimensionali. E 'più normale avere char *ary[]
, come ad esempio argv. Questo tipo non può essere risolto direttamente utilizzando qsort
e strcmp
, perché qsort passerà char **
non char *
alla funzione di confronto. Questo è un bene per l'efficienza, i puntatori possono essere scambiati al posto di tutto stringhe. Il Linux pagina di manuale per qsort ha qualche codice buon esempio con una funzione di confronto corretto.
Non è possibile passare direttamente alla strcmp
qsort
come la sua funzione di confronto, perché si aspetta qsort
di passare puntatori a vuoto dove strcmp
aspetta puntatori a const char. Data la somiglianza richiesta tra puntatori a vuoto e puntatori a char, potrebbe , probabilmente farlo con un cast (per il codice), ma il modo più pulito sarebbe quello di scrivere una funzione che prende i giusti tipi:
int cmpstr(void const *a, void const *b) {
char const *aa = (char const *)a;
char const *bb = (char const *)b;
return strcmp(aa, bb);
}
Si noti, tuttavia, che in C ++ che normalmente si desidera utilizzare std::sort
invece di qsort
, e probabilmente usare std::string
invece di char *
, qual caso l'ordinamento diventa molto più semplice (e generalmente più veloce pure).
Altri suggerimenti
Il quarto argomento di qsort prende 2 puntatori void * come args.So è necessario definire una funzione di confronto per il vostro. fare riferimento a questo link per ulteriori dettagli.
Al di là perché qsort fallisce , non utilizzare in C ++.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
char const* const raw_data[5] = {"dat", "mai", "lik", "mar", "ana"};
std::vector<std::string> data (raw_data, raw_data + 5);
// would rarely be a global
// see below for code that needs to go here
int main() {
using namespace std;
cout << "before: " << data << "\n";
sort(data.begin(), data.end());
cout << "after: " << data << "\n";
return 0;
}
Boost ha flusso di inserimento sovraccarichi di uscita un vettore direttamente, ma qui è una versione semplice . Questo va in un colpo di testa, piuttosto che essere copiato e incollato in continua:
template<class Stream, class Iter, class Ch>
void write_sequence(Stream& s, Iter begin, Iter end, Ch const* initial, Ch const* sep, Ch const* final) {
if (initial) {
s << initial;
}
if (begin != end) {
s << *begin;
++begin;
for (; begin != end; ++begin) {
if (sep) {
s << sep;
}
s << *begin;
}
}
if (final) {
s << final;
}
}
template<class T, class A>
std::ostream& operator<<(std::ostream& s, std::vector<T,A> const& value) {
write_sequence(s, value.begin(), value.end(), "[", ", ", "]");
return s;
}
È possibile passare direttamente a strcmp qsort
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char list[5][4]={"dat","mai","lik","mar","ana"};
int main(int argc, char *argv[]) {
int x;
puts("unsorted:");
for (x=0;x<sizeof(list)/sizeof(list[0]);x++)
printf("%s\n",list[x]);
qsort(list,sizeof(list)/sizeof(list[0]),sizeof(list[0]),strcmp);
puts("sorted:");
for (x=0;x<sizeof(list)/sizeof(list[0]);x++)
printf("%s\n",list[x]);
// system("PAUSE");
return EXIT_SUCCESS;
}
uso C, C ++ non
Maggiori C ++ - Style - al giorno d'oggi - con static_cast:
int scmp(const void * s1, const void * s2)
{
const char* _s1 = *static_cast<const char* const*>(s1);
const char* _s2 = *static_cast<const char* const*>(s2);
return strcmp(_s1, _s2);
}
E nel main ():
char *str_arr[] = { "one", "two", "three" };
qsort(str_arr, sizeof(str_array)/sizeof(char*), sizeof(char*), scmp);
Molto più facile è con vettore e std :: sort.