Hello Rayjk,
The only way I was able to duplicate your problem was to open a file name that did not exist. The open did not work, but the program continued any way.
The first question is how do you know that the input file is open and usable? YOu do not.
I found this to be useful when I first started working with input and output files:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
const std::string inFileName{ "albuminfo.txt" };
const std::string outFileName{ "tracklist.txt" };
std::ifstream inFile(inFileName);
if (!inFile)
{
std::cout << "\n File " << std::quoted(inFileName) << " did not open" << std::endl;
//std::this_thread::sleep_for(std::chrono::seconds(3)); // <--- Needs header files chrono" and "thread". Optional as is the header files.
return 1; //exit(1); // If not in "main".
}
std::ofstream outFile(outFileName);
if (!outFile)
{
std::cout << "\n File " << std::quoted(outFileName) << " did not open" << std::endl;
//std::this_thread::sleep_for(std::chrono::seconds(3)); // <--- Needs header files chrono" and "thread". Optional as is the header files.
return 2; //exit(2); // If not in "main".
}
|
Lines 1 and 2 are defined as constant variables because they should not be changed, but should you need this variable for user input just remove the "const".
Lines 4 and 14 both define the file stream variable and open the file at the same time.
The if statement at line 6 is a must for input files. Kind of 50/50 for output files because if the file name does not exist it will create it first. The if statement for the output file stream is useful if you have a path to the file name.
Lines 9 and 19 are optional. I use this because when the program executes a return, or "exit()", the console window closes and any last messages sent to the screen are lost when the console window closed. Some IDEs will wait for a key press to close the console window in which case these lines are not needed.
Lines 10 and 20 the "return" is used if the code is in "main". Use the "exit()" if used in a function otherwise you will just return back to the calling function.
The reason for the "return", or "exit()" is because there is no reason to continue with the program if you can not read from the file. This needs to be fixed before the program can continue.
After that the program works down to the while loop.
The while condition is a problem.
while (!inputFile.eof())
this does not work the way that you are thinking. By the time the condition figures that you have reached "eof" you have already entered the loop tried to read past "eof" and your input stream has failed, but you still have to process what you could not read. Usually this uses what was left in the variables form the last read and gives you two of the last good read before the loop ends.
I cave come to the conclusion that students ate taught about the ".eof()" function, but not how to use it properly. To use what you have you should do this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
getline(inputFile, songT); // <--- This here to catch if an empty file. Or read the first line.
while (!inputFile.eof())
{
inputFile >> min;
inputFile >> sec;
numT += 1;
outputFile << setw(2) << left << setfill('0') << right << numT << " - ";
outputFile << setw(40) << left << setfill(' ') << songT;
outputFile << setw(2) << right << min << ": ";
outputFile << setw(2) << setfill('0') << sec << setfill(' ') << endl;
TotalAM += min;
TotalAS += sec;
inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>.
getline(inputFile, songT); // <--- This here to catch when "eof" is reached.
}
|
The method that is most often used is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
while (getline(inFile, songT))
{
inFile >> min;
inFile >> sec;
numT += 1;
outFile << setw(2) << left << setfill('0') << right << numT << " - ";
outFile << setw(40) << left << setfill(' ') << songT;
outFile << setw(2) << right << min << ":";
outFile << setw(2) << setfill('0') << sec << setfill(' ') << endl;
TotalAM += min;
TotalAS += sec;
inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>.
}
|
This way when "getline" tries to read past "eof" the stream fails and so does the condition continuing with what comes after the while loop.
Inside the while loop you have
min << ": ";
. I removed the space after the colon so that the output would look better.
I played around with these two line:
1 2 3
|
outFile << "----------------------------------------------------" << endl;// For a better appearance take 26 or 27 "-"s
//outFile << std::string(52, '-') << '\n';
outFile << "Total Time" << std::string(35, ' ') << TotalAM << ':' << TotalAS << std::endl;
|
Line 2 is another way of writing line 1 that is easier to work with and change. Line 3 I added for fun. Use as you see fit.
Hope that helps,
Andy