开发者

Sorting strings using qSort

According to this site, I have done the following program which sorts strings.

#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;
}

Here is the error I get

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*))' 

Please help


Please note: It is unusual to store C strings in two dimensional char arrays. It's more normal to have char *ary[], such as argv. That type cannot be sorted directly using qsort and strcmp, because qsort will pass char ** not char * to the comparison function. This is good for efficiency, the pointers can be swapped instead of the whole strings. The Linux manpage for qsort has some good example code with a correct comparison function.

You can't pass strcmp directly to qsort as its comparison function because qsort expects to pass pointers to void where strcmp expects pointers to const char. Given the required similarity between pointers to void and pointers to char, you could probably do it with a cast (for your code), but the cleaner way would be to write a function that takes the right types:

int cmpstr(void const *a, void const *b) { 
    char const *aa = (char const *)a;
    char const *bb = (char const *)b;

    return strcmp(aa, bb);
}

Note, however, that in C++ you'd normally want to use std::sort instead of qsort, and probably use std::string instead of char *, which case the sorting gets a lot simpler (and generally faster as well).


The fourth argument of qsort takes 2 void* pointers as args.So you need to define a compare function for yours. refer to this link for more details.


You can pass strcmp directly to 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;
}

use C, not C++


Beyond why qsort fails, don't use it 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 has stream inserter overloads to output a vector directly, but here's one simple version. This goes into a header, rather than being copied and pasted continually:

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;
}


More C++-Style - nowadays - with 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);
}

And in main():

char *str_arr[] = { "one", "two", "three" };
qsort(str_arr, sizeof(str_array)/sizeof(char*), sizeof(char*), scmp);

Much easier is it with vector and std::sort.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜