Ifstream getting information from a textfile - c++

At the moment I'm trying to get to create a race track that has all of the textures on the ground loaded via a textfile. An example is this:
0, 0, 1, 1, 1, 1, 0, 0
0, 1, 0, 0, 0, 0, 1, 0
0, 0, 1, 1, 1, 1, 0, 0
The ground itself is simply a grid.
At the moment the code I have to get information from text file is as follows:
string line;
ifstream myfile ("track1.txt");
if (myfile.is_open())
{
while ( !myfile.eof() )
{
getline( myfile, line, ',');
if (line == '0')
{
const wstring textureFileName=TEXT("crate.jpg");
}
myfile>>line;
}
myfile.close();
}
When I build this code, how ever I get the following error:
binary '==' : no operator found which
takes a right-hand operand of type
Then if I change the double equals sign to a single I get the following error:
error C2451: conditional expression
of type 'std::basic_string<_Elem,_Traits,_Ax>'is illegal
'char' (or there is no acceptable
conversion)
Is there something I'm missing that is causing the error?
Sorry for my lack of proper detail.
Thank you chaosTechnician. Will the val work on multiple lines in the text file?
Like this
0 0 1 1 1 1 0 0
0 1 0 0 0 0 1 0
1 0 0 0 0 0 0 1
0 1 0 0 0 0 1 0
0 0 1 1 1 1 0 0
I mean, is there anything else I need to type to get the computer to realise the line has ended?

You're trying to compare a string to a char:
line == '0'
instead, try:
line[0] == '0'
or:
line == "0"

First, I strongly suggest using the code formatting in your post to make it easier to read...
Also, the easiest way to see if it's written correctly would be to compile it and run it. :)
If your text file is 0,0,0,0,0,0,0,0,0,0 (everything on one line), then getline(myfile, line); will read it all in with your first read--it's all on one line. Here's a link to how getline() works. If you were to use a comma as the delimeter (by passing a comma as the third argument: getline(myfile, line, ',');) it's much more likely to do what you want. But, if you want to just read each line, why put them on the same line separated with a comma when you could just put each on its own line? Is there a specific reason you're doing it that way?
Additionally, if line is a string, if(line == 0) won't check what you want it to check. You'd need to convert line to a int to compare values.
If you want to be using ifstream and the values in the file will be integers, I'd suggest something akin to this:
int val;
ifstream myfile("track1.txt");
while(myfile >> val)
{
//Use the value in here
}
Then your file can be as simple as this:
0 0 0 0 0 0 0 0 0 0
Hope this helps.

To expand on chaosTechnician answer the ifstream does not see lines.
every time you call myfile it will read the next value irrespective of its location.
that means that it would read 0 0 0 0 and
0
0
0
0
as the same thing.
the way I use it in my code is to put different data on diffident lines for example
50 //race length
0 0 0 //first square of each lane
0 1 0 //second lane and so on
but it would function exactly the same if it was
50 0 0 0 0 1 0
By knowing what order the information will be read in you can read it into variables at load time and manipulate them as the game goes on.
Good luck with your project
edit:
I use c++ an directx 9.c so this method should work for you.

If you're concerned about keeping relative spatial data (i.e., rows/columns of each 'tile') intact and you're limiting yourself to ascii files, you might as well just forgo any issues with delimiting or reading invalid input by switching to chars.
Let's say this is your file:
a6sgb1
dsj26s
l8h9h4
34gpoy
And then do do the following to parse it (after testing reading a line from std::getline() through std::stringstream, std::get(), and just plain iterating through a std::string from std::getline() on my development machine, I found the first to be fastest - your mileage may vary. I'll supply all three):
stringstream
ifstream strFile("test.txt");
string line;
int row(0);
int col(0);
while(getline(strFile, line)) {
stringstream ss(line);
char ch;
while(ss >> ch) {
switch(ch) {
// your code
}
++col;
}
++row;
}
line iteration
istream lineFile("test.txt");
string line;
int row(0);
while(getline(lineFile, line)) {
int len(line.length());
for(int col = 0; col < len; ++col) {
switch(line[col]) {
// your code
}
}
++row;
}
individual char parsing
ifstream chFile("test.txt");
char ch;
int row(0);
int col(0);
while(chFile.get(ch)) {
switch(ch) {
case '\n':
++row;
break;
// your code
}
++col;
}
Someone else mentioned questions like this should probably be on stackoverflow, I agree.

Related

How to read character by character from a file to a 2D array

I'm trying to read character from a text file that looks like this. The '-' are supposed to be converted to zeros and the 'x' are supposed to be converted to ones
3
3
-x-
xx-
--x
I'm able to read the first two integers using a seperate function but when I use this method to copy it over I get a 3x6 2d array with all zeros. the output is
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
To read character by character from a file, you have some options.
Character by character
char c;
ifstream data_file("my_file.txt");
while (data_file >> c)
{
Do_Something_With_Character(c);
}
By text line
From your input data example, you may want to read text line instead:
std::string text;
ifstream data_file("my_file.txt")
while (getline(data_file, text))
{
for (int index = 0; index < text.length(); ++i)
{
Do_Something_With_Character(text[index]);
}
}
Note: The above examples are generic for reading data. They do not parse the OP's input file.

C++ Converting a text file list with numbers and words into an integer 2D array

I have a basic text file which has one entry per line, most entries are are numerical, however there are a few lines with the word and (evenly spaced) in them. Here is an example of one such spacing between and :
<event>
4
0
0.1005960E+03
0.2722592E+03
0.7546771E-02
0.1099994E+00
21
-1
0
0
501
502
0.00000000000E+00
0.00000000000E+00
0.17700026409E+03
0.17700026409E+03
0.00000000000E+00
0.
-1.
21
-1
0
0
502
503
0.00000000000E+00
0.00000000000E+00
-0.45779372796E+03
0.45779372796E+03
0.00000000000E+00
0.
1.
6
1
1
2
501
0
-0.13244216743E+03
-0.16326397666E+03
-0.47746002227E+02
0.27641406353E+03
0.17300000000E+03
0.
-1.
-6
1
1
2
0
503
0.13244216743E+03
0.16326397666E+03
-0.23304746164E+03
0.35837992852E+03
0.17300000000E+03
0.
1.
</event>
What I need to do is create a numerical matrix (using only the numerical values) where each column holds all the data values between each separate instance of and .
This is what I have so far:
using namespace std;
int main()
{
vector <string> data;
string str;
ifstream fin("final_small.txt");
while (fin >> str)
{
data.push_back(str);
}
fin.close(); // Close the file.
int N = data.size();
int matrix[13][19];
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 19; j++) {
matrix[i][j] = data[i];
}
}
}
Obviously this is a huge work in progress. First of all, I read the text file in to a vector, which can not be of type int because of the words. This then causes problems later on when I try to input it into the matrix.
Does anyone have any suggestions?
Thanks in advance!
In C++11, use std::stoi to convert a string to an int. Note that std::stoi will throw an exception of type std::invalid_argument if the conversion cannot be performed.
Could you give some example inputs? What you could do is iterate through each line and only convert characters that are numbers. You can check this with the stdlib function isdigit() which you can see here. You can then use atoi() for numerical conversion. Hope this helps!

Re-setting an istringstream object

When I run this code:
for (int i = 0; i < indexArray.size(); i++) {
iss.str(indexArray.at(i));
iss>>one;
iss>>two;
iss>>three;
cout<<one<<" "<<two<<" "<<" "<<three<<" "<<"\n";
}
the istreamstream (iss) remains the same with every iteration. (The file is read into an vector at the beginning of the program. Yes, I checked to make sure the array had the corresponding data.)
In other words, I get this output:
12345 1 0
12345 1 0
12345 1 0
whereas the file/vector actually says:
12345 1 0
12346 1 25
12543 1 50
I've tried various traces and can't pinpoint the problem. Thanks!
You should call iss.clear(); before iss.str(indexArray.at(i)); to clear the EOF flag when reusing istringstream.

read line with different length backwards c++

I have a text file that I need to read data from, and these data will go into various arrays later. The text file looks like:
1 5.154600E-05 1.329887E-02 1.907202E-03 3 -1 8937 8889 1 0 890 1532 1533
2 4.639140E-03 9.845286E-03 1.659781E-02 1 9708 0 0 1617
3 1.329887E-02 1.329887E-02 1.108239E-02 4 8497 5442 0 5711 0 1 1611 1619 889 1618
4 1.030920E-04 5.154600E-05 1.412360E-02 3 -1 6966 6965 1 0 888 1620 1330
5 6.030882E-03 6.546342E-03 1.030920E-04 2 8238 6002 0 0 1622 1621
6 9.484464E-03 5.154600E-05 4.072134E-03 2 6104 5455 0 0 2481 1112
1st, I need to take out specific column (in this case 5th column). The size of lines are not equal, and I couldn't break reading after catching 5th column. cin.ignore didn't help.
2nd, 5th column is always an integer, say N, and then (maybe in a separate function) I need to read the LAST N number of same line and store them into arrays. I have no clue how to do it.
Here is part of code:
while (!myfile.eof())
{
// myfile.ignore (50, '\n'); // This is just a try. 5th col. always ends at 50th charachter of line. It didn't work!
double a,b,c,d,e;
myfile >> a >> b >> c >> d >> e;
if (minsize>e)
minsize=e;
if (maxsize<e)
maxsize=e;
frequency2[int(e)]++;
}
Any help ?
You could use std::getline to get the whole line in each iteration, and then use std::istringstream to parse out the columns. Something like this:
std::string buffer;
std::getline(myfile, buffer);
std::istringstream iss(buffer);
// Do your stuff
double a, b, c, d, e;
iss >> a >> b >> c >> d >> e;
I'd recomming you using a string with some reversed size like 60 bytes.
Then read char by char. If the char is a White space/Line break and the string size > 0 you should handle the data in the string and clear the data in the string. If the size == 0 you should continue.
void handle(std::string& data)
{
if(data.size())
{
//Handle Input
data.clear();
}
}
std::string buf(60);
while(file.isgood())
{
char c = file.get();
if(!file.isgood())
break;
switch(c)
{
case '\n':
case ' '://Probably you need more cases here just debug to find out
handle(buf);
break;
default:
buf.push_back(c);
break;
}
}
To complete others solutions:
getline is the good way to read a file line by line
you could use (boost) tokenizer to build an iterable from the line
you could use (boost) lexical cast to parse data from this iterable
something like
while(file.good())
{
string line;
getline(file, line);
if(line.empty())
continue;
boost::tokenizer<> tok(line);
boost::tokenizer<>::iterator tokiter = tok.begin();
double ex1 = boost::lexical_cast<double>(*tokiter);
tokiter++;
float ex2 = boost::lexical_cast<float>(*tokiter);
//etc..
cout << ex1 << " " << ex2 << endl;
}
http://www.boost.org/doc/libs/1_55_0b1/libs/tokenizer/tokenizer.html
http://www.boost.org/doc/libs/1_55_0/doc/html/boost_lexical_cast.html

How to input a character and then output a number sequence dependent on value of char?

so I'm trying to write a program that would take an input character between 0 and 127 and then output a string of numbers in the following form:
- If I input a 0, the output should be a 0
- If I input a 5, the output should be 012345
- If I input a 9, the output should be 0123456789
- If I input a 14, the output should be 012345678901234
- If I input a 27, the output should be 0123456789012345678901234567
So, I'm looking for increments of 10 characters from 0 to 9 at most and then repeat the sequence until the last number is reached. So in 27, there's actually 28 characters output due to the first 0, but the last one is still a 7.
I know I want to use for loops, but I'm having a bit of a trouble figuring out how to make this happen. I can probably use the the ASCII 48 through 57 for the output, but my problem is how I make the input work... should I static cast it to an integer and then work with that? I'm kind of hitting a wall here.
Try the following:
#include <iostream>
int main() {
char input;
std::cin >> input;
if (input >= 0 && input <= 127) {
for (int i = 0; i <= n; i++) std::cout << i % 10;
}
}