I wish I knew where people are taught to loop on EOF. That has never ever been correct in any programming language I have ever used. (And I have used several dozen.)
The correct way is
• attempt to read from file
• break loop on failure
C++ makes this very easy to write succinctly:
1 2 3 4 5
|
while (infile >> number)
{
cout << number << "\n"; // Don't forget to separate the output!
outfile << number << "\n";
}
| |
If you wish to write it out, it would look like this:
1 2 3 4 5 6 7 8
|
while (true)
{
infile >> number;
if (!infile.good()) break;
cout << number << "\n";
outfile << number << "\n";
}
| |
or this:
1 2 3 4 5
|
while ((infile >> number).good())
{
cout << number << "\n";
outfile << number << "\n";
}
| |
Notice the newlines after each number. It doesn’t have to be a newline, it could be a space or a comma or a tab (or whatever). What is important, however, is that copying a file this way potentially changes the way the data is formatted. That is, it forces the data to be delimited by newlines (or spaces or commas or whatever). If this is desired, then it is good. If not, then it is bad.
After copying from infile to outfile, outfile is
still open, and it is already at EOF. Hence, there is no need to try to open it again (the attempt will fail). If your assignment is to
append data to an extant file, simply open with append the extant file:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
int main()
{
std::ofstream outfile( "results.txt", std::ios::app );
// If "results.txt" did not exist before, it does now.
// Either way, we will append data to the file.
for (int n = 0; n < 3; n++)
{
std::cout << "Please enter a number (" << (n+1) << " of 3): ";
int number;
std::cin >> number;
outfile << number << "\n";
}
| |
The best time to check whether a file open succeeded is immediately after opening it:
1 2 3 4 5 6 7 8
|
int main()
{
std::ofstream outfile( "results.txt", std::ios::app );
if (!outfile)
{
std::cerr << "Failure to open \"results.txt\".\n";
return 1;
}
| |
In terms of sequence, only indicate that something has completed successfully
after it has completed successfully. Your users will never hate you for lying to them. ("Hey, program crashed after program said it did something, but that something hasn't been done! WTF!?")
1 2 3 4 5 6 7
|
std::ifstream infile( "data.txt" );
std::ofstream outfile( "results.txt" );
outfile << infile.rdbuf();
if (infile and outfile)
std::cout << "1 file(s) copied.\n";
else
std::cout << "Failure to copy.\n";
| |
All objects have
scope, including fstream objects. When the fstream goes out of scope the associated file will be closed automatically; you do not need to close() it yourself.
A for loop has a pretty standard way of writing it; it is normally written this way because it causes least surprise and failure:
1 2 3
|
for (int n = 0; // start at zero
n < N; // stop at N=number of times through loop. Notice we use strictly-less-than.
n++) // same as: n = n+1 and: n += 1
| |
If you wish to count backwards or have some unusual offset, do that in the loop:
Hope this helps.