-1

I have 2 classes, I make an object from the second class (I pass the filename as an argument). It should print the contents of the file which contains the following data in the following format:

A.Yordanov 1234567819
S.Todorov 3456789120
D.Lazarov 2569789054
P.Pavlov 4329549823
M.Kalinova 2367892343
B.Georgiev 659045324

I have overloaded the << operator but I when I try to cout << cty2 nothing appears on the console even though I have put the file in the same directory?

// OOP_Homework.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <fstream>
#include <set>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
fstream f;
class CPerson {
    string name;
    string egn;
public:
    CPerson(string n, string e) {
        name = n;
        egn = e;
    }
    friend bool operator<(CPerson p1, CPerson p2) {
        if (p1.egn < p2.egn) {
            return true;
        }
        return false;
    }
    friend bool operator==(CPerson p1, CPerson p2) {
        if (p1.egn == p2.egn) {
            return true;
        }
        return false;
    }
    friend ostream& operator<< (ostream o, CPerson pn) {
        o << "Egn" << endl;
        o << pn.egn << endl;
        o << "Name:" << endl;
        o << pn.name << endl;
    }
    friend istream& operator>> (istream is, CPerson p) {
        is >> p.egn;
        is >> p.name;
        return is;
    }
    string getName() {
        return name;
    }
    string getEgn() {
        return egn;
    }
    void setName(string n) {
        name = n;
    }
    void setEgn(string e) {
        egn = e;
    }
};
class CCity {
    vector<CPerson> pr;
public:
    CCity(string fl) {
        f.open(fl, ios::out);
        string name = "", fn = "";
        while (!f.eof()) {
            //формата на данните във файла е във вида:
            //<име на студент> <факултетен номер>
            cin >> name >> fn;
            pr.push_back(CPerson(name, fn));
        }
        f.close();
    }
    //помощен getter за вектора  pr;
    vector<CPerson> getV() {
        return pr;
    }
    friend ostream& operator<<(ostream& os, CCity& psn) {
        vector<CPerson> ps = psn.getV();
        for (auto x = ps.begin(); x != ps.end(); x++) {
            os << x->getName() << endl;
            os << x->getEgn() << endl;
        }
        return os;
    }
    vector<CPerson> getDuplicate() {
        set<CPerson> temp;
        vector<CPerson> duplicates;
        for (auto i = pr.begin(); i != pr.end(); i++) {
            for (auto x : pr) {
                if (*i == x) {
                    temp.insert(*i);
                }
            }
        }
        for (auto j : temp) {
            duplicates.push_back(j);
        }
        temp.clear();
        //връщаме студентите с повтарящи се егн-та
        return duplicates;
    }
    void removeDuplicates() {
        sort(pr.begin(),pr.end());
        pr.erase(unique(pr.begin(), pr.end()));
    }
    void removeVector(vector<CPerson> ob) {
        for (auto i:ob) {
            for (auto x = pr.begin(); x != pr.end(); x++) {
                if (i == *x) {
                    pr.erase(x);
                }
            }
        }
    }
};
int main()
{
    CCity  cty2("persons.txt");
    //cout << cty1 << endl;
    cout << cty2 << endl;
    return 0;
}
TrebledJ
  • 8,713
  • 7
  • 26
  • 48
  • 1
    `while (!f.eof()) {` https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong – drescherjm Dec 04 '18 at 18:13
  • My advice (if you don't have an IDE with a good debugger like Visual Studio) add cout statements in your code to see if things worked. If you do have a debugger use it to single step through your code looking at your variables at each step. Don't just run your program in the debugger. – drescherjm Dec 04 '18 at 18:17
  • 2
    @drescherjm I'm starting to think we should have a short-cut like `[!eof]` that expands like `[mcve]` for that one. – user4581301 Dec 04 '18 at 18:29

1 Answers1

4

The code for your overload for operator<< should be

friend ostream& operator<< (ostream &o, const CPerson &pn) {
    //                              ^   ^^^^^         ^

    o << "Egn" << endl;
    o << pn.egn << endl;
    o << "Name:" << endl;
    o << pn.name << endl;

    return o;  // since return type is ostream&
}

You should be passing the stream by reference and returning it once you've finished using it. Passing by-reference ensures that the same stream is used (unlike pass-by-value).

Another thing to note would be your CPerson p function arguments. These should be passed by-reference as well. With operator<<, your CPerson won't be modified, so we can keep it as const.

You may also want to watch out your operator>>. Again, istream is should be istream &is. With the CPerson p parameter, you will modify it, so you'll definitely want to be passing it as a reference.

friend istream& operator>> (istream &is, CPerson &p) {
    //                              ^            ^

    is >> p.egn;
    is >> p.name;
    return is;
}

In your other overloads, you should be using const CPerson &p as well. Moreover, your overloads for operator< and operator== don't need to be friended since they're not accessing any other class's private members. Thus,

bool operator<(const CPerson &p1, const CPerson &p2) {
    if (p1.egn < p2.egn) {
        return true;
    }
    return false;
}

bool operator==(const CPerson &p1, const CPerson &p2) {
    if (p1.egn == p2.egn) {
        return true;
    }
    return false;
}

You'll want to get used to passing your classes by-reference as it saves space (not having to copy-construct another instance of the class as passing by-value would do). It's thus, more efficient both space-wise and performance-wise to pass your classes by reference.

TrebledJ
  • 8,713
  • 7
  • 26
  • 48