Сортировка строк с использованием qSort - PullRequest
2 голосов
/ 21 сентября 2010

согласно этому сайту

http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/

Я сделал следующую программу, которая сортирует строки

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

Вот ошибка, которую я получаю

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

Пожалуйста, помогите

Ответы [ 5 ]

11 голосов
/ 21 сентября 2010

Пожалуйста, обратите внимание: Строки C необычно хранить в двумерных массивах символов. Более нормально иметь char *ary[], например argv. Этот тип нельзя отсортировать напрямую, используя qsort и strcmp, потому что qsort передаст char **, а не char * в функцию сравнения. Это хорошо для эффективности, вместо целых строк можно поменять указатели. Справочная страница Linux для qsort содержит хороший пример кода с правильной функцией сравнения.

Вы не можете передать strcmp непосредственно в qsort в качестве функции сравнения, потому что qsort ожидает, что указатели будут аннулированы, тогда как strcmp ожидает, что указатели будут соответствовать char. Учитывая требуемое сходство между указателями на void и указателями на char, вы могли бы , вероятно, сделать это с помощью приведения (для вашего кода), но более чистый способ - написать функцию, которая принимает правильные типы: 1016 *

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

    return strcmp(aa, bb);
}

Обратите внимание, однако, что в C ++ вы обычно хотите использовать std::sort вместо qsort и, вероятно, использовать std::string вместо char *, в этом случае сортировка становится намного проще (и, как правило, быстрее) а также).

1 голос
/ 21 сентября 2010

Четвертый аргумент qsort принимает в качестве аргументов 2 указателя void *. Так что вам нужно определить функцию сравнения для вашей. обратитесь к этой ссылке для более подробной информации.

0 голосов
/ 15 июля 2018

Больше C ++ - Стиль - в настоящее время - с 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);
}

А в основном ():

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

Гораздо проще с вектором и std :: sort.

0 голосов
/ 19 апреля 2014

Вы можете передать 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;
}

используйте C, а не C ++

0 голосов
/ 21 сентября 2010

За , почему qsort завершается неудачно , не используйте его в 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 есть перегрузки для потоковых вставок для непосредственного вывода вектора, но вот одна простая версия .Это идет в заголовок, а не копируется и вставляется постоянно:

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