简体   繁体   中英

How to sort an array of struct/class based on its member data?

How to sort an array of struct/class based on its member data, as this fails ?

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;                                          

struct O{
    const string n;
    int a=1;
};

bool bfunction (O a, O b) {
    return a.n < b.n; }

int main () {

    O m[]={ {"unta"}, {"jalan"}, {"sama"}, {"aki"} };


// using function in sort control
    sort (m.begin(), m.end(), &bfunction);
}

gcc gives:

 error: request for member ‘begin’ in ‘m’, which is of non-class type ‘O [4]’
     sort (m.begin(), m.end(), &bfunction);
             ^~~~~
 error: request for member ‘end’ in ‘m’, which is of non-class type ‘O [4]’
     sort (m.begin(), m.end(), &bfunction);
                        ^~~~~

sincere useful help is appreciated

Use std::array

#include <iostream>
#include <algorithm>
#include <vector>
#include <array>    

struct O {
    std::string n;
    int a;

    O(const char* c) : a(1) { n = c; }
};

bool bfunction(O a, O b) {
    return a.n < b.n;
}

int main() {
    std::array<O, 4> m = { "unta", "jalan", "sama", "aki" };

    // using function in sort control
    std::sort(m.begin(), m.end(), &bfunction);
}

Some mistakes are made here:

  1. sort (m.begin(), m.end(), &bfunction); calls begin() and end() on an O[] . But an array has no member functions whatsoever.

    You got some choice here: Either make m an std::array<O, 4> or a std::vector<O> or use std::begin(m) and std::end(m) which work for static arrays.

  2. The sorting function should take it's parameters via const reference:

    bool bfunction (const O &a, const O &b)

  3. In the sorting function an < bn compares two arrays of strings, but such a comparison is not defined anywhere. Thats a logic error you need to solve. Think about what you actually want to compare here. Comparison is defined for std::string , for example return an[0] < bn[0]; would work.

  4. When sorting anything elements need to be moved around. But your struct O has no move constructor, because you don't provide one and the automatically generated one would be ill formed because O has const members.

    I think the best way to deal with this is to make all member variables private and control access to them via getters and setters. For now, the easiest way is to just remove the const .

Here is a copy-paste-ready example of how I'd do it (assuming your n should simply be a string, rather than an array of seven strings). If you really want to have an array of strings as n , then you have to define a proper ordering for them.

#include <iostream>
#include <algorithm>
#include <vector>
#include <array>

class O {
    std::string n;
    int a;

public: 

    O(const char* c, int a = 1) : n(c), a(a) {}

    const std::string& get_n() const { return n; }

};

bool bfunction(const O& a, const O& b) {
    return a.get_n() < b.get_n();
}

int main() {

    std::array<O, 4> m = { "unta", "jalan", "sama", "aki" };

    std::sort(m.begin(), m.end(), &bfunction);

    for(auto& x : m) { 
        std::cout << x.get_n() << ',';
    }
}

Live code here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM