Я пытаюсь написать фрагмент кода, который позволяет пользователю вводить определенное количество имен, а затем проверяет, существуют ли в наборе объекты, содержащие эти имена. Я хочу, чтобы программа взяла имена, введенные пользователем, провела цикл через набор и посмотрела, существует ли имя в любом из элементов объекта, а затем печатайте в командной строке, существует ли это имя или нет.
По какой-то причине он печатает "Имя не существует в наборе" для каждого элемента в наборе, даже если имя существует в наборе. Как я могу проверить это правильно? Кроме того, как я могу заставить его печатать сообщение "не существует" один раз, даже если проверка завершилась несколько раз, прежде чем найти (или не найти) совпадение?
Мой код пока:
#include <iostream>
#include <set>
#include <string>
#include <cassert>
using namespace std;
class Name {
public:
Name();
Name(string n);
bool operator<(Name right)const;
string get_name()const;
private:
string name;
};
Name::Name(){}
Name::Name(string n)
{
name = n;
}
bool Name::operator<(Name right)const
{
bool result = true;
return result;
}
string Name::get_name()const
{
return "Name name is: " + name + "\n";
}
int main(){
set<Name>NamesSet;
NamesSet.insert(Name("Patrick Star"));
NamesSet.insert(Name("Jason"));
NamesSet.insert(Name("Bob Marl"));
NamesSet.insert(Name("Greg"));
set<Name>::iterator pos;
int numjobs;
string cusname;
cout << "Number of names to enter:" << endl;
cin >> numjobs;
cin.ignore();
if (numjobs != 0 || numjobs > 0) {
for (int i = 0; i != numjobs; i++)
{
cout << endl;
cout << "Name " << i+1 << ": " << endl;
getline(cin, cusname);
for (pos = NamesSet.begin(); pos != NamesSet.end(); pos++)
{
if (NamesSet.count((*pos).get_name()))
{
cout << (*pos).get_name() << " exists in set";
break;
}
else
{
cout << "Name does not exist in set";
}
}
}
}
return 0;
}
Вы должны изменить их:
bool Name::operator<(const Name& right)const
{
return (this->name < right.name);
}
string Name::get_name()const
{
return name;
}
Это будет рабочий образец:
#include <iostream>
#include <set>
#include <string>
#include <cassert>
using namespace std;
class Name {
public:
Name();
Name(string n);
bool operator<(const Name& right)const;
string get_name()const;
private:
string name;
};
Name::Name(){}
Name::Name(string n)
{
name = n;
}
bool Name::operator<(const Name& right)const
{
return (this->name < right.name);
}
string Name::get_name()const
{
return name;
}
int main()
{
set<Name>NamesSet;
NamesSet.insert(Name("Patrick Star"));
NamesSet.insert(Name("Jason"));
NamesSet.insert(Name("Bob Marl"));
NamesSet.insert(Name("Greg"));
set<Name>::iterator pos;
string cusname = "Greg";
if ( NamesSet.count(cusname) == 1 )
{
cout << cusname << " exists in set"<<endl;
}
else
{
cout<<"Nanda!";
}
return 0;
}
Ваше Name::operator<
неверно. Он всегда возвращает true
, что означает, что set
всегда будет считать, что два объекта Name
сравнивают неравные.
Вместо этого сравните строки имен, возвратив this->name < right.name
, и вы увидите правильное поведение из своего set
.
(Кстати, ваш operator<
должен принять const Name &
для эффективности).
std::set
использует operator<
для сравнения элементов. Поэтому для правильной работы требуется правильная реализация.
Ты нуждаешься в этом
bool operator< (const Name& right) {
return name < right.name;
};
Однако в этом случае вы можете напрямую использовать строку вместо имени.
Эта часть кода неверна для начинающих
for (pos = NamesSet.begin(); pos != NamesSet.end(); pos++) <-------- count does this for you
{
if (NamesSet.count((*pos).get_name())) <------ you check the whole set to see if it is in itself
{
cout << (*pos).get_name() << " exists in set";
break;
}
else
{
cout << "Name does not exist in set";
}
}
Это должно быть лучше, замените выше:
if (NamesSet.count(cusname))
{
cout << cusname << " exists in set";
break;
}
else
{
cout << "Name does not exist in set";
}
std::find
(с соответствующим оператором сравнения) илиstd::find_if
?class Name
, похоже, не делает ничего, что не делаетstd::string
. Почему бы просто не использовать вместо негоstd::string
?