重载比较运算符以与 C++ 中的 STL 排序一起使用

发布于 2025-01-06 22:27:55 字数 2211 浏览 2 评论 0原文

我正在编写一个程序,它将读取带有社会安全号码(当然不是真实号码)的姓名列表,并根据姓氏或 ssn 对列表进行排序,具体取决于命令行参数。我已经超载了<为了简单起见,还重载了输入和输出运算符。一切编译都很好,直到我在 main 末尾添加排序函数和输出。我很困惑。有什么想法吗?任何其他提示也将不胜感激。

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

}

I am writing a program that will read in a list of names with social security numbers (not real ones of course) and sort the list based on either last name or ssn, depending on a command line argument. I have overloaded the < operator and also overloaded input and output operators for simplicity. Everything compiles fine until I add the sort function and the output at the end of main. I'm stumped. Any ideas? Any other tips are also greatly appreciated.

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

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晨曦÷微暖 2025-01-13 22:27:55

这有点奇怪,您的编译器应该警告您

if (rhs.t_sort = false)

,您没有测试 t_sort 的值,而是始终将其设置为 false。

无论如何,针对 truefalse 测试 bool 是没有必要的,因为这就是 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;
    }
}

This is kind of strange, and something your compiler should warn about

if (rhs.t_sort = false)

You are not testing the value of t_sort but always setting it to false.

Testing a bool against true or false is bit unnecessary anyway, as this is what the if-statement is doing already.

Try this code instead

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;
    }
}
看轻我的陪伴 2025-01-13 22:27:55

您确定对 record 类进行排序具有真正的意义,而不仅仅是出于任意排序的目的吗?考虑一个大整数的类,其中对象的这种排序是有意义的,但它对您的记录是否有意义?或者如果你不排序,它就失去了意义吗?

[imo] 不要将 operator< 引入的排序与您的类定义结合起来,除非它与您的类定义有真正的对应关系,换句话说,如果人类直观地清楚某些“对象 a”比某个“对象 b”小。

如果您想要对非直观可排序的类对象进行不同的排序,例如按名字、按姓氏、按汽车数量等升序与降序,则尤其如此。那么如果不查找文档/代码,没有人会记住您的默认排序是什么,从而失去了它的便利性。

相反,可以传递仿函数或就地 lambda 函数:

#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());
}

Are you sure that having an ordering for your record class has a real meaning, not only for arbitrary sorting purposes? Consider a class for large integers, where a such an ordering for your objects makes sense, but would it make such valid sense for your records? Or does it lose its meaning if you never sort?

[imo] Do not couple this ordering introduced by operator< with your class definition unless it has a real correspondence with it, in other words, if it is intuitively clear for human beings that some "object a" is smaller than some "object b".

This holds especially true if you ever want to have different orderings for non intuitively order-able class objects, think of ascending vs. descendening, by first name, by last name, by number of cars, et cetera. Then nobody will remember what your default ordering is without looking up the documentation/code, thus loosing even its convenience.

Instead, either pass functors or in-place lambda function:

#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());
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文