C++ 中重载比较运算符导致“无效运算符”

发布于 2024-11-03 02:25:04 字数 1780 浏览 3 评论 0原文

目前正在尝试对 C++ 中的对象向量进行排序,每个对象都包含一个字符串。

字符串可以包含字母或数字(由于设计限制,这是必要的,因为可以更改比较器)。

目前,对象的类已重载,因此当比较两个对象时,将比较它们包含的字符串。这在一定程度上是有效的——但是,当我使用排序操作(例如 STL 排序)将对象按顺序排列时,它将按顺序对三个字符串(例如“1”、“4”、“12”)进行排序“1”、“12”、“4”。 4 大于 12,但由于它从最左边的数字开始比较,因此会发生这种“不正确”的排序。

我最初的反应是改变重载比较操作的方式。我首先检查要比较的字符串的长度——如果字符串的内容更大或更小,这将是一个明显的标志。

// overloaded comparision operators
friend bool operator<(const nodeRecord & record1, const nodeRecord & record2){
    // we need to deal with strings of different lengths...
    if(record1.comparator.length() < record2.comparator.length())
        return true;
    else
        return (record1.comparator < record2.comparator);
}

此操作会产生“表达式:无效运算符<”运行时期间的消息。

关于我在哪里犯了错误有什么想法吗?看来我应该能够准确地指示操作我希望排序操作如何发生——即使它是无效的,因为我当前正在使用向量来包含对象。

nodeRecord 对象初始化期间的比较器:

nodeRecord(int fromNode, int toNode, int connectionCost, bool compareByCost = false){
    // take the provided stock information and insert it into the object
    stringstream fromNodeSS;
    fromNodeSS << fromNode;
    this->fromNode = fromNodeSS.str();
    stringstream toNodeSS;
    toNodeSS << toNode;
    this->toNode = toNodeSS.str();
    this->connectionCost = connectionCost;

    // set the comparator to our chosen comparision term
    if (!compareByCost){
        this->comparator = this->fromNode; // we use from node in this case, since we build the tree outwards
    }
    else{
        stringstream ss;
        ss << this->connectionCost;
        this->comparator = ss.str(); // we use the connection cost in this case, to allow us to sort new connections
    }

    // set this as a non-null (active) record
    this->nullRecord = false;
}

Currently attempting to sort a vector of object, with each object containing a string, in C++

The strings can contain letters or numbers (due to a design constraint, this is necessary, as the comparator can be changed).

At the moment, the class of the object is overloaded, so that when two objects are compared, the strings they contain are compared. This works to a point -- however, when I use a sort operation (such as STL sort) to put the objects in order, it will sort three strings such as "1", "4", "12", in the order "1", "12", "4". 4 is greater then 12, but because it begins comparing from the most left digit, this 'incorrect' sort occurs.

My initial response was to change how I was overloading the comparison operation. I would first check the length of the string I was comparing -- which would be a telltale sign if the string's contents was larger or smaller.

// overloaded comparision operators
friend bool operator<(const nodeRecord & record1, const nodeRecord & record2){
    // we need to deal with strings of different lengths...
    if(record1.comparator.length() < record2.comparator.length())
        return true;
    else
        return (record1.comparator < record2.comparator);
}

This operation results in a "Expression: invalid operator<" message during runtime.

Any ideas as to where I am making a mistake? It seems that I should be able to dictate to the operation exactly how I want the sorting operation to occur -- even if it is invalid, since I am currently using a vector to contain the objects.

Comparator during initialization of the nodeRecord object:

nodeRecord(int fromNode, int toNode, int connectionCost, bool compareByCost = false){
    // take the provided stock information and insert it into the object
    stringstream fromNodeSS;
    fromNodeSS << fromNode;
    this->fromNode = fromNodeSS.str();
    stringstream toNodeSS;
    toNodeSS << toNode;
    this->toNode = toNodeSS.str();
    this->connectionCost = connectionCost;

    // set the comparator to our chosen comparision term
    if (!compareByCost){
        this->comparator = this->fromNode; // we use from node in this case, since we build the tree outwards
    }
    else{
        stringstream ss;
        ss << this->connectionCost;
        this->comparator = ss.str(); // we use the connection cost in this case, to allow us to sort new connections
    }

    // set this as a non-null (active) record
    this->nullRecord = false;
}

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

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

发布评论

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

评论(3

安人多梦 2024-11-10 02:25:04

您的操作员实际上无效。

如果您希望运算符 < 可用于排序,则它必须具有许多数学属性。一是反对称性质:

<代码>x < y => !(y < x)

让我们定义 x = "b"y = "aa"

  • <代码>x < y 因为 "b" 的长度小于 "aa" 的长度
  • y x 因为 "aa" 不如 "b"

嗯?

另请注意,如果数字以 0 为前缀,则您的定义很奇怪。

哦,比较字符串比比较数字慢得多。

我的看法是?停止使用比较信息更改节点。实际的比较模式与节点本身无关。

然后,您只需编写两种比较方法,一种按成本进行比较,另一种按来源进行比较。


回到最初的问题,如何编写一个考虑 ["a", "b", "aa"] 排序的比较器?

您已经快到了,但“长度”比较不完整。仅在长度不同的情况下才需要回退到实际的词法比较,因此您忘记了右侧参数的长度小于左侧参数的长度的情况。

因此,正确的形式是,假设有两个字符串:

bool compare(std::string const& lhs, std::string const& rhs) {
  if (lhs.length() < rhs.length()) { return true; }
  if (rhs.length() < lhs.length()) { return false; } // don't forget this
  return lhs < rhs;
}

You operator is effectively invalid.

The operator < must have a number of mathematical properties if you want it to be usable for sorting. One is the AntiSymmetry property:

x < y => !(y < x)

Let's define x = "b" and y = "aa".

  • x < y because the length of "b" is inferior to the length of "aa"
  • y < x because "aa" is inferior to "b"

Hum ?

Also note that your definition is weird for numbers in case they are prefixed by 0s.

Oh, and comparing strings is way slower than comparing numbers.

My take ? Stop altering the node with comparison information. The actual comparison mode has nothing to do within the node itself.

Then you'll just write two comparison methods, one that compares by cost and the other by origin.


And to come back to the original issue, how to write a comparator that consider ["a", "b", "aa"] sorted ?

You were almost there, but the "length" comparison is incomplete. You need to fall back to the actual lexical comparison only in the case the lengths differ, thus you forgot the case where the right hand side argument's length is inferior to the left hand side's one.

Thus the correct form is, supposing two strings:

bool compare(std::string const& lhs, std::string const& rhs) {
  if (lhs.length() < rhs.length()) { return true; }
  if (rhs.length() < lhs.length()) { return false; } // don't forget this
  return lhs < rhs;
}
相权↑美人 2024-11-10 02:25:04

找到以下引发错误的代码段,然后思考我的重载操作是如何工作的。

template<class _Ty1, class _Ty2> inline
    bool _Debug_lt(_Ty1& _Left, _Ty2& _Right,
        _Dbfile_t _File, _Dbline_t _Line)
    {   // test if _Left < _Right and operator< is strict weak ordering
    if (!(_Left < _Right))
        return (false);
    else if (_Right < _Left)
        _DEBUG_ERROR2("invalid operator<", _File, _Line);
    return (true);
    }

工作解决方案是这样的(再次修改,感谢Matthieu M留下的评论。)

// overloaded comparision operators
friend bool operator<(const nodeRecord & record1, const nodeRecord & record2){
    // we need to deal with strings of different lengths...
    if(record1.comparator.length() > record2.comparator.length()
        && (record1.comparator.length() !=0 && record2.comparator.length() != 0))
        return false;
    else if(record1.comparator.length() < record2.comparator.length()
        && (record1.comparator.length() !=0 && record2.comparator.length() != 0))
        return true;
    else
        return (record1.comparator < record2.comparator);
}

感谢所有提供帮助的人!

Found the following code segment which was throwing the error, then thought about how my overloaded operation was working.

template<class _Ty1, class _Ty2> inline
    bool _Debug_lt(_Ty1& _Left, _Ty2& _Right,
        _Dbfile_t _File, _Dbline_t _Line)
    {   // test if _Left < _Right and operator< is strict weak ordering
    if (!(_Left < _Right))
        return (false);
    else if (_Right < _Left)
        _DEBUG_ERROR2("invalid operator<", _File, _Line);
    return (true);
    }

Working solution is this (modified again thanks to comments left by Matthieu M.)

// overloaded comparision operators
friend bool operator<(const nodeRecord & record1, const nodeRecord & record2){
    // we need to deal with strings of different lengths...
    if(record1.comparator.length() > record2.comparator.length()
        && (record1.comparator.length() !=0 && record2.comparator.length() != 0))
        return false;
    else if(record1.comparator.length() < record2.comparator.length()
        && (record1.comparator.length() !=0 && record2.comparator.length() != 0))
        return true;
    else
        return (record1.comparator < record2.comparator);
}

Thanks to everyone who helped!

女中豪杰 2024-11-10 02:25:04

为什么不使用单个比较器并使该功能更智能一点呢?让它在开头检查数字字符,如果是,则执行一对 strtol()atoi() 并比较结果。

否则,根据您的非数字要求比较字符串和字符的长度。

Why don't you use a single comparator and make that function a little smarter? Have it check for numeric characters at the beginning, if so, do a pair of strtol() or atoi() and compare the results.

Otherwise compare the length of string and the characters as per your non-numeric requirements.

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