Importing int multi-array from .txt

I am currently working on a big game project, a platform game that uses a tilebased system to load the maps. But the text to load all the (currently) 40*160 tiles is quite large and it's annoying to scroll down. I am also planning on having more maps (I only got 1 currently) and possibly larger maps.

I was thinking that if I write the tiles to a .txt file instead and then use a function to load the tiles from that file. But I got problem with how to load the integers one by one.

I feel like a beginner and that I have taken water above my head. But I still managed to create the platform game (using allegro library), but now I am just confused I got no code that I have tried because I don't know where to start or how to think.

I use a program that writes the tiles (not made by me) they look like this when I load them:
0, 1, 2, 3,
4, 4, 4, 4,
2, 1, 3, 0,

and then I have to add all those {}
{0, 1, 2, 3},
{4, 4, 4, 4},
{2, 1, 3, 0}}:

Now I have searched for a few way of loading from a file, and then how to convert from string to an int. But I am really confused how I take the precise number without the ", " and saving them into my "double-array". I only know a way to save the whole "getline".

I guess it looks just about this way:
*string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( myfile.eof() )
{
getline (myfile,line); //(loads 0, 1, 2, 3)


cout << line << endl;

/*convert the string to numbers and save to myInt[i][x], (i is the row and x should increase per each number (it could be good if it is also possible to store numbers with more then 1 digits, ex 13.*/
i++
}
myfile.close();
}

else cout << "Unable to open file";
One way is to treat ',' as white space. Then you can just read the values as normal.

For example:
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
#include <string>
#include <sstream>
#include <fstream>
#include <locale>
#include <vector>

// From:
// http://groups.google.com/group/alt.comp.lang.learn.c-c++/msg/db55ffea728c5cf9?dmode=source
class local_ctype : public std::ctype<char>
{
	// VC++ 7 doesn't make table_size a const, so we use UCHAR_MAX+1
	// instead -- this is kind of a hack, but works well enough for now.
	mask m_table[UCHAR_MAX+1];
public:
	local_ctype(const char* delimiters, size_t refs = 0)
		:	std::ctype<char>(m_table, false, refs)
	{
		// copy the original character classification table.
		std::copy(classic_table(), classic_table() + table_size, m_table);

		// specify white space chars.
		for (const char* p = delimiters; *p; ++p)
			m_table[*p] = (mask)space;
	}
};

struct Row
{
	std::vector<int> values;
};

int main()
{
	std::vector<Row> rows;

	std::locale custom_whitespace(std::locale::classic(), new local_ctype("{},"));
	std::ifstream infile("example.txt");
	infile.imbue(custom_whitespace);

	std::string line;
	while (std::getline(infile, line))
	{
		Row row;
		int value;
		std::istringstream instr(line);
		while (instr >> value)
			row.values.push_back(value);

		rows.push_back(row);
	}

	return 0;
}
Last edited on
I got no idea what those std::vector, struct Row does.

To be honest I don't think I understand most of it. I think it's mostly because I have 0 to very little experience with loading from files. (I've only used it once where I stored a string and then loading the stored string. I could then delete those strings via a linked list system. If I remember correctly)

I have also pretty little experience with string types.

Is there a way where you only load each row as a string, and then afterwards splitting it up into int variables and then storing them in the array?
A vector is a dynamicly sized array: http://www.cplusplus.com/reference/stl/vector/

The top part of the page explains it pretty well but I didn't understand it until I tried to use it in code.

EDIT: If you have used linked lists then vectors will feel like a Birthday present.

Is there a way where you only load each row as a string, and then afterwards splitting it up into int variables and then storing them in the array?


A string is and array, so is a vector as I mentioned above. Also yes you can do that, you would declare an array of strings, or a string type vector would be better, then load the data into the array and access each piece by the index number.
Last edited on
Hm, we learned the linked list in class. And we worked pretty linear with first using a class etc. I just remember we spend a lot of time on this.

Maybe it will be hard to learn on my own. We will see, since I am planning on continuing with this I will try to learn. Will try this tomorrow if I get time. Might take a while for another reply.

*When trying to learn things by yourself, do you got any tips in doing so?

EDIT: I took a quick look at it, and I realized I had no idea what it means with "template". Is this something I need to know more about, or can I just "write it" and then use vectors?
Last edited on
Hi Twilice I think there are two major component in your project. You have a clear idea of the first component and that is the "tile loading" conceptually. The second component is to implement in C++ code based on your first component concept.

It seem you may need to learn more on C++ in particular Standard C++ container, algorithm, iterator etc classes. It is only when you clear this hurdle can you comfortably undertake your second component.

It is the classic program design -> coding -> testing -> release cycle.

You should be at stage 2 coding.
To be honest I don't think I understand most of it.
Ok, here we go. I hope this isn't too basic.

A data stream is a sequence of bytes. These can come from memory, from disk, from a terminal, from a network interface and so on. In C++ it's common to treat file operations as streams to/from disk.

C++ provides a family of classes to deal with streams in the I/O Stream Library. The idea is you create the appropriate kind of stream, then read/write to them in a common way. The idea is a powerful one and starts with Multics, but that's another story.

So you use stringstream to deal with streams on memory, fstream to deal with streams on files, and there are a few predefined instances of streams that deal with terminals called cin, cout, cerr, clog.

So to read a number from a terminal you do:
 
    std::cin >> number;

And to read a number from a file:
1
2
    std::iftream in("data.txt");  // create file stream instance
    in >> number;

And to read a number that's in a string:
1
2
3
    std::string str = "77";  // a string with a number
    std::istringstream in(str);  // create a string stream instance
    in >> number;

Enough of that.

As you know, arrays hold sequences of things:
1
2
    std::string string_array[10];  // an array of 10 strings
    int number_array[5];  // an array of 5 ints 

But what if you don't know how many elements you need before hand? That's what std::vector is. It's like an array, but it can grow. It's like arrays because you can use [] to get to each element, and it's like array because it knows what type it is storing. So vector equivalents of the declarations above are:
1
2
    std::vector<std::string> string_vector(10);  // a vector of strings with intial size 10
    std::vector<int> int_vector(5);  // vector of int with initial size 5 

But you add to the end of a vector with push_back. For example:
 
    int_vector.push_back(3);  // add 3 to the end, int_vector now has size 6 

I'll assume you know what struct is.

If you want to read three numbers from a stream that has
 
    1  2  3  4

you can do so with:
1
2
    int n[4];
    std::cin >> n[0] >> n[1] >> n[2] >> n[3];

But what if you want to read:
 
    0, 1, 2, 3,

You have to tell the stream that the comma character as well as the space and tab characters is white space. And that's what lines 7- 25, 36, and 38 do. But I won't explain them.

The rest should be straight forward.
line 37: create an input file instance
line 41: read a line from the input file stream to a string
lines 43-47: read the values from the string into a Row, a vector of ints.
line 49: add the row you just read to a vector of rows.

At the end you're left with a 2D grid of your data that you can access as:
1
2
    rows[3][0];  // row 3, col 0
    unsigned nrows = rows.size(); // I have this many rows 

Thanks, now it's a bit easier to understand. (I will try to use it when/if I have the time)
Topic archived. No new replies allowed.