C ++,映射插入&&文件流读取引起麻烦

时间:2019-04-01 21:59:59

标签: c++ dictionary fstream

我已经掌握了这部分代码(可能未对包含的内容进行优化)

#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 studio\2017\community\vc\tools\msvc\14.16.27023\include\xstddef 141 

是我做错了什么,如果是,那到底是什么?我希望如果您发现一些不好的做法,也可以添加它:] 谢谢!

编辑#1: 我上传了完整的代码,并按建议在运算符<上添加了重载。 好像我必须提供此输出窗口

1>------ Build started: Project: C++_Stelio_Kursova, Configuration: Debug Win32 ------
1>Source.cpp
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\xstddef(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:\users\echo\source\repos\c++_stelio_kursova\c++_stelio_kursova\source.cpp(24): note: could be 'bool CTurist::operator <(CTurist &)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\system_error(319): note: or       'bool std::operator <(const std::error_condition &,const std::error_condition &) noexcept'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\system_error(312): note: or       'bool std::operator <(const std::error_code &,const std::error_code &) noexcept'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\xstddef(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 studio\2017\community\vc\tools\msvc\14.16.27023\include\xstddef(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 studio\2017\community\vc\tools\msvc\14.16.27023\include\xutility(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 studio\2017\community\vc\tools\msvc\14.16.27023\include\xutility(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 studio\2017\community\vc\tools\msvc\14.16.27023\include\xutility(264): note: see reference to variable template 'const bool is_empty_v<std::less<CTurist> >' being compiled
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\xtree(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 studio\2017\community\vc\tools\msvc\14.16.27023\include\map(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:\users\echo\source\repos\c++_stelio_kursova\c++_stelio_kursova\source.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 ==========

1 个答案:

答案 0 :(得分:1)

std::map是一个有序容器,其顺序基于地图的键。对于存在的订单,必须为密钥类型定义一个operator<。 (这只是一种简化,但目前已经足够了。)

您做错了什么是没有为operator<定义CTurist,但是当您将CTurist用作地图键时隐式使用了它。

最明显的做法是使用std::unordered_map之类的无序容器,但这有其自身的要求,或者为您的operator<类定义CTurist ,大概是根据游客的姓名和年龄。

如何定义operator<并不重要,例如,顺序是升序还是降序,订购时是否先考虑年龄或名字都没有关系,只要您operator<为所有不相等的CTurist实例定义一致的顺序。

良好实践

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

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

所以

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

但总体上还不错。