I'm having a bit of an issue with a while loop in a program I'm working on. I am attempting to use a while-eof loop to read float numbers from and input file and simply rewrite those files to a created output file. My issue is that the while loop is missing the last value all the time. The test file I'm using has 4 numbers in it but it will only output the first 3 to the output file.

#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;

int main()
{
    float value;
    
    
    
    
    ifstream infile;
    ofstream outfile;
    
    infile.open("tax.dat");
    if (infile.fail())
       {
            cout << "The input file cannot be located" << endl;
            exit(1);
       }
       
    outfile.open("test.out", ios::out);
    if (outfile.fail())
       {
            cout << "The output file could not be created" << endl;
            exit(1);
       }   

    infile >> value;
    while (!infile.eof())
    {
          

          outfile << value;
          outfile << endl;
          infile >> value;
    }
    
    infile.close();
    outfile.close();
    system("pause");
    return 0;
}
infile >> value;
    while (!infile.eof())
    {
          

          outfile << value;
          outfile << endl;
          infile >> value;
    }

You have infile >> reading one number per trip per the loop, plus once at the top. If you have this file:

7.8
7.6
8.9

how many trips through the loop should you have? 2.

7.8 is read BEFORE the loop. 7.6 and 8.9 are read inside the loop. You write to the output file once per trip through the loop. Hence you should write two numbers with this program.

Interestingly enough you can "solve" your problem by sticking a line return at the end of the input file so that eof () won't be detected after 8.9 is read. "Solve" means getting the right output. It's in quotes because in this case, the solution works because two wrongs would make a right and you'd go through the loop an EXTRA time so it would work. The eof() function can be really treacherous if used incorrectly, as it is here. End-of-file is NOT always detected when you think it is (i.e. in this case, after the last number is read from the file). Often you have to try and fail to read data before it is set. You'd be better off without eof() altogether in this program.

while (infile >> value)
    {
          outfile << value;
          outfile << endl;
    }

Edited 7 Years Ago by VernonDozier: n/a

ok.. so the while statement is actually reading in the values instead of it being done in the main body of the loop? So when the while statement stops reading in values it stops. For files where you're reading in a list of singular items this seems much easier than the eof loop.

I appreciate the help ^_^

ok.. so the while statement is actually reading in the values instead of it being done in the main body of the loop? So when the while statement stops reading in values it stops. For files where you're reading in a list of singular items this seems much easier than the eof loop.

I appreciate the help ^_^

I'm not very clear on how ifstreams work, so I won't attempt to explain what's going on in any kind of detail. infile is a pointer to something (I'm not entirely sure what). When you try to read something with the >> operator and you fail, infile changes its pointer so that it no longer points to anything. In other words, it sets its pointer to NULL. Here's some code:

infile >> value;
    
    while (infile != NULL)
    {
          outfile << value;
          outfile << endl;
          infile >> value;
          
          //cout << "infile is pointing to  " << infile << endl;
    }

You can uncomment the line to see what infile is pointing to. You can rewrite it as follows (pseudocode)

/* read in a value from the file*/
    
    while (/* every attempt to read a value has been successful */)
    {
          /* display the last value read in */
         /* try to read in another value from the file */
    }

The difference is that I'm no longer testing whether the end of the file has been reached, but instead I am testing whether any attempt to read has failed. Thus, unlike with the eof () command, I don't care at all whether the file has any white space at the end. It's more reliable. eof () works fine, but only if you're very careful and understand its limitations. Reading until you get your first unsuccessful read is safer in many ways.

ahh ok.. that does make a lot of sense. and "infile" and "outfile" is just a variable name used to direct input and output to and from actual files. So in case the actual file names are 3 miles long you assign a shorter variable name to them for easier use in code. Or thats what i have been lead to believe ^_^.

ahh ok.. that does make a lot of sense. and "infile" and "outfile" is just a variable name used to direct input and output to and from actual files. So in case the actual file names are 3 miles long you assign a shorter variable name to them for easier use in code. Or thats what i have been lead to believe ^_^.

Well, it's a bit more complicated than that. It has little to do with the filename. Even if it was a short filename, you'd need an ifstream object. The filename is just the starting point. There are a whole bunch of intermediate steps between getting information from a hard drive to getting that information into a variable in your program. The program isn't going to grab a byte of data from your hard drive directly. The computer grabs a bunch of data all at once from your hard drive, sticks it in RAM and/or some of its chips, and does a whole bunch of other stuff before it gets into your program. Everything's done by addresses and pointers. Names are mapped to addresses. This "whole bunch of other stuff" is accomplished with buffers, streams, file descriptors, etc., and fstream does it all for you behind the scenes so you don't have to figure it all out for yourself. So the infile and outfile pointers are pointers to something, again I don't know what, that handles all that stuff for you. According to this link:

http://www.cplusplus.com/reference/iostream/ifstream/

it maintains a pointer to a filebuf object. Click on some of the links on THIS link and you'll get pages on filebuf, streambuf, etc. I imagine that calls to lower level functions like "read" and "write" happen behind the scenes.

Anyway, if you're interested, google "buffer", "stream", "file descriptor", etc., and follow the links. Here's a good link on reading/writing files.

http://www.cplusplus.com/doc/tutorial/files/

Edited 7 Years Ago by VernonDozier: n/a

This question has already been answered. Start a new discussion instead.