|
Is there a way to use CSV files within a tile game? |
Ryan Rees-Williams
Member #13,825
December 2011
|
[SOLVED] I.E. a level file could be something like: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 0,0,0,1,1,1,1,1,1,1,1,0,0,0,9 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 1,1,1,1,1,0,0,0,0,1,1,1,1,1,9 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 1,1,1,1,1,1,1,1,1,1,1,1,1,1,9 ones indicating a solid surface, zeros indication nothing and nines indicating the end of a line. Are there any libraries capable of handling a CSV file that anyone could point me in the direction of? Thanks! |
CursedTyrant
Member #7,080
April 2006
|
Eh? Why not just read the file directly and store the tile value in a Tile class object (or even a 2D integer array if you want something really simple)? I hear Mappy is quite good. It even generates C++ code IIRC. --------- |
Ryan Rees-Williams
Member #13,825
December 2011
|
Not quite what I'm after, I've tried using fstream.h (the standard file handling header for C++) with a CSV file and it will simply not work, it even BSOD'd me once which is a clear indication to me that it's not designed to work with CSV files (unless I'm doing something very wrong) |
CursedTyrant
Member #7,080
April 2006
|
If it's a .csv file saved in some other program, I suppose you would have to know the exact file format info to know how to handle said file. Failing that, there is nothing preventing you from just using .txt files containing comma separated tile values like in the first post. If all you want is to use a text editor and have data in a CSV-like format, there is no reason not to use a .txt file if it's the easier alternative, especially while using a monospaced type font in your text editor of choice. --------- |
gnolam
Member #2,030
March 2002
|
CursedTyrant: CSV is plain text. Containing comma-separated values. The extension does not matter. Ryan Rees-Williams said: I've tried using fstream.h (the standard file handling header for C++) with a CSV file and it will simply not work, it even BSOD'd me once which is a clear indication to me that it's not designed to work with CSV files
That... makes no sense whatsoever, I'm afraid. First off, file streams simply read/write data. File formats do not concern them - that's for you to handle. -- |
Ryan Rees-Williams
Member #13,825
December 2011
|
guess the BSOD was just a coincidence then, I know Windows 7 is not a crash prone OS so I'll have to look into that. and trust fstream.h to understand how the information is to be read differently? |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Ryan Rees-Williams said: I've tried using fstream.h (the standard file handling header for C++) with a CSV file and it will simply not work, it even BSOD'd me once which is a clear indication to me that it's not designed to work with CSV files (unless I'm doing something very wrong) You're doing something very wrong. fstream will NEVER, I repeat NEVER give you a BSOD. Something else is causing that. Your best bet is to use std::string::getline(istream& is) and then create a vector of values (or use an array is the size is predetermined) by using sscanf on the c_str(). Example : 1std::vector<std::vector<int> > ReadCSV(const char* csvfile) {
2 std::ifstream in(csvfile);
3 if (!in) {throw -1;}
4 string line;
5 int value;
6 int charcount = 0;
7 int n = 0;
8 int nitems = 0;
9 std::vector<std::vector<int> > map;
10 while (!in.eof()) {
11 std::vector<int> row;
12 line.getline(in);
13 const char* cstr = line.c_str();
14 charcount = 0;
15 while (charcount < line.size()) {
16 nitems = sscanf(cstr , "%i%n" , &value , &n);
17 if (nitems != 1) {throw -2;}
18 row.push_back(value);
19 cstr += n + 1;// number of characters in the number + 1 to skip the comma;
20 charcount += n + 1;
21 }
22 map.push_back(row);
23 }
24 return map;
25}
Use : vector<vector<int> > map; try { map = ReadCSV("map.txt"); } catch (int i) { cout << "Error " << i << " occurred during ReadCSV." << endl; return -1; }
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Ryan Rees-Williams
Member #13,825
December 2011
|
wow that just threw me right off, I have absolutely no idea what's going on in that code, is there any chance you could break down what's there at all? for example, I see your returning 'map', should I be using this as an int function? |
james_lohr
Member #1,947
February 2002
|
I don't understand how you could have a nearly complete game but be incapable of parsing a CSV using regular C/C++.
|
Ryan Rees-Williams
Member #13,825
December 2011
|
so far I've been hard coding the levels in my games I know, I'm a naughty and messy programmer hangs head in shame |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Ryan Rees-Williams said: wow that just threw me right off, I have absolutely no idea what's going on in that code, is there any chance you could break down what's there at all? for example, I see your returning 'map', should I be using this as an int function? Well, since you asked : 1// The ReadCSV function takes a file name string and returns a vector of integer vectors
2std::vector<std::vector<int> > ReadCSV(const char* csvfile) {
3 std::ifstream in(csvfile);// create our input file stream
4 if (!in) {throw -1;}// test to make sure the stream is working
5 string line;// for reading each line in the file
6 int value;// for storing each integer read from the string
7 int charcount = 0;// to keep track of how many characters have been read
8 int n = 0;// temp variable storing how many characters were read this time
9 int nitems = 0;// number of items successfully read by sscanf
10 std::vector<std::vector<int> > map;// declare our vector of integer vectors
11 while (!in.eof()) {// while not at the end of the input file stream
12 std::vector<int> row;// create an empty vector of integers
13 line.getline(in);// read a line from the input stream into the string
14 const char* cstr = line.c_str();// get access to the c string
15 charcount = 0;// reset character count to 0
16 while (charcount < line.size()) {// while we're not past the end of the string
17 nitems = sscanf(cstr , "%i%n" , &value , &n);// scan an integer and record the number of characters read
18 if (nitems != 1) {throw -2;}// if we didn't read one integer, we failed
19 row.push_back(value);// add the integer to the vector
20 cstr += n + 1;// number of characters in the number + 1 to skip the comma;// advance the char pointer by n + 1 chars
21 charcount += n + 1;// increase the character count by n + 1
22 }
23 map.push_back(row);// add the vector of integers to our map vector
24 }
25 return map;// return the vector of integer vectors
26}
Quote: Should I be using this as an int function? Your question suggests you don't know what a return type is, or you don't know what a vector is. The function returns a 2d array of integers stored in vectors, and you access it with [] notation. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
bamccaig
Member #7,536
July 2006
|
Ryan Rees-Williams said:
0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 0,0,0,1,1,1,1,1,1,1,1,0,0,0,9 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 1,1,1,1,1,0,0,0,0,1,1,1,1,1,9 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 1,1,1,1,1,1,1,1,1,1,1,1,1,1,9 ones indicating a solid surface, zeros indication nothing and nines indicating the end of a line. Levels generally don't have "lines" (at least, not in the sense of a newline..). Additionally, the file already has newlines, so I see no need for the special meaning given to the '9'. I also don't really see much need for the commas. You might need the commas if you're going to have enough tiles to require more than one digit per tile (i.e., 0-9 as a single digit is obviously only 10 tiles). If instead you use a single printable ASCII character per tile, for example, then that's 95 tiles. I think that there are relatively few tile-based games that require more than 95 tiles for a single level. That is easier to parse because each character is either a tile, or a control character (e.g., newline to trigger the y coordinate incrementing). It's easy to read and write in plain text, meaning that you can easily edit the levels with a plain text editor. I think I made a similar suggestion here that you may or may not find useful. If you do opt to use a delimited list then you might still prefer not to call them CSV files. There are many 'standards' for CSV files and you may get people trying to use incompatible formats with your software if you call them CSV files. For example, sometimes the data fields are quoted, sometimes quoting is optional, sometimes white-space (outside of quotes) is ignored, etc. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
CursedTyrant
Member #7,080
April 2006
|
gnolam said: CursedTyrant: CSV is plain text. Containing comma-separated values. The extension does not matter. I thought MS Excel saved CVS files a little bit differently, with some sort of additional data, but I guess not . I suppose that wouldn't make any sense. --------- |
torhu
Member #2,727
September 2002
|
Ryan Rees-Williams said: Are there any libraries capable of handling a CSV file that anyone could point me in the direction of? Thanks! C++ makes it easy to read whitespace-separated values, you could just replace the commas with spaces or tabs. Here's roughly how to do it:
Add some error checking and a test for when you should exit the loop, and you're good to go |
Ryan Rees-Williams
Member #13,825
December 2011
|
Thanks for the replies guys, I'm going to have a go at using white space instead of commas and try out the getline() function that torhu suggested and give csv reading a go once I'm back at college (seems just a tad complicated for someone with my level of experience right now), thanks again |
torhu
Member #2,727
September 2002
|
By the way, if you just need one (or a fixed number of) character(s) per tile, it would be easier to do what bamccaig suggested. Your data would then look like this: 00000000000000 00011111111000 00000000000000 11111000011111 00000000000000 11111111111111 You could read one line at a time with getline, check that the length is correct, that all values are valid, etc. But you wouldn't need to parse it using istringstream or anything else, you can just use the values directly. |
Ryan Rees-Williams
Member #13,825
December 2011
|
Thanks, I'm learning getline from the links you posted although I'm running into brick walls, I feel I'm so close to reading a line but I just can't seem to get rid of one error without causing another 1
2#include <iostream>
3#include <fstream>
4
5using namespace std;
6
7int main()
8{
9 ofstream out_stream;
10 ifstream in_stream;
11
12 int coord[100][100], currentx, currenty, numtiles, line;
13
14 in_stream.open("test.txt");
15
16 getline(in_stream,line);
17 cout << line;
18
19 in_stream.close();
20
21 /*cout << coord[0][0] << " ";
22 cout << coord[1][0] << " ";
23 cout << coord[2][0] << " ";
24 cout << coord[3][0] << " ";
25 cout << coord[4][0] << " ";
26 cout << coord[5][0] << endl;
27 cout << coord[0][1] << " ";
28 cout << coord[1][1] << " ";
29 cout << coord[2][1] << " ";
30 cout << coord[3][1] << " ";
31 cout << coord[4][1] << " ";
32 cout << coord[5][1] << endl;
33 cout << coord[0][2] << " ";
34 cout << coord[1][2] << " ";
35 cout << coord[2][2] << " ";
36 cout << coord[3][2] << " ";
37 cout << coord[4][2] << " ";
38 cout << coord[5][2] << endl;*/
39}
I'm possibly making more silly "noob" mistakes again that will be a very conspicuous and obvious error to you |
gnolam
Member #2,030
March 2002
|
Ryan Rees-Williams said: I have searched solutions for it online but everybody else seems to be using strings instead of integers Exactly. Therefore, the error is..? You're passing an integer where the function expects a string reference.
-- |
Ryan Rees-Williams
Member #13,825
December 2011
|
Right, I changed it to a string and it's reading from the file just fine now as the number is a string will I have to convert them to integers for them to work with mathematical stuff like if statements to determine which tile is what kind? |
Specter Phoenix
Member #1,425
July 2001
|
Ryan Rees-Williams said: what an array actually means. What do you mean? Single arrays are just lists and 2D+ are tables (the higher the dimensions the more tables in tables you have).
|
Ryan Rees-Williams
Member #13,825
December 2011
|
yes but to somebody learning a new bit of C++ that will mean nothing but nonsense, people learning can't just have a load of technical terms thrown at them and be expected to know how they work without explaining what each term is and how the interact with code, books I find are very bad at this An update on what my code is like right now: 1#include <iostream>
2#include <fstream>
3#include <sstream>
4
5using namespace std;
6
7int main()
8{
9 ofstream out_stream;
10 ifstream in_stream;
11
12 int coord[1][1], currentx, currenty, numtiles, howtall;
13 string stuff[3], gettall;
14
15 in_stream.open("test.txt");
16
17 getline(in_stream,gettall);
18 stringstream convert(gettall);
19 if (!(convert >> howtall))
20 {
21 howtall = 0;
22 }
23
24 getline(in_stream,stuff[0]);
25 getline(in_stream,stuff[1]);
26 getline(in_stream,stuff[2]);
27
28 cout << howtall << endl;
29 cout << stuff[0] << endl;
30 cout << stuff[1] << endl;
31 cout << stuff[2] << endl;
32
33 in_stream.close();
34}
Reading from the file is now fine, and I am able to convert the first variable (the one that determines how high the level is), finally some progress has been made ^^ now ill have a go at converting the other lines to integers and separating each number to different variables |
CursedTyrant
Member #7,080
April 2006
|
Ryan Rees-Williams said: yes but to somebody learning a new bit of C++ that will mean nothing but nonsense, people learning can't just have a load of technical terms thrown at them and be expected to know how they work without explaining what each term is and how the interact with code, books I find are very bad at this Why not look it up, then? http://cplusplus.com/doc/tutorial/arrays/ Also, you can find almost anything you want to know about C++ on those two sites, and most of it is explained clearly: --------- |
Ryan Rees-Williams
Member #13,825
December 2011
|
I meant that as a generalisation, and by going into websites I am no longer learning form a book, and it's very unlikely that a book will have links to a website, it could have been any kind of term I used but my point is books are terrible for teaching completely new people C++ as they are full of technical mumbo jumbo. Anyway this has gone a bit off-topic, lets bring it back onto rails for a bit yes? |
Specter Phoenix
Member #1,425
July 2001
|
Ryan Rees-Williams said: yes but to somebody learning a new bit of C++ that will mean nothing but nonsense, people learning can't just have a load of technical terms thrown at them and be expected to know how they work without explaining what each term is and how the interact with code, books I find are very bad at this What? Arrays is an easy concept compared to the rest of the concepts in C++. If your books didn't explain that clear enough you need to start investing money in a Computer Science course book (pricey but worth it). Computer programming is technical. Most technical terms are self explanatory, and those that aren't normally are defined. Most books introduce the terminology in early chapters and build on it while using them throughout the book they stay in your head. What books are you reading? I've read and own tons of books and the ones I have read have never just thrown technical terms in without explaining them. Lastly, like CursedTyrant pointed out, if you run into a term you don't know then ask or look it up online to get an understanding of it. Actually, term really isn't the proper word, array is more a feature that goes with a concept (lists and tables, data tables, etc). Ryan Rees-Williams said: Anyway this has gone a bit off-topic, lets bring it back onto rails for a bit yes? After you have been here a while you will realize we seldom stay on topic in any thread .
|
torhu
Member #2,727
September 2002
|
Ryan Rees-Williams said: now ill have a go at converting the other lines to integers and separating each number to different variables You don't really need to do that. This will work: if (stuff[linenum][tilenum] == '1') cout << "it's a one!\n"; else if (stuff[linenum][tilenum] == '0') cout << "it's a zero!\n"; Each element in a string is a value of type char, which you can compare to a character literal. |
|
|