0

I am trying to write a "text adventure" engine that runs off of text and data files. I understand the concepts of arrays and multidimensional arrays, but know they cause memory leaks and not re-sizable. Therefor I have decided to use vectors and vectors of vectors (or multidimensional vectors). I have a data file that holds at current time 52 lines, each line has 10 integers separated by a space. (for this board) I cut the data file down to 3 lines. I'm having a terrible time reading the data into a multi-d vector. My question is what am I doing wrong? Thank you in advance for any insights.

#include <iostream>
#include <vector>
#include <fstream>

using namespace std;



int main()
{
vector<vector <int> > rooms;
vector <int> locations;

ifstream openfile("rooms.dat");
 if (openfile.is_open()){
    while (!openfile.eof()){
            int temproom; openfile >> temproom;
    locations.push_back(temproom);
    }

    rooms.push_back(locations);
    locations.clear();
}
    for (int y=0;y<3;y++){
            for ( int i=0; i<9; i++){
                cout << rooms [y][ i ] << " , " ;
                }
                cout << rooms[y][9] << "\n" << endl;
                }

    return 0;
}

I have a data file that looks like:

23,6,4,8,2,12,6,3,2,6
65,34,22,65,34,23,11,5,3,3
3,12,21,4,9,5,2,7,43,22
Just Earl
  • 21
  • 4
  • Have a look at this answer: http://stackoverflow.com/a/22338539/396551 – Sjoerd Jan 30 '15 at 03:28
  • Use space instead of ',' for number separation in file. Also, `rooms.push_back(...)` seems to be called exactly once, not thrice. – Chintan Jan 30 '15 at 03:32
  • [`while (!openfile.eof())`](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) - don't do that. – WhozCraig Jan 30 '15 at 04:35

1 Answers1

0

Let me take you through how I would do this.

Note that I didn't try to optimize anything at all. Writing easy to understand code is much more important than optimization. Besides, the current compilers are very good at optimizing this code (using NRVO).

First some typedefs for the types involved. It makes it so much easier to read and write the code:

typedef std::vector<int> Locations;
struct Room
{
  Locations locations; // Apparently, a room has only locations (or should that be exits?) and nothing else.
};
typedef std::vector<Room> Rooms;

Then some high-level pseude-code:

Open File
Read File into 'rooms'
Print 'rooms'

Which, in this case, translates easily into a short main:

int main()
{
    std::ifstream openfile("rooms.dat");
    Rooms rooms = readRooms(openfile);
    printRooms(rooms);

    return EXIT_SUCCESS;
}

How do I implement readRooms()? We start with pseudo-code again:

For each line in the file:
    Read the room on this line

The easiest way to process a file line by line, is reading a full line with std::getline(). Otherwise one risks skipping the newlines by accident. To easy parsing this line, let's create a stringstream from it, so we can use the usual way to parse the line.

Note that readRooms() accept a std::istream, which is more generic than a std::ifstream. When you do this, the function can be used with e.g. std::stringstream as well.

Rooms readRooms(std::istream& is)
{
    Rooms allRooms;
    std::string line;
    while (std::getline(is, line))
    {
       std::stringstream lineStream(line)
       Room newRoom = readRoom(lineStream);
       allRooms.push_back(newRoom);
    }
    return allRooms;
}

Now reading a single room. Pseudo-code:

for each location on the line:
    add the location to the room

In code:

Room readRoom(std::istream& is)
{
     Room newRoom;
     int location;
     while (is >> location)
     {
         newRoom.Locations.push_back(location);

         // It would be easier if the locations are separated by whitespace only.
         char shouldBeComma;
         is >> std::ws >> shouldBeComma;
     }
     return newRoom;
}

Wow, we're already finished with reading our rooms!


You should be able to write code to print the rooms yourself. In case you have C++11, it would be very easy:

void printRooms(const Rooms& rooms)
{
    for (const Room& room : rooms)
    {
        printRoom(room);
    }
}

and so on...

Sjoerd
  • 6,534
  • 27
  • 44