Перегрузка операторов сравнения для работы с сортировкой STL в C ++ - PullRequest
2 голосов
/ 18 февраля 2012

Я пишу программу, которая будет читать список имен с номерами социального страхования (конечно, не настоящими) и сортировать список по фамилии или ssn в зависимости от аргумента командной строки. Я перегрузил оператор <, а также перегружал операторы ввода и вывода для простоты. Все компилируется нормально, пока я не добавлю функцию сортировки и вывод в конце main. Я в тупике. Есть идеи? Любые другие советы также приветствуются. </p>

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

enum sortVar { NAME, SOCSEC };

class record {
    public:
        friend bool operator<(record& rhs, record& name);
        friend ostream& operator<<(ostream& out, record& toWrite);
        friend istream& operator>>(istream& in, record& toRead);
        bool t_sort;    
    private:
        string firstName, lastName, ssn;

};

bool operator<(record& rhs, record& next)
{
    if (rhs.t_sort = false) {
        if (rhs.lastName == next.lastName)
            return rhs.firstName < next.firstName;
        else
            return rhs.lastName < next.lastName;
    }
    else if (rhs.t_sort = true)
        return rhs.ssn < next.ssn;
}

ostream& operator<<(ostream& out, record& toWrite)
{
    out << toWrite.lastName 
         << " " 
         << toWrite.firstName 
         << "    " 
         << toWrite.ssn;
}

istream& operator>>(istream& in, record& toRead)
{
    in >> toRead.lastName >> toRead.firstName >> toRead.ssn;
}

int main(int argc, char* argv[])
{
    if (argc !=3) {
        cerr << "Incorrect number of arguments.\n";
        exit(1);
    }
    if (argv[1] != "name" || argv[1] != "socsec") {
        cerr << "Argument 1 must be either 'name' or 'socsec'.\n";
        exit(1);
    }

    sortVar sortMode;
    if (argv[1] == "name")
        sortMode = NAME;
    else if (argv[1] == "socsec")
        sortMode = SOCSEC;

    ifstream fin(argv[2]);

    vector<record> nameList;
    while(!fin.eof()) {
        record r;
        if (sortMode == NAME)
            r.t_sort = false;
        else if (sortMode == SOCSEC)
            r.t_sort = true;
        fin >> r;
        nameList.push_back(r);
    }

    //sort(nameList.begin(), nameList.end());
    //cout << nameList;

}

Ответы [ 2 ]

5 голосов
/ 18 февраля 2012

Это немного странно, и ваш компилятор должен предупредить о

if (rhs.t_sort = false)

Вы не проверяете значение t_sort, но всегда устанавливаете в значение false.

Проверка bool против true или false в любом случае не нужна, так как это то, что уже делает заявление if.

Попробуйте этот код вместо

bool operator<(const record& rhs, const record& next)
{
    if (rhs.t_sort) {
        return rhs.ssn < next.ssn;
    }
    else
    {
        if (rhs.lastName == next.lastName)
            return rhs.firstName < next.firstName;
        else
            return rhs.lastName < next.lastName;
    }
}
1 голос
/ 21 февраля 2012

Вы уверены, что наличие порядка для вашего класса record имеет реальное значение не только для произвольной сортировки?Рассмотрим класс для больших целых чисел, где такой порядок для ваших объектов имеет смысл, но будет ли он иметь такой правильный смысл для ваших записей?Или оно теряет смысл, если вы никогда не сортируете?

[imo] Не объединяйте этот порядок, введенный operator<, с вашим определением класса, если оно не имеет реального соответствия с ним, другими словами, если оноИнтуитивно понятно для людей, что некоторый «объект а» меньше, чем какой-либо «объект б».

Это особенно верно, если вы когда-нибудь захотите иметь разные порядки для объектов классов с не интуитивно упорядоченным порядком, подумайте о восходящем и нисходящем, по имени, по фамилии, по количеству автомобилей и так далее.Тогда никто не вспомнит, какой у вас порядок по умолчанию, не просмотрев документацию / код, тем самым потеряв даже его удобство.

Вместо этого, либо передайте функторы, либо лямбда-функцию на месте:

#include <algorithm>
#include <functional>
#include <vector>

struct Foo {
    int x;
    Foo (int x) : x(x) {}
};

struct FooAscending : std::binary_function<Foo,Foo, bool>
{
    bool operator() (Foo const &lhs, Foo const &rhs) const { 
        return lhs.x < rhs.x;
    }
};

int main () {
    std::vector<Foo> foos;
    foos.emplace_back(1);
    foos.emplace_back(2);

    sort (foos.begin(), foos.end(), 
          [](Foo const &l, Foo const &r) { return l.x < r.x; });
    sort (foos.begin(), foos.end(), 
          [](Foo const &l, Foo const &r) { return l.x > r.x; });

    sort (foos.begin(), foos.end(), FooAscending());
}
...