c++ input from a file.

Started by
10 comments, last by crazykid48x 18 years, 5 months ago
Im making a textbased game that loads information about the different room objects from a file. Theres an area class and the constructor does all the loading. Heres what I got so far. I basicly loads the name, description and position of each room. class constructor:

area::area()
{
      ifstream room("rooms.txt");
      room.seekg(pos);
      room.getline(roomname, 20);
      room.getline(description, 1000);
      for(int i=0; i<2; i++)
          room>>position;
      pos=room.tellg();
      room.close();
}

Text file:

The Hallway
Everyones room is on this hallway. The numbers on the doors go from 200 to 300.
1 1
The lobby
The lobby has gold tiles and a ceilling atleast 30 feet high. There are beutiful gold paterns along the walls and the ceilling. There is a desk with a receptionist north of you and an elevator to the west. To the east theres a dining area and to the south, the exit.
1 2
the Dining hall
The Dining hall has gold pattern walls just like the lobby but instead of tiles it has red carpet. Theres rows of round tables at witch to eat, All properly set. The bar is to the east, and the pool is to the south. To the west is the lobby. 
1 3
The Bar
The Bar follows the look of the other rooms. There are lots of colorful lights above the bar. Behind the bar is a large array of bottles. To the north is the bartender, To the west is the Dining hall.
1 4
The Outside
Outside of the hotel theres two valley parkers in red uniforms. If you look up you can see all the windows to the rooms on your floor. To the north is the Lobby.
2 2
The Pool
The Pool is a great place to relax. The shimmering water is soothing. To the north is the Dining Hall.
2 3

Pos is a global variable, atfirst set to 0. Its used to keep track of where to load from. I think somehow its the problem. the problem is the beginnig of the room names get cut off. (sory if this was a simple problem and i didnt have to give so much info).
Advertisement
seekg and tellg can be unreliable with text mode files under Operating Systems which use multiple characters to represent a newline (like Windows). This is because the number of characters read can be different to the number of bytes read. Since it seems likely that all the area will be constructed one after the other you could just delegate the file opening to a higher level function and pass the ifstream to the constructor:
void loadAreas(){	ifstream roomsData("rooms.txt");	something = area(roomsData);	// ...}area::area(ifstream & data){	data.getline(roomname, 20);	// ...}

Actually, I'd make a further suggestion than that, since it seems you are using the dreaded char * to represent text in C++. Replace your evil char *'s with std::strings and change data.getline(x, y); to getline(data, x);.

Enigma
Thats exactly what I was going to do, but I had trouble making an array of objects that had constructor arguments. Could you please show me how your function would work to make alot of room objects?
Probably something like:
std::vector< area > rooms;void loadAreas(){	ifstream roomsData("rooms.txt");	while (!roomsData.eof())	{		rooms.push_back(area(roomsData));	}}

Enigma
Hrm... where exactly are you getting 'pos' from now? It looks as though you're keeping it stored in a global, so that you can re-open and re-close the file for each object construction.

Constructing from a stream object would indeed be cleaner (no reopening or reclosing needed; just re-pass the same stream each time, as it has already 'advanced' to the right position). But yes, you don't really get to declare arrays of non-default-constructed objects in C++ - a rather annoying language limitation.

In your case, the solution I would propose is not to load into an array anyway, but instead into a std::vector. That will also free you from having to know (or somehow indicate) how many rooms are indicated in the file.

Something like:

std::vector<area> rooms;std::ifstream data("rooms.txt");while (!data.eof()) {  rooms.push_back(area(data));}
Snap! [lol]

Enigma
ah crap, I was trieng to aviod using vectors. Ive always thought they were gonna be complicated because they werent covered in my 4 dummies book but it looks simple enough. thanks for the help everyone.
I left and read through a vector tutorial and then got back to work. But now im getting the oddest error Ive ever seen! here I'll post the whole source (dont wory it isnt much!)

#include <iostream>#include <cstdio>#include <cstdlib>#include <fstream>#include <vector>using namespace std;class area{      private:              bool firstvisit;              char roomname[20];              char description[1000];      public:              int position[2];              area(ifstream& room);              int DisplayArea();};area::area(ifstream& room){      //cout<<"error";      room.getline(roomname, 20);      room.getline(description, 1000);      for(int i=0; i<2; i++)          room>>position;      //cout<<roomname;}int area::DisplayArea(){    cout<<roomname<<endl<<endl<<description<<endl;    for(int i=0; i<2; i++)        cout<<position;    cout<<endl<<endl;}int main(){    vector<area> map;    ifstream room("rooms.txt");    while(!room.eof())       map.push_back(area(room));    room.close();    for(int i=0; i<map.size(); i++)       map.DisplayArea();    getchar();    return 0;}  


At first I wasnt getting any output. Then I placed cout statements in the constructer and thats where it gets odd. If you un comment the first cout (cout<<"error") you will se the effects of an infinate loop. but If you recomment that and un comment the 2nd cout statement (cout<<roomname) It will only apear once. And also when i tried getline(room, roomname); it gave me an error. (no matching function for call to `getline(std::basic_ifstream<char, std::char_traits<char> >&, char[20])')

I didnt think making a text based game would be so hard. And im just now getting started.

[Edited by - crazykid48x on November 11, 2005 9:37:00 PM]
Quote:Original post by crazykid48x
I didnt think making a text based game would be so hard. And im just now getting started.

The problem is that text processing is not one of C++'s greatest strengths. It may sound unintuitive, but you'd probably obtain faster and more stable results if you either build a chunk-based binary format (each chunk stores its own length in bytes and you drop newlines entirely) or use a paired key-value format a la .ini files.
That sounds alittle too advanced.

This topic is closed to new replies.

Advertisement