I have data files with extra empty lines in them at the end. This is causing problems with reading in the data lines. I'm using:
while (datFile.good())
but .eof() didn't work either.
Any suggestions?
while (datFile.good())
{
getline (datFile, line);
istringstream liness(line);
int z = 0;
while (z <= index)
{
while (liness >> temp)
{
if (z == 0)
{
values[0].push_back(atof(temp.c_str()));
}
if (z == index)
{
values[1].push_back(atof(temp.c_str()));
}
cout << temp << endl;
z++;
}
}
}
Thou shalt use the stream's status after thy read!
You didn't post enough code to tell but input always looks something like this:
while (in >> data) {
process(data);
}
Whether you use formatted input or unformatted input diesn't matter either. Also, good() is generally not that useful aabd eof() is only useful to suppress an error message: if you read failed it may be OK that it failed because you read all the data. It is never a useful condition to determine whether a read was successful: eof() can yield true although the read was successful.
while (getline (datFile, line))
{
istringstream liness(line);
// the rest of the loop is unchanged.
...
}
Related
So I have written a program that runs as intended when taking input from a file, but throws a "runtime exceeded" error (I'm using onlinegdb). The input in both cases is separated like so:
```
input
```
I copied this into a text file and it worked, but entering the input as standard input at the bottom of the screen does not work. I can also input to console, which also works fine. My readFromFile function is the same function but with file I/O functions instead of cin. This is my first time really experimenting with input/output. Please help!!
void readFromInput() {
string Word;
int count = 0;
while (cin >> Word) {
if (Word == "```") {
count++;
}
if (count == 2) {break;} //exit after recieving opening and closing ```
if (Word == "Add") {
//do stuff
}
if (Word == "Charge") {
//do stuff
}
if (Word == "Credit") {
//do stuff
}
}
return;
}
There are a couple of special features of the standard input/output that don't apply to normal file streams:
The C++ std::cin and std::cout is linked to the C streams by default. To keep these in sync is expensive. If you are not using C streams this is not necessary. To remove this cost unlink them:
int main()
{
std::ios::sync_with_stdio(false);
}
If your code uses input and output streams. Reading from std::cin forces std::cout to be flushed (to make sure user questions reflect the input question). This can be inefficient if the two are not linked. So untie them,
int main()
{
std::cin.tie(nullptr);
}
Prefer to use '\n' over std::endl to avoid extra flushes.
int main()
{
if (cin)
{
(...)
}
else
{
cerr << "No Data!!!" << endl;
}
}
I want to check if the input has any data, but the error message won't be displayed even if I only input Ctrl+Z at the beginning.
Before you attempted to read, the stream won't know whether there is any useful data. At the very least you'll need to look at the first character, e.g., using
if (std::cin.peek() != std::char_traits<char>::eof()) {
// do something with the potentially present input.
}
else {
// fail
}
More likely you'll depend on some non-space data to be available. If so, you could see if there is something other than space in the file:
if (!(std::cin >> std::ws).eof())
...
The manipulator std::ws will skip leading whitespace. It will stop when either a non-whitespace character or the end of file is reached. If the end of file is reached, std::cin.eof() will be true.
In general, I wouldn't bother but rather try to read the first item. If nothing at all is read it would still be viable to fail:
bool hasData = false;
while (std::cin >> some >> data) {
hasData = true;
// do something with the input
}
if (!hasData) {
// report that there was no data at all
}
The no data case may be implicitly testable, e.g., by looking at the size of a read data structure.
After inputting getline, the first row of numbers in my input file are ignored and the program starts at the second line until the end.
Here's the code:
while (!file.eof())
{
getline(file, lineBuffer);
if(lineBuffer.length()==0)
{
continue; //ignore empty lines
}
else
{
// file.open("test.txt");
while (file >> A >> B >> N)
{
for(int count=1; count<=N; count++)
{
if(count%A == 0 && count%B == 0) { cout << "FB "; }
else if(count%A == 0) { cout << "F "; }
else if(count%B == 0) { cout << "B "; }
else { cout << count << " "; }
}
cout << endl;
}
}
}
The input file contains 3 rows of integers and only the second line and third like are processed. I've looked this up extensively, but no one has mentioned a case similar to mine. Usually they deal with people trying to get user input after a getline function. Any ideas would be greatly appreciated.
getline(file, lineBuffer) reads a line from file and stores it in lineBuffer. If you want to use it, you should then process lineBuffer instead of reading from file (where the first line will already be skipped). To make it work, simply remove all code outside of the inner while. This will read from the file 3 numbers at a time, stopping when extracting one of them fails.
Is the above code real or is it an example?
If it is real, you don't need to skip th eempty lines. The operator>> will skip the whitespaces for you.
The following code without any lineskipping performs just the same reading of "A B N" lines:
// outer loop is not needed, either remove it, or include error checking
// while (!file.eof() && !file.fail())
{
while (file >> A >> B >> N)
{
for(int count=1; count<=N; count++)
{
if(count%A == 0 && count%B == 0) { cout << "FB "; }
....
If for some reason you cannot remove the getline at all, remember that getline reads the line ALWAYS (well, unless the streampointer reached its end). This means that your code skips the empty lines, then reads first nonempty line, notices that the line is not empty and breaks the loop. Note that it has read the line, hence, your first-line-of-data now is in the linebuffer, and not in the stream anymore. Now you have to either unget the whole line (if your stream supports it) or rewind the stream by the line's length (if your stream supports it) or - just read the data from the line - for example using istringstream class.
In general, mixing getline and operator>> is doable but tricky, (especially when you first read via >> and then want to skip a 1 or 2 lines), as they behave a little differently in terms of buffering and whitespace-handling. If you really want that, search for this subject - there are lots of examples how to sync them.
I am creating a program (In C++) that takes an ASCII file and reads a few values from each line until it reaches the end of the file. I am using ifstream to read the file, and I have never had problems with it stopping when I use the ifstream.eof() method. This time, however, even though it found the eof character in my test case, when I analyzed my other files, it is infinite looping because it never finds the eof character. Is this a coding issue, or an issue with my files?
string line = "";
unsigned long pos = 0;
ifstream curfile(input.c_str());
getline(curfile, line);
int linenumber = 0;
cout<<"About to try to read the file"<<endl;
if (!curfile.good())
cout<<"Bad file read"<<endl;
while (!curfile.eof())
{
cout<<"Getting line "<<linenumber<<endl;
linenumber++;
pos = line.find_first_of(' ');
line = line.substr(pos+1, line.size()-1);
pos = line.find_first_of(' ');
current.push_back(atof(line.substr(0, pos).c_str()));
for (int i = 0; i<4; i++)
{
pos = line.find_first_of(' ');
line = line.substr(pos+1, line.size()-1);
}
pos = line.find_first_of(' ');
dx.push_back(atof(line.substr(0, pos).c_str()));
pos = line.find_first_of(' ');
line = line.substr(pos+1, line.size()-1);
pos = line.find_first_of(' ');
dy.push_back(atof(line.substr(0, pos).c_str()));
getline(curfile, line);
}
EDIT: When I first run the loop, currentfile.good() returns false...what am I doing that causes it to return that?
First thing is first, you shouldn't check like that. eof() doesn't return true until after a failed read. But you can do better (and easier)!
check the stream state with the implicit conversion to void* which can be used in a bool context. Since most of the read operations on streams return a reference to the stream, you can write some very consice code like this:
std::string line;
while(std::getline(currentfile, line)) {
// process line
}
Basically what it is doing is saying "while I could successfully extract a line from currentfile, do the following", which is what you really meant to say anyway ;-);
Like I said, this applies to most stream operations, so you can do things like this:
int x;
std::string y;
if(std::cin >> x >> y) {
// successfully read an integer and a string from cin!
}
EDIT: The way I would rewrite your code is like this:
string line;
unsigned long pos = 0;
int linenumber = 0;
ifstream curfile(input.c_str());
std::cout << "About to try to read the file" << std::endl;
while (std::getline(curfile, line)) {
std::cout << "Getting line " << linenumber << std::endl;
linenumber++;
// do the rest of the work with line
}
Do not do it like that.
EOF is not the only thing you'll encounter while reading. There's a bunch of errors you might get, and so the best is to simply test the stream itself:
while(currentfile)
{
// read somehow
}
If you're reading lines, then, the simplest way is:
std::string line;
while(std::getline(currentfile, line))
{
// use line
}
Your first call to getline is triggering one of the fail-bits on the ifstream object. That is why if you do a check for a fail-bit using ios::good(), you never enter your read loop. I would check to see what the value of line is ... it's probably empty, meaning you're having another issue reading your file, like maybe permissions problems, etc.
The problem is here:
if (!curfile.good())
cout<<"Bad file read"<<endl; // OK you print bad.
while (!curfile.eof()) // But the loop is still entered.
// Another reason to **NEVER** to use
// while (file.eof()) // as bad does not mean eof
// though eof is bad
Try this:
void readFile(std::istream& str)
{
std::string line;
while(std::getline(str, line))
{
std::stringstream lineStream(line);
std::string ignoreWord;
int number[3];
lineStream >> ignoreWord // reads one space seporated word
>> number[0] // reads a number
>> ignoreWord >> ignoreWord >> ignoreWords // reads three words
>> number[1] // reads a number
>> number[2]; // reads a number
current.push_back(number[0]);
dx.push_back(number[1]);
dy.push_back(number[2]);
}
}
I am reading a std::istream and I need to verify without extracting characters that:
The stream is not "empty", i.e. that trying to read a char will not result in an fail state (solved by using peek() member function and checking fail state, then setting back to original state)
That among the characters left there is at least one which is not a space, a tab or a newline char.
The reason for this is, is that I am reading text files containing say one int per line, and sometimes there may be extra spaces / new-lines at the end of the file and this causes issues when I try get back the data from the file to a vector of int.
A peek(int n) would probably do what I need but I am stuck with its implementation.
I know I could just read istream like:
while (myInt << myIstream) {…} //Will fail when I am at the end
but the same check would fail for a number of different conditions (say I have something which is not an int on some line) and being able to differentiate between the two reading errors (unexpected thing, nothing left) would help me to write more robust code, as I could write:
while (something_left(myIstream)) {
myInt << myIstream;
if (myStream.fail()) {…} //Horrible things happened
}
Thank you!
There is a function called ws which eats whitespace. Perhaps you could call that after each read. If that hits eof, then you know you've got a normal termination. If it doesn't and the next read doesn't produce a valid int, then you know you've got garbage in your file. Maybe something like:
#include <fstream>
#include <iostream>
int main()
{
std::ifstream infile("test.dat");
while (infile)
{
int i;
infile >> i;
if (!infile.fail())
std::cout << i << '\n';
else
std::cout << "garbage\n";
ws(infile);
}
}
this is what I did to skip whitespace/detect EOF before the actual input:
char c;
if (!(cin >> c)) //skip whitespace
return false; // EOF or other error
cin.unget();
This is independent of what data you are going to read.
This code relies on the skipws manipulator being set by default for standard streams, but it can be set manually cin >> skipw >> c;
And simple
for(;;){
if(!(myIstream >> myInt)){
if(myIstream.eof()) {
//end of file
}else{
//not an integer
}
}
// Do something with myInt
}
does not work? Why you need to know if there are numbers left?
Edit Changed to Ben's proposition.
The usual way to handle this situation is not to avoid reading from the stream, but to put back characters, which have been read, if needed:
int get_int(std::istream& in)
{
int n = 0;
while(true) {
if (in >> n)
return n;
clean_input(in);
}
}
void clean_input(std::istream& in)
{
if (in.fail()) {
in.clear();
// throw away (skip) pending characters in input
// which are non-digits
char ch;
while (in >> ch) {
if (isdigit(ch)) {
// stuff digit back into the stream
in.unget();
return;
}
}
}
error("No input"); // eof or bad
}