Read info from a txt file into a class

Hello, I'm having trouble in getting my program to read from a file and put all the proper data into its proper class variables. I have a class (called Champion) that has string variable for a name and a vector of strings for items. I also have a vector of Champion that holds multiple champions. Any help would be appreciated. Here's my code:

Champion.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef CHAMPION_HPP_INCLUDED
#define CHAMPION_HPP_INCLUDED

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Champion
{
    private:
        string name;
        vector<string> items;
    public:
        Champion();
        Champion(string name);
        void addItems();
        void editItem();
        string getItem(int item_num);
        int numOfItems();
        string getName();
        ~Champion();
};

ostream &operator <<(ostream &stream, Champion &c); //function to print out all class data
//istream &operator >>(istream &stream, Champion &c);   //not needed so far

#endif // CHAMPION_HPP_INCLUDED


Champion.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <iostream>
#include <string>
#include <vector>

#include "Champion.hpp"

using namespace std;

Champion::Champion()
{
    this->name = "";
}

Champion::Champion(string name)
{
    this->name = name;
}

void Champion::addItems()
{
    string item;

    cout << "item 1: ";
    getline(cin, item);
    items.push_back(item);

    cout << "item 2: ";
    getline(cin, item);
    items.push_back(item);

    cout << "item 3: ";
    getline(cin, item);
    items.push_back(item);

    cout << "item 4: ";
    getline(cin, item);
    items.push_back(item);

    cout << "item 5: ";
    getline(cin, item);
    items.push_back(item);

    cout << "item 6: ";
    getline(cin, item);
    items.push_back(item);
}

void Champion::editItem()
{
    int item_num;
    string item;
    //vector<string>::iterator it;
    cout << "Which item do you want to change? ";
    cin >> item_num;
    bool item_set = false;
    while(!item_set)
    {
        switch(item_num)
        {
            //make sure its a proper item slot
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
                cout << "Enter new item name: ";
                cin.ignore();
                getline(cin, item);
                this->items[item_num - 1] = item; //set new item
                item_set = true;
                break;
            default:
                cout << "Invalid number.  Try again." << endl;
                break;
        }
    }
}

string Champion::getItem(int item_num)
{
    return this->items[item_num];
}

int Champion::numOfItems()
{
    return this->items.size();
}

string Champion::getName()
{
    return this->name;
}

Champion::~Champion()
{

}

ostream &operator <<(ostream &stream, Champion &c)
{
    stream << c.getName();
    stream << endl;
    for(int i = 0; i < c.numOfItems(); i++)
    {
        stream << c.getItem(i);
        stream << endl;
    }
    return stream;
    /*stream << c.getItem(1);
    return stream;*/ //test
}


main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <iostream>
#include <string>
#include <vector>
#include <fstream>

#include "Champion.hpp"

using namespace std;

enum {ADD_CHAMPION = 1, EDIT_ITEM = 2, PRINT_LIST = 3, SAVE = 4, LOAD = 5, HELP = 6, QUIT = 7};

int main()
{
    vector<Champion> champions;
    int option;
    string name;
    cout << "Select an option: ";
    cin >> option;
    while(option != QUIT)
    {
        switch(option)
        {
            case ADD_CHAMPION:
                {
                    cout << "Enter champion name: ";
                    cin >> name;
                    int i;
                    for(i = 0; i < (int)champions.size(); i++)
                    {
                        if(champions[i].getName() == name)
                        {
                            cout << "Champion already exist." << endl;
                            break;
                        }
                    }
                    if(i == (int)champions.size())
                    {
                        Champion a(name);
                        cin.ignore();   //ignores name so addItems() would not add it
                        a.addItems();
                        champions.push_back(a);
                    }
                    break;
                }
            case EDIT_ITEM:
                {
                    cout << "Enter champion name: ";
                    cin >> name;
                    for(int i = 0; i < (int)champions.size(); i++)
                    {
                        if(champions[i].getName() == name)
                        {
                            champions[i].editItem();
                            break;
                        }
                    }
                }
                break;
            case PRINT_LIST:
                {
                    for(int i = 0; i < (int)champions.size(); i++)
                    {
                        cout << champions[i] << endl;
                    }
                    break;
                }
            case SAVE:
                {
                    ofstream ofs;
                    ofs.open("LoL.txt", ios::trunc);    //overwrite old file
                    if(ofs.is_open())
                    {
                        for(int i = 0; i < (int) champions.size(); i++)
                        {
                            ofs << champions[i] << endl;
                        }
                        ofs << endl;
                        ofs.close();
                    }
                    else
                    {
                        cout << "Fail to open file." << endl;
                    }
                    break;
                }
            case LOAD:
                {
                    ifstream ifs;
                    string line;
                    ifs.open("LoL.txt");
                    if(ifs.is_open())
                    {
                        while(getline(ifs, line))
                        {
                            //stuck here on how to add input into proper variables in class Champion
                        }
                        ifs.close();
                    }
                    else
                    {
                        cout << "Fail to open file." << endl;
                    }
                    break;
                }
            case HELP:
            default:
                {
                    cout << "Invalid option." << endl;
                    break;
                }
        }
        cout << "Select an option: ";
        cin >> option;
    }

    return 0;
}
In looking at your save routine, the problem I see is that you don't write a delimiter between each champion (or a count of how many items each champion has). This makes it impossible to determine where one champion's data ends and the next one starts.

Lines 94-96: You want to read the champion's name first, then you want to loop reading that champion's items until you either encounter a delimiter, or reach the number of items that champion has.

I would suggest adding at line 103 of champion.cpp:
 
   stream << c.numOfItems() << endl;

Then on load, after reading the champion's name, read the number of items from the file, then loop reading items for that number of times.
Last edited on
Ok, that will work. Thank you :)
I should have suggested this before.

You have already overloaded the << operator to write a champion to an output stream. Why not overload the >> operator to read a champion from an input stream.

Lines 93-97 become simply:
93
94
95
96
    Champion  champ;  // temp instance used for reading
    while (ifs >> champ)
        champions.push_back (champ); 
    ifs.close();


This encapsulates the code for reading a champion into it's class where it belongs. This does not address the delimiter/count issue, but it isolates it to code in your class. If you decide to add additional variables to champion, only your input and output overloads needs to change.
Topic archived. No new replies allowed.