Why would fstream.fail() return true or false - c++

I'm working through some work with some code already provided. There is an if statement that includes 2 fstream.fails(). The code is continually returning true and I'm not sure if it's because of a problem with the provided code or if I am missing something.
I've googled around to try and better understand what could be going on, but due to me being new to C++, I'm finding it hard to find an answer that helps me understand what might be going on.
The provided code where I think might be a problem.
bool Navigation::BuildNetwork(const string &fileNamePlaces, const string &fileNameLinks)
{
fstream finPlaces(fileNamePlaces);
fstream finLinks(fileNameLinks);
if (finPlaces.fail() || finLinks.fail()) return false;
ifstream();
// Add your code here
}
Where the "Build network" function is called
ACW_Wrapper wrapper("log.txt");
// Build Navigation
wrapper.startTimer();
Navigation nav;
if (nav.BuildNetwork("Places.csv", "Links.csv")) {
const auto elapsed = wrapper.stopTimer();
std::cout << std::fixed << std::setprecision(1) << "BuildNetwork - " << elapsed << " microseconds" << std::endl;
}
else {
std::cout << "\n*** Error *** BuildNetwork" << std::endl;
}
I would expect it to return false since this is provided code, but I'm unsure if I need to add something that would give me the expected outcome.

From the ios::fail documentation:
true if badbit (Read/writing error on I/O operation) and/or failbit (Logical error on i/o operation) are set.
which suggests that at least one of the two files is not opened successfully.
The problem is not in the code, the problem is with your program trying to open files that are not probably found (or it doesn't have permissions to).
Copy the files to the same workspace (folder) with your executable, and try again.

Related

What is causing 0 and 1 to be written to the end of the new file? C++

I use two different txt files at work for a task. One of them gets updated any time I need to call someone back (callback.txt), and one that gets updated with all of the callbacks that didn't get finished by the end of the day (recap.txt). I have written a basic python program, as well as a PowerShell script, that updates recap.txt at the end of the day by adding the newest entries to the top of the recap.txt from the day before.
Now, I am trying to write it in C++ just to get some experience with the language, but I can't seem to find why I am running into this issue. Everything works as intended, except that "recapNEW.txt" has 0 and 1 written and the end of the file on separate lines each. For example:
callback.txt:
----------
here's something
here is something else
yadda yadda
recapOLD.txt
----------
old news
still need it though
so we keep it around
recapNEW.txt (blank)
----------
And, after running the program:
recapNEW:
----------
here's something
here is something else
yadda yadda
old news
still need it though
so we keep it around
0
1
This is what I have written:
#include<fstream>
#include<iostream>
#include<string>
void update () {
std::ifstream callback("callback.txt");
std::ifstream recapBAK("recapBAK.txt");
std::ofstream recapNEW("recapNEW.txt");
std::string callLine;
std::string bakLine;
if (!callback || !recapNEW || !recapBAK) {
std::cerr << "Could not open needed files. Exiting.";
std::exit(1);
}
while (std::getline ( callback,callLine )) {
recapNEW << callLine << std::endl ;
}
while (std::getline ( recapBAK,bakLine )) {
recapNEW << bakLine << std::endl ;
}
recapNEW << callback << std::endl << recapNEW << std::endl ;
callback.close();
recapBAK.close();
recapNEW.close();
}
I split the recap.txt file into two separate files ("recapBAK.txt" & "recapNEW.txt") to keep a copy of the previous day's recap and am updating it in a separate function (posted below), but I have narrowed it down that it is the above function that is writing the extra numbers to the end of the file.
void backup () {
std::ofstream backup("recapBAK.txt");
std::ifstream today("recapNEW.txt");
std::string todayLine;
while (std::getline (today,todayLine)) {
backup << todayLine << std::endl;
}
backup.close();
today.close();
}
What is confusing me the most is that I don't see what I am doing differently in the first function that is causing the integers to be tagged on to the end of the file, because no additional integers are added to the updated version of recapUSED.
Apologies if this is not clear enough, first time I've hit a wall hard enough that I posted to a forum lol. I appreciate the help, I'm self-teaching and love having input to work with to see where I can/should improve.
I think the problem is that in:
recapNEW << callback << std::endl << recapNEW << std::endl ;
... you are attempting to output the contents of the streams callback and recapNEW to recapNEW, but it doesn't work that way. Rather, the Boolean "good" status of the file streams is output instead. Prepending to a stream isn't that simple.
Actually, it looks like you have what you need without that line. Have you tried just removing it?

Control may reach end of non-void function error in C++

I'm following a tutorial on how to make a game in C++ and I'm getting the "Control may reach end of non-void function" error. I know this error is common and many have already asked on how to solve this, but I just don't get how it is possible that I'm getting this error and thus am unable to run it while my teacher has the EXACT same code and seems to be doing just fine.
This is my code :
FText GetValidGuess()
{
EGuessStatus Status = EGuessStatus::Invalid_Status;
do {
int32 CurrentTry = BCGame.GetCurrentTry();
std::cout << "Try " << CurrentTry << ". Enter your guess! : ";
FText Guess = "";
getline(std::cin, Guess);
Status = BCGame.CheckGuessValidity(Guess);
switch (Status) {
case EGuessStatus::Wrong_Length:
std::cout << "Please enter a " << BCGame.GetHiddenWordLength() << " letter word.\n";
break;
case EGuessStatus::Not_Lowercase:
std::cout << "Please enter your guess in lowercase letters.\n";
break;
case EGuessStatus::Not_Isogram:
std::cout << "Please enter an isogram.\n";
break;
default:
return Guess;
}
std::cout << std::endl;
} while (Status != EGuessStatus::OK);
}
Here's a screenshot of the code used in the video, which runs just fine and has no errors.
Am I missing something or how is it possible that I am having trouble and my teacher isn't?
I'm sorry if this question has been asked several times already but I can't seem to fix it and the code is the same as in the video...
The "error" you're getting is (at least with most compillers) only a warning. Whether it causes the compilation to be aborted can be enabled/disabled using compiler options (usually called "threat warnings as errors"). This may be why you get the error while your teacher does not.
The reason for the error though, is that you don't have a return statement at the end of your method. So if Status == EGuessStatus::OK, the method returns an undefined value at the end.
It's a false positive. The compiler only performs a superficial code analysis for this warning, so it ends up telling you that you "may" get a problem.
In fact, that's the same thing I would tell you if I saw this piece of code in a code review before mentally going through the control flow: "Are you sure this function always returns something?"
What's confusing the compiler and your fellow human code reviewer is your redundant loop condition. Status != EGuessStatus::OK can never be false at this point, so why do you put it there anyway? Turn the loop it into something like for (;;), and the warning should go away.
Expected return type is FText, and is not guaranteed if do-while does nothing.
So keep your code fool proof to provide return value always.
In GCC -Wreturn-type compiler option can be used to highlight this error.
Cross check the compiler options for cl

How to disable cout output in the runtime?

I often use cout for debugging purpose in many different places in my code, and then I get frustrated and comment all of them manually.
Is there a way to suppress cout output in the runtime?
And more importantly, let's say I want to suppress all cout outputs, but I still want to see 1 specific output (let's say the final output of the program) in the terminal.
Is it possible to use an ""other way"" of printing to the terminal for showing the program output, and then when suppressing cout still see things that are printed using this ""other way""?
Sure, you can (example here):
int main() {
std::cout << "First message" << std::endl;
std::cout.setstate(std::ios_base::failbit);
std::cout << "Second message" << std::endl;
std::cout.clear();
std::cout << "Last message" << std::endl;
return 0;
}
Outputs:
First message
Last message
This is because putting the stream in fail state will make it silently discard any output, until the failbit is cleared.
To supress output, you can disconnect the underlying buffer from cout.
#include <iostream>
using namespace std;
int main(){
// get underlying buffer
streambuf* orig_buf = cout.rdbuf();
// set null
cout.rdbuf(NULL);
cout << "this will not be displayed." << endl;
// restore buffer
cout.rdbuf(orig_buf);
cout << "this will be dispalyed." << endl;
return 0;
}
Don't use cout for debugging purposes, but define a different object (or function, or macro) that calls through to it, then you can disable that function or macro in one single place.
You can user cerr - standard output stream for errors for your debug purposes.
Also, there is clog - standard output stream for logging.
Typically, they both behave like a cout.
Example:
cerr << 74 << endl;
Details: http://www.cplusplus.com/reference/iostream/cerr/
http://www.cplusplus.com/reference/iostream/clog/
If you include files which involve cout you may want to write the code at the start (outside of main), which can be done like this:
struct Clearer {
Clearer() { std::cout.setstate(std::ios::failbit); }
} output_clearer;
It seems you print debug messages. You could use TRACE within Visual C++/MFC or you just might want to create a Debug() function which takes care of it. You can implement it to turn on only if a distinct flag is set. A lot of programs use a command line parameter called verbose or -v for instance, to control the behavior of their log and debug messages.

c++ CopyFile function problem

Hey guys i need to use CopyFile in win 2000 and above platforms.
i want to copy my application to a different folder say c:.
so this works:
BOOL didThisFail = FALSE;
if (CopyFile(L"MyApplication.exe", L"something.exe", didThisFail))
cout << "File was copied" << endl;
but this dosen't:
BOOL didThisFail = FALSE;
if (CopyFile(L"MyApplication.exe", L"C:\\something.exe", didThisFail))
cout << "File was copied" << endl;
GetLastError() will tell you why it failed, probably an access denied error.
sometimes copy can fail if you can run out of disk space. When i got stuck in this problem i changed copy command to Move and it worked out for me.
I used to get error code 112.

Unable to write file in C++

I'm trying to to the most basic of things .... write a file in C++, but the file is not being written. I don't get any errors either. Maybe I'm missing something obvious ... or what?
I thought there was something wrong with my code, but I also tried a sample I found on the net and still no file is created.
This is the code:
ofstream myfile;
myfile.open ("C:\\Users\\Thorgeir\\Documents\\test.txt");
myfile << "Writing this to a file.\n";
myfile.close();
I've also tried creating the file manually beforehand, but it's not updated at all.
I'm running Windows 7 64bit if that has got something to do with this. It's like file-write operations are completely forbidden and no error messages or exceptions are shown.
You need to open the file in write mode:
myfile.open ("C:\\Users\\Thorgeir\\Documents\\test.txt", ios::out);
Make sure to look at the other options for that second argument, as well. If you're writing binary data you'll need ios::binary for example.
You should also be checking the stream after opening it:
myfile.open(...
if (myfile.is_open())
...
Update:
AraK is right, I forgot that an ofstream is in write mode by default, so that's not the problem.
Perhaps you simply don't have write/create permissions to the directory? Win7 defaults a lot of directories with special permissions of "deny all". Or perhaps that file already exists and is read-only?
Start off by turning that slash around.
Even Windows understands the slash being the other way around.
ofstream myfile("C:/Users/Thorgeir/Documents/test.txt");
You could test if there are any errors:
if (!myfile)
{
std::cout << "Somthing failed while opening the file\n";
}
else
{
myfile << "Writing this to a file.\n";
myfile.close();
}
Make sure the directory exists.
If the file exists make sure it is writeable (by you)
Check the directory you are writing into is writeable (by you)
Have you read about UAC (User Account Control) and UAC Virtualization / Data Redirection in Windows Vista and 7? It's possible that your file is actually in the Virtual Store.
User Account Control Data Redirection
Your example output directory is in Users, so I wouldn't think this would be the issue, but it's a possibility worth mentioning and something that can be very frustrating if you're not looking out for it!
Hope this helps.
This code should catch any error. Most likely it's a permissions thing if any errors are encountered. Make sure you can read/write to the folder you're creating the file in.
#include "stdafx.h"
#include <fstream>
#include <iostream>
bool CheckStreamErrorBits(const std::ofstream& ofile);
int _tmain(int argc, _TCHAR* argv[]) {
std::ofstream ofile("c:\\test.txt");
if(ofile.is_open()) {
CheckStreamErrorBits(ofile);
ofile << "this is a test" << std::endl;
if(CheckStreamErrorBits(ofile)) {
std::cout << "successfully wrote file" << std::endl;
}
}else {
CheckStreamErrorBits(ofile);
std::cerr << "failed to open file" << std::endl;
}
ofile.close();
return 0;
}
//return true if stream is ok. return false if stream has error.
bool CheckStreamErrorBits(const std::ofstream& ofile) {
bool bError=false;
if(ofile.bad()) {
std::cerr << "error in file stream, the bad bit is set" << std::endl;
bError=true;
}else if(ofile.fail()) {
std::cerr << "error in file stream, the fail bit is set" << std::endl;
bError=true;
}else if(ofile.eof()) {
std::cerr << "error in file stream, the eof bit is set" << std::endl;
bError=true;
}
return !bError;
}
Update:
I just test my code under Windows 7 Enterprize and it failed the first time (fail bit was set). Then I turn off User Account Control (UAC) and tested again and it wrote the file. That is probably the same problem you're seeing. To turn off UAC go to:
Control Panel (view by Small icons) | User Accounts | Change User Account Control settings. Set it to Never notify then click OK button. You will have to restart for the changes to take affect.
I'm curious how to make it work with UAC on, i'll look into that.
Try this:
if( ! myfile)
{
cerr << "You have failed to open the file\n";
//find the error code and look up what it means.
}
Use FileMon and look for failed WriteFile calls from your process.