【问题标题】:Sorting strings using qSort使用 qSort 对字符串进行排序
【发布时间】:2011-04-15 01:08:13
【问题描述】:

根据这个site,我已经完成了以下对字符串进行排序的程序。

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

请帮忙

【问题讨论】:

  • 这不是在 C 中对字符串进行排序的好方法,您可能应该对 char * 数组进行排序,而不是对具有固定长度字符串的二维数组进行排序。
  • 应该是:for (x=0;x

标签: c++ c qsort


【解决方案1】:

请注意:将 C 字符串存储在二维字符数组中是不常见的。有char *ary[]比较正常,比如argv。该类型不能直接使用qsortstrcmp排序,因为qsort会将char **而不是char *传递给比较函数。这对效率有好处,可以交换指针而不是整个字符串。 Linux manpage for qsort 有一些很好的示例代码,具有正确的比较功能。

您不能将strcmp 直接传递给qsort 作为比较函数,因为qsort 期望传递指向void 的指针,而strcmp 期望传递指向const char 的指针。鉴于指向 void 和指向 char 的指针之间所需的相似性,您可以可能使用强制转换(对于您的代码)来实现,但更简洁的方法是编写一个函数正确的类型:

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 *,这种情况下排序会变得更简单(而且通常更快以及)。

【讨论】:

  • 此函数适用于提出的问题,但这不是对字符串进行排序的好方法。这不适用于对 char * 数组进行排序,因为 qsort 会将 char ** 传递给函数。
  • @SamWatkins:让我直说吧。你投反对票是因为我回答了他提出的问题,而不是告诉他如何做一些与他所问的几乎(但不完全)完全不同的事情?
  • 好吧,也许这不公平。我提议对您的答案进行编辑,如果编辑被接受,我将删除反对票。 (由于“规则”,现在无法删除它)
  • 为了完整起见,强制转换版本为:(int ()(const void, const void *))strcmp),参见working example
【解决方案2】:

qsort 的第四个参数需要 2 个 void* 指针作为参数。所以你需要为你定义一个比较函数。 请参阅此link 了解更多详情。

【讨论】:

    【解决方案3】:

    你可以将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++

    【讨论】:

    • 不要把strcmp直接传给qsort,正常情况下(对char *数组排序)是行不通的,而且总是类型冲突。
    【解决方案4】:

    why qsort fails 之外,不要在 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 具有流插入器重载以直接输出向量,但这里有一个 simple version。这进入标题,而不是被不断复制和粘贴:

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

    【讨论】:

      【解决方案5】:

      更多 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);
      }
      

      在 main() 中:

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

      使用 vector 和 std::sort 会容易得多。

      【讨论】:

        猜你喜欢
        • 2010-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-19
        • 2013-03-23
        • 2016-09-10
        • 2013-02-06
        • 1970-01-01
        相关资源
        最近更新 更多