C++,映射插入&&文件流读取导致麻烦



我有这部分代码(包含可能未优化)

#include <iostream>
#include <string>
#include <map>
#include <list>
#include <vector>
#include <fstream>
using namespace std;
class CTurist {
string name;
int age;
public:
CTurist(string name, int age) {
this->name = name;
this->age = age;
}
CTurist() {}
int GetAge() const { return age; }
bool operator< (CTurist& right) {
return this->age < right.age && this->name < right.name;
}
friend fstream& operator>>(fstream& is, CTurist& turist) {
is >> turist.name >> turist.age;
return is;
}
friend fstream& operator<<(fstream& os, const CTurist& turist) {
os << turist.name << "t" << turist.age;
return os;
}
};
class CHotel {
string name;
int rating;
int bedsCount;
map<CTurist, unsigned> mmap; //<Turist, dni prestoi>
public:
CHotel(string name, int rating, int bedsCount, fstream stream) {
this->name = name;
this->rating = rating;
this->bedsCount = bedsCount;
//read stream
}
CHotel(string name, int rating, int bedsCount) {
this->name = name;
this->rating = rating;
this->bedsCount = bedsCount;
}
CHotel() {}
void addRecord(pair<CTurist, unsigned> record) {
mmap.insert(record);
}
int GetCountTuristsInHotel() {
int count = 0;
for (map<CTurist, unsigned>::iterator it = mmap.begin(); it != mmap.end(); it++)
count += it->second;
return count;
}
CTurist GetMaxStayTurist() {
map<CTurist, unsigned>::iterator max = mmap.begin();
for (map<CTurist, unsigned>::iterator it = mmap.begin(); it != mmap.end(); it++)
if (it->second > max->second)
max = it;
return max->first;
}
float DaysToBedsRatio() {
float busyDaysCount = 0.0;
for (map<CTurist, unsigned>::iterator it = mmap.begin(); it != mmap.end(); it++)
busyDaysCount += it->second;
return busyDaysCount / bedsCount;
}
float AverageAge() {
float sumAge = 0.0;
for (map<CTurist, unsigned>::iterator it = mmap.begin(); it != mmap.end(); it++)
sumAge += (it->first).GetAge();
return sumAge / mmap.size();
}
list<CTurist> GetTuristByAge(int age) {
list<CTurist> llist;
for (map<CTurist, unsigned>::iterator it = mmap.begin(); it != mmap.end(); it++)
if (it->first.GetAge() == age)
llist.push_back(it->first);
return llist;
}
int GetTuristCountYongerThan(int age) {
int count = 0;
for (map<CTurist, unsigned>::iterator it = mmap.begin(); it != mmap.end(); it++)
if (it->first.GetAge() < age)
count++;
return count;
}
int GetTuristCountOlderThan(int age) {
int count = 0;
for (map<CTurist, unsigned>::iterator it = mmap.begin(); it != mmap.end(); it++)
if (it->first.GetAge() > age)
count++;
return count;
}
CTurist TheYongestTurist() {
CTurist turist = mmap.begin()->first;
for (map<CTurist, unsigned>::iterator it = mmap.begin(); it != mmap.end(); it++)
if (it->first.GetAge() < turist.GetAge())
turist = it->first;
return turist;
}
bool operator< (CHotel right) {
return this->rating < right.rating && this->bedsCount < right.bedsCount;
}
friend fstream& operator>> (fstream& is, CHotel& hotel) {
int count, n;
CTurist turist;
is >> hotel.name >> count;
for (int i = 0; i < count; i++) {
is >> turist >> n;
hotel.mmap.insert(pair<CTurist, unsigned>(turist, n));
}
is >> n;    //reading the new line
return is;
}
friend fstream& operator<<(fstream& os, CHotel& hotel) {
os << hotel.name << "t" << hotel.mmap.size();
for (map<CTurist, unsigned>::iterator it = hotel.mmap.begin(); it != hotel.mmap.end(); it++) {
os << it->first << endl;
os << it->second << endl;
}
os << endl;
return os;
}
};
class CComplex {
string name;
vector<CHotel> hotels;
public:
CComplex(string name, string filePath) {
fstream file;
file.open(filePath, ios::in);
if (!file) {
cout << "Unable to open file for reading..n";
exit(3);
}
this->name = name;
CHotel hotel;
while (!file.eof()) {
file >> hotel;
hotels.push_back(hotel);
}
}
CComplex() {
}
CHotel TheBusiestOne() {
CHotel busiest = *hotels.begin();
float ratio = busiest.DaysToBedsRatio();
for (vector<CHotel>::iterator it = hotels.begin(); it != hotels.end(); it++)
if (it->DaysToBedsRatio() > ratio) {
busiest = *it;
ratio = busiest.DaysToBedsRatio();
}
return busiest;
}
float RatioOfAllHotels() {
float sum = 0;
for (vector<CHotel>::iterator it = hotels.begin(); it != hotels.end(); it++)
sum += it->DaysToBedsRatio();
return sum / hotels.size();
}
int TuristsOlderThan(int age) {
int count = 0;
for (vector<CHotel>::iterator it = hotels.begin(); it != hotels.end(); it++)
count += it->GetTuristCountOlderThan(age);
return count;
}
CHotel YongestAverageTurists() {
CHotel hotel = *hotels.begin();
for (vector<CHotel>::iterator it = hotels.begin(); it != hotels.end(); it++)
if (it->AverageAge() < hotel.AverageAge())
hotel = *it;
return hotel;
}
CTurist TheYongestTurist() {
CTurist turist = hotels.begin()->TheYongestTurist();
for (vector<CHotel>::iterator it = hotels.begin(); it != hotels.end(); it++)
if (it->TheYongestTurist().GetAge() < turist.GetAge())
turist = it->TheYongestTurist();
return turist;
}
void WriteToFile(string filePath) {
fstream file;
file.open(filePath, ios::out);
if (!file) {
cout << "Unable to open file for writing..n";
exit(3);
}
file << name << "t" << hotels.size();
for (vector<CHotel>::iterator it = hotels.begin(); it != hotels.end(); it++)
file << *it << endl;
file.close();
}
void addHotel(CHotel hotel) {
hotels.push_back(hotel);
}
friend fstream& operator<<(fstream& ostream, CComplex complex) {
ostream << complex.name << "t" << complex.hotels.size();
for (vector<CHotel>::iterator it = complex.hotels.begin(); it != complex.hotels.end(); it++)
ostream << *it << endl;
return ostream;
}
};
int main()
{
CComplex ccomplex;
CHotel hotel("Echolandia", 5, 100);
//Name          Years       Nights
hotel.addRecord(pair<CTurist, unsigned>(CTurist("Echo", 23), 20));
hotel.addRecord(pair<CTurist, unsigned>(CTurist("Kristiyan", 25), 30));
ccomplex.addHotel(hotel);
hotel = CHotel("newHotelValey", 3, 20);
//Name          Years       Nights
hotel.addRecord(pair<CTurist, unsigned>(CTurist("Echo1", 12), 20));
hotel.addRecord(pair<CTurist, unsigned>(CTurist("Kristiyan1", 15), 30));
hotel.addRecord(pair<CTurist, unsigned>(CTurist("Kristiyan2", 30), 30));
ccomplex.addHotel(hotel);
fstream file;
file.open("test.txt", ios::out);
file << ccomplex;
}

问题是,如果我在 CHotel 中注释这两个函数,则没有编译错误,但是如果我得到其中一个,它会给出。

Severity    Code    Description Project File    Line    Suppression State
Error   C2678   binary '<': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)    C++_project32   c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includexstddef 141 

是我做错了什么吗,如果是的话,到底是什么?我希望如果您看到一些不好的做法,您也会添加它:] 谢谢!

编辑#1: 我按照建议上传了完整的代码<并在运算符上添加了重载>。 似乎我必须提供这个输出窗口

1>------ Build started: Project: C++_Stelio_Kursova, Configuration: Debug Win32 ------
1>Source.cpp
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includexstddef(141): error C2678: binary '<': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)
1>        with
1>        [
1>            _Ty=CTurist
1>        ]
1>c:usersechosourcereposc++_stelio_kursovac++_stelio_kursovasource.cpp(24): note: could be 'bool CTurist::operator <(CTurist &)'
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includesystem_error(319): note: or       'bool std::operator <(const std::error_condition &,const std::error_condition &) noexcept'
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includesystem_error(312): note: or       'bool std::operator <(const std::error_code &,const std::error_code &) noexcept'
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includexstddef(141): note: while trying to match the argument list '(const _Ty, const _Ty)'
1>        with
1>        [
1>            _Ty=CTurist
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includexstddef(140): note: while compiling class template member function 'bool std::less<_Kty>::operator ()(const _Ty &,const _Ty &) const'
1>        with
1>        [
1>            _Kty=CTurist,
1>            _Ty=CTurist
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includexutility(1110): note: see reference to function template instantiation 'bool std::less<_Kty>::operator ()(const _Ty &,const _Ty &) const' being compiled
1>        with
1>        [
1>            _Kty=CTurist,
1>            _Ty=CTurist
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includexutility(264): note: see reference to class template instantiation 'std::less<_Kty>' being compiled
1>        with
1>        [
1>            _Kty=CTurist
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includexutility(264): note: see reference to variable template 'const bool is_empty_v<std::less<CTurist> >' being compiled
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includextree(1032): note: see reference to class template instantiation 'std::_Tree_comp_alloc<_Traits>' being compiled
1>        with
1>        [
1>            _Traits=std::_Tmap_traits<CTurist,unsigned int,std::less<CTurist>,std::allocator<std::pair<const CTurist,unsigned int>>,false>
1>        ]
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.16.27023includemap(82): note: see reference to class template instantiation 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>' being compiled
1>        with
1>        [
1>            _Kty=CTurist,
1>            _Ty=unsigned int,
1>            _Pr=std::less<CTurist>,
1>            _Alloc=std::allocator<std::pair<const CTurist,unsigned int>>
1>        ]
1>c:usersechosourcereposc++_stelio_kursovac++_stelio_kursovasource.cpp(43): note: see reference to class template instantiation 'std::map<CTurist,unsigned int,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' being compiled
1>        with
1>        [
1>            _Kty=CTurist,
1>            _Ty=unsigned int
1>        ]
1>Done building project "C++_Stelio_Kursova.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

std::map是一个有序容器,其顺序基于映射的键。要使订单存在,必须为密钥类型定义operator<。(这是一个简化,但现在已经足够好了)。

您做错了什么,就是没有为CTurist定义一个operator<,而是在将CTurist用作地图的键时隐式使用它。

显而易见的事情是使用像std::unordered_map这样的无序容器,但它有自己的要求,或者为您的CTurist类定义operator<,大概基于游客的姓名和年龄。

你如何定义operator<并不重要,例如,顺序是升序还是降序,或者在排序时是否首先考虑年龄或名称并不重要,只要您的operator<为任何不相等的CTurist实例定义了一致的顺序。

良好的实践,

1) 通过常量引用传递字符串和其他大型对象

2) 在构造函数中更喜欢初始化而不是赋值

所以

CHotel(const string& n, int r, int bc) : 
name(n), rating(r), bedsCount(bc)
{
}

但总体来说还不错。

最新更新