Daniel
Daniel

Reputation: 27

Comparing the private member variables of class objects stored in a vector - C++

So I have created a program which can read a .dat file of about 20 lines containing info about different atoms (name, symbol, mass etc) and added them all to a vector of class type I made called Atom.

How would I write a function to find the atom with the highest mass?

Here is my class:

class Atom
{
    string element, symbol;
    float number;
    float mass;
public:
    Atom(string e, string s, float n, float m){
        element = e; symbol = s; number = n; mass = m;
    }
    string getElement();
    string getSymbol();
    float getNumber();
    float getMass();
    float ratio();
    friend ostream& operator<<(ostream& os, Atom c);
};

and the information is added to a vector with the following statements

    ifstream fin("atoms.dat");  

    string E, S;
    float M, N;

    vector <Atom> periodic;

    while(!fin.eof()){
        fin >> E >> S >> M >> N;
        Atom Atom(E, S, M, N);
        periodic.push_back(Atom);
    }

I want to be able to write a function which finds which atom has the highest mass, I've tried using a max_element function but I keep getting errors. Is there a quick way of comparing the member variables of class objects stored in a vector?

I'm currently using C++ 98 as it is what my course requires.

Thanks

Upvotes: 0

Views: 328

Answers (3)

Ivaylo Valchev
Ivaylo Valchev

Reputation: 10425

I don't know what you did wrong with std::max_element, as you haven't provided what you've tried with it.

struct CompareAtomMass
{
    bool operator()(const Atom& lhs, const Atom& rhs) {
        return lhs.getMass() < rhs.getMass();
    }
};

and then:

vector <Atom> periodic;
Atom max_atom = *max_element(periodic.begin(), periodic.end(), CompareAtomMax());

struct CompareAtomMass is called a function object. It's a class with operator() overloaded to return a bool. std::max_element requires just such a function object to spit out the max element as it needs a way to compare your Atoms.

EDIT: You should mark your getter functions as const since they don't change the inner state of the class.

string getElement() const;
string getSymbol() const;
float getNumber() const;
float getMass() const;

This will allow you to call them from a const object of type Atom just as the above function object requires (const Atom&).

Upvotes: 2

Alan Milton
Alan Milton

Reputation: 424

It is a good idea to make your member functions const. This will allow this code. Otherwise just remove all const from my code. In case your vector is empty, you will get null pointer.

struct AtomMassComparator
{
    bool operator()(const Atom& lhs, const Atom& rhs)
    {
        return lhs.getMass() < rhs.getMass();
    }
};

const Atom* getAtomWithHighestMass(const vector<Atom>& v)
{
    vector<Atom>::const_iterator it = max_element(
        v.begin(), v.end(), AtomMassComparator());
    return v.end() == it ? 0 : &*it;
}

Upvotes: 0

Johan Lundberg
Johan Lundberg

Reputation: 27028

Variation of DeiDeis answer: If you only do this at one place, and don't feel a need to keep a CompareAtomMass function class, you can use a lambda:

const auto maxIt = max_element(periodic.begin(), periodic.end(), 
   [](const Atom& lhs, const Atom& rhs) {
    return lhs.getMass() < rhs.getMass();
));
if(maxIt != periodic.end()){
  // use *maxIt ;
}

in C++14 and later you can also use auto in lambdas:

const auto maxIt = max_element(periodic.begin(), periodic.end(), 
   [](const auto& lhs, const auto& rhs) {
    return lhs.getMass() < rhs.getMass();
));

Upvotes: 0

Related Questions