为什么不止一个元素没有插入一组结构中?

Why is more than one element not inserting in a set of structures?

我想将多个结构对象插入到一个集合中,但只有一个元素被插入到集合中。我做错了什么?

struct Productions {
    char LHS;
    string RHS;
    bool operator<(const Productions& t) const { 
        return (this->LHS < t.LHS); 
    } 
};

int main() {

    int NoP;
    cout<<"Enter No. of Productions: ";
    cin>>NoP;
    set<Productions> old_prod;
    Productions prod;
    for(int i=0; i<NoP; i++) {
        cout<<"Enter Production No. "<<i+1<<":"<<endl;
        cout<<"LHS: ";
        cin>>prod.LHS;
        cout<<"RHS: ";
        cin>>prod.RHS;
        old_prod.insert(prod);
    }

    cout<<old_prod.size()<<endl;
    for(auto it=old_prod.begin(); it!=old_prod.end(); it++) {
        cout<<it->LHS<<"->"<<it->RHS<<endl;
    }
}

输出是这样的: terminal snippet.

我也试过:

int main() {

    int NoP;
    cout<<"Enter No. of Productions: ";
    cin>>NoP;
    set<Productions> old_prod;
    for(int i=0; i<NoP; i++) {
        cout<<"Enter Production No. "<<i+1<<":"<<endl;
        Productions *prod = new Productions; 
        cout<<"LHS: ";
        cin>>prod->LHS;
        cout<<"RHS: ";
        cin>>prod->RHS;
        old_prod.insert(*prod);
    }

    cout<<old_prod.size()<<endl;
    for(auto it=old_prod.begin(); it!=old_prod.end(); it++) {
        cout<<it->LHS<<"->"<<it->RHS<<endl;
    }
}

但输出保持不变。我错过了什么?

如果您插入的元素具有相同的 LHS,根据您的运算符<,它们被认为是等价的,并且一个集合只存储等价元素的一个实例。

来自 cppreference:

std::set is an associative container that contains a sorted set of unique objects of type Key.

如果集合中已经存在等效元素,则通过简单地不插入元素来确保唯一性。请参阅 insert:

上的文档

Inserts element(s) into the container, if the container doesn't already contain an element with an equivalent key.

如果 a<bb<a 的计算结果都不为真,则 ab 这两个元素被认为是等价的。注意,等价并不一定意味着相等,即a == b。当您仅比较 operator< 中的 LHS 时,具有相同 LHS 的两个条目被认为是等效的(请参阅 here 以了解标准中的相关引用)。您可以让等价元素相等,但是您还需要在运算符中比较 RHS

不清楚你为什么选择一套,因为上面的属性基本上就是让一套成为一套的原因。也许您想改用 std::vector 。或者,您可以将您的操作员也修改为 comapre RHS

您正在为数据成员输入相同的值 char LHS;。并且元素在集合中根据这个数据成员排序

bool operator<(const Productions& t) const { 
    return (this->LHS < t.LHS); 
} 

所以除了集合中的第一个输入外,所有其他输入都将被忽略。

对数据成员使用不同的值 LHS

或者按照下面的方式重新定义比较运算符

bool operator<(const Productions& t) const { 
    return this->LHS < t.LHS && this->RHS < t.RHS; 
} 

或者如果要使用元组则写

bool operator<(const Productions& t) const { 
    return std::tie( this->LHS, this->RHS ) < std::tie( t.LHS, t.RHS ); 
} 

在这种情况下,您必须包括 header <tuple>

这是一个演示程序

#include <iostream>
#include <string>
#include <tuple>
#include <set>

using namespace std;

struct Productions {
    char LHS;
    string RHS;
    bool operator<(const Productions& t) const { 
        return std::tie( this->LHS, this->RHS ) < std::tie( t.LHS, t.RHS ); 
    } 
};

int main() {

    int NoP;
    cout<<"Enter No. of Productions: ";
    cin>>NoP;
    set<Productions> old_prod;
    Productions prod;
    for(int i=0; i<NoP; i++) {
        cout<<"Enter Production No. "<<i+1<<":"<<endl;
        cout<<"LHS: ";
        cin>>prod.LHS;
        cout<<"RHS: ";
        cin>>prod.RHS;
        old_prod.insert(prod);
    }

    cout<<old_prod.size()<<endl;
    for(auto it=old_prod.begin(); it!=old_prod.end(); it++) {
        cout<<it->LHS<<"->"<<it->RHS<<endl;
    }
}

它的输出可能看起来像

Enter No. of Productions: 3
Enter Production No. 1:
LHS: S
RHS: aSa
Enter Production No. 2:
LHS: S
RHS: bSb
Enter Production No. 3:
LHS: S
RHS: c
3
S->aSa
S->bSb
S->c

另一种方法是使用 std::multiset 而不是 std::set 如果您想要键的重复值。

例如

#include <iostream>
#include <string>
#include <set>

using namespace std;

struct Productions {
    char LHS;
    string RHS;
    bool operator<(const Productions& t) const { 
        return (this->LHS < t.LHS); 
    } 
};

int main() {

    int NoP;
    cout<<"Enter No. of Productions: ";
    cin>>NoP;
    multiset<Productions> old_prod;
    Productions prod;
    for(int i=0; i<NoP; i++) {
        cout<<"Enter Production No. "<<i+1<<":"<<endl;
        cout<<"LHS: ";
        cin>>prod.LHS;
        cout<<"RHS: ";
        cin>>prod.RHS;
        old_prod.insert(prod);
    }

    cout<<old_prod.size()<<endl;
    for(auto it=old_prod.begin(); it!=old_prod.end(); it++) {
        cout<<it->LHS<<"->"<<it->RHS<<endl;
    }
}