【问题标题】:Sorting array of string based on first character value根据第一个字符值对字符串数组进行排序
【发布时间】:2021-10-30 18:03:04
【问题描述】:

我正在阅读 C++ 中的字符串和函数指针。在那里,我发现了一个基于第一个字符值的字符串排序数组。 这是我的代码解决方案。

#include<bits/stdc++.h>
using namespace std;

bool compare1(const void *a, const void  *b)
{
    string c = *(string *)a;
    string d = *(string *)b;
    return c[0]<d[0];
}

int main()
{

    string str[3];
    int i;
    
    for(i=0;i<3;i++)
    {
        cout<<"Enter "<<i+1<<" string";
        cin>>str[i];
    }
    
    cout<<"Before sort"<<endl;
    for(i=0;i<3;i++)                               
    {
        cout<<str[i]<<" ";
    }
    
    cout<<endl;
    
    sort(str.begin(),str.end(),compare1);
    
    cout<<"After sort"<<endl;
    for(i=0;i<3;i++)
    {
        cout<<str[i]<<" ";
    }
    return 0;
}

但我收到编译时错误:[Error] 请求“str”中的成员“begin”,它属于非类类型“std::string [3] {aka std::basic_string [ 3]}'

如何解决这个问题?

【问题讨论】:

  • 您似乎将 C 库的 qsort 与 C++ 库的 std::sort 混淆了。
  • 与您的问题无关,但您可以使用 lambda 来简化您的代码:std::sort(std::begin(str), std::end(str), [](const std::string&amp; s1, const std::string&amp; s2) { return s1[0] &lt; s2[0]; });
  • 看起来您几乎是在从所谓的“竞赛”或“在线评委”网站学习编程和 C++。不要那样做,那不是他们的目的。获取some good books 阅读并参加一些课程。您需要这样做,因为您的代码中有多个基本错误。
  • 你不应该使用void*,尤其是当方法只有在string*s 被传递时才能正常工作(虽然你首先不需要指针)
  • 除了实际答案之外,如果您不想等待分段错误,您应该确保您的比较函数还检查字符串是否真的有第一个元素。

标签: c++ string sorting string-comparison function-definition


【解决方案1】:

标准 C++ 数组没有 begin 成员。

要么使用函数式重载:

sort(std::begin(str), std::end(str), compare1);

或者改用std::vector&lt;std::string&gt; str

或使用std::array&lt;std::string, 3&gt;,这是一个固定大小,但确实支持begin成员。

【讨论】:

  • 或者由于数组的大小在编译时是已知的,std::array&lt;std::string, 3&gt;
【解决方案2】:

两个问题:

  1. str 是一个原始数组,没有名为 beginend 的成员函数。您可以改用std::beginstd::end

  2. std::sort 传递要比较的元素; compare1 应该接受 std::strings 而不是指针。

例如

bool compare1(const string& c, const string& d)
{
    // for empty strings
    if (c.length() == 0 || d.length() == 0)
        return c.length() < d.length();

    return c[0] < d[0];
}

然后

sort(std::begin(str), std::end(str), compare1);

LIVE

【讨论】:

  • 我建议你添加一些东西来捕捉比较器中字符串的长度是否为零。不希望在等待中出现分段错误。
  • @Aziuth 好主意。
  • @Hashinclude 这就是std::sort 的工作方式,你必须遵守它的规则。 Type1 和 Type2 类型必须是 RandomIt 类型的对象可以被取消引用,然后隐式转换为它们。​
  • 好的,谢谢,我把它与 C 语言中的 qsort() 混淆了,我们可以在比较器中使用 const void*,然后将其类型转换为所需的数据类型。
  • @Hashinclude C 和 C++ 完全不同。在大多数情况下,您不会在 C++ 中使用原始指针(和数组)。
【解决方案3】:

我认为string 是标准类的名称std::string

您声明了一个包含三个 string 类型的对象的数组

string str[3];

数组不是类。所以他们没有包括beginend在内的成员函数。

所以这个说法

sort(str.begin(),str.end(),compare1);

不正确。

在标头中声明了通用函数std::beginstd::end,例如可以使用

#include <iterator>

//...

sort( std::begin( str ), std::end( str ), compare1 );

或者没有这些函数你也可以写

sort( str, str + 3, compare1 );

另一方面,函数 compare1 不正确。函数 sort 将两个 std::string 类型的对象或对此类对象的引用传递给比较函数。

必须至少按以下方式声明和定义

bool compare1( const std::string &s1, const std::string &s2 )
{
    return s1[0] < s2[0];
}

【讨论】:

  • 为什么我们不能在 compare 函数中使用 void*?
  • @Hashinclude 因为函数排序没有传递给比较函数指针。
  • 那么有没有什么概念可以在比较函数中使用void*,只有当我们对基本数据类型(char,char类型的数组指针)进行操作时?
  • @Hashinclude 您可以将类型 void * 用于比较函数的参数,然后它会获取指针类型的参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
  • 1970-01-01
  • 2016-10-24
  • 2021-03-27
相关资源
最近更新 更多