I have a program where I need to take in a command line argument that is the name of a text file. The program is run by ./programName file1. If for the purpose of my program I can assume file1 will always be formatted correctly, can I just do
ifstream myFile(argv[1]);
if(!myFile.good()){
cout << "Not a valid player file" << endl;
return 1;
}
to check if there is such a file, and then simply
myFile >> var1;
myFile >> var2;
myFile.close();
or should I stick with
if(myFile.is_open()){
myFile >> var1;
myFile >> var2;
myFile.close();
}
else{
cout << "Unable to open file";
}
Again I can assume the file will always be formatted correctly(i.e myFile >> var# will always work). So is there any situation in which the else statement might be called after my initial check of (!myFile.good())?
You should mainly check the input operations, to know if your file has the proper input format:
if(myFile >> var1 >> var2) {
// Everything's fine
}
else {
// WRONG FORMAT OR COULDN'T BE OPENED!
}
To know the actual error reason in the else part, you can inspect the iostate flags returned by the std::istream::rdstate() function.
If the open() failed the badbit will be set, if one of the input operations failed the failbit will be set.
Related
I am building an input validation function that takes the input of the user and tries to open that file. and repeats if user is not entering the correct format. the correct format is:
test1.txt
My function works if I write correct format in the first run, but after the second run it keeps printing the error message although I am writing the write format to be opened. I have tried to clear the input "cin" and "filename" after taking the input but it did not work. Any ideas ?
string getFileInput()
{
string filename;
fstream file;
cout << "Please enter the name of the file: ";
getline(cin, filename);
file.open(filename.c_str());
while(!file.is_open())
{
file.clear(); file.ignore();
cout << "File name is incorrect, please enter again: ";
cin.clear(); cin.ignore();
getline(cin, filename);
file.open(filename.c_str());
}
// Extra condition. Empty file
if (file.eof())
{
cout << filename << " is an empty file." << endl;
}
file.close();
return filename;
}
I could reproduce and fix.
The problem is caused by cin.ignore(). According to cppreference:
... the next available character c in the input sequence is delim
So ignore will read the next line, up to the newline, and leave that newline alone. And the following getline can only read an empty string!
By the way, using a non opened fstream (file) for ignore and clear is at least useless and could be harmlfull because those methods are expected to be called on an open stream. And using cin.clear() is useless too and can be harmfull: if for any reason you have a read error (because you reached an end of file for example), you will consistently clear the error condition and try to read again when you should abort.
Finally, the eof condition is only set after a read returned nothing because of the end of file. It is never set when opening an empty file, nor if you could successfully read up to the end of file.
So the function should boil down to:
string getFileInput()
{
string filename;
fstream file;
cout << "Please enter the name of the file: ";
getline(cin, filename);
if (! cin) {
// test the error immediately and before using filename!
cerr << "read error: aborting...\n";
return "";
}
file.open(filename.c_str());
while(!file.is_open())
{
cout << "File name is incorrect, please enter again: ";
getline(cin, filename);
if (! cin) {
// test the error immediately and before using filename!
cerr << "read error: aborting...\n";
return "";
}
file.open(filename.c_str());
}
file.close();
return filename;
}
//Prompts user for a file name and stores it
string fileName;
cout << "Enter the file name: ";
cin >> fileName;
ifstream inFile (fileName);
inFile.open(fileName);
//Prompt the user until they give the name of a file that can be opened
bool validFileName = false;
while(validFileName == false)
{
if(inFile.is_open())
{
validFileName = true;
}
else
{
cout << "Please enter a valid file name: ";
cin >> fileName;
ifstream inFile;
inFile.open(fileName);
}
}
//this block prints to the terminal, so it's opening
if(inFile.is_open())
{ cout << "It works! \n"; }
I am trying to create a program that will work with a file, but there needs to be a section that checks to see if the file that the user types in is an actual file that the program can open. I've tried a few different ways to write the while loop, because it needs to keep asking until it receives a valid file. I have the valid file name "input.txt", but even when I type that into the terminal it continues to print the error message. I have tried to type the file name with and without quotes, so I'm not sure what it is caught up on. I know it is opening the file, because I added a second check afterward and it appears that it's opening, so I think it's an issue with how I have the error check statement written?
The problem is that you are using
ifstream inFile;
inFile.open(fileName);
in the loop. The variable in the loop hides the variable of the same name outside the loop. Remove the first of those lines.
FWIW, you can simplify your code to:
ifstream inFile (fileName);
while(!inFile)
{
// Prompt the user until they give the name of a file that can be opened
cout << "Please enter a valid file name: ";
cin >> fileName;
inFile.open(fileName);
}
if(inFile)
{
cout << "It works! \n";
}
In:
ifstream inFile (fileName);
inFile.open(fileName);
The file is opened on the first line.
Reopening it is redundant.
Also in the loop you declare a temporary variable inFile which goes out of stop at the end of the else statement. Make sure to declare it only once at the outmost scope you would like to use it.
I am working on a program that reads from a file and pushes back the contents of that file into a vector. It will read until the file reaches a space and push that string into a vector, then continue after the space. I have written this code.
ifstream inFile;
inFile.open("message1.txt");
if (inFile.fail()) {
cerr << "Could not find file" << endl;
}
while (inFile >> S) {
code1.push_back(S);
}
I am just confused about the while (inFile >> S) actually does. I understand that it reads from the inFile until it reaches the end of file. But what does the inFile >> S condition actually do? Thanks for your time.
What the inFile >> S does is take in the file stream, which is the data in you file, and uses a space delimiter (breaks it up by whitespace) and puts the contents in the variable S.
For example:
If we had a file that had the follow contents
the dog went running
and we used inFile >> S with our file:
ifstream inFile("doginfo.txt")
string words;
while(inFile >> words) {
cout << words << endl;
}
we will get the following output:
the
dog
went
running
The inFile >> S will continue to return true until there are no more items separated by whitespace.
The expression inFile >> S reads a value into S and will return inFile.
This allows you to chain variables together like infile >> a >> b >> c;
Since this inFile is being used in a bool context, it will be converted to bool. And iostream objects are defined to convert to a bool that's true if and only if the object has no current error state.
I'm trying to write a function that automatically formats XML-Strings; but I'm already failing when I try to read text from a file and write it into another one.
When I use my function sortXMLString()
bool FormatXML::sortXMLString()
{
string XMLString;
ifstream fin("input.txt");
fin.open("input.txt", ios::in);
ofstream fout("output.txt");
fout.open("output.txt", ios::out);
if (fin.is_open() && fout.is_open())
{
if (fin.good()) cout << "good" << endl;
if (fin.fail()) cout << "fail" << endl;
if (fin.bad()) cout << "bad" << endl;
while (getline(fin, XMLString))
{
//TODO: Formatting
fout << &XMLString << endl;
}
fin.close();
fout.close();
}
else return false;
return true;
}
I will get the output "fail", but the function never enters the while-loop. The function returns true.
It doesn't matter what I write into my input.txt (a single letter, a single number, multiple lines of text or even nothing), the failbit will always be set before getline can even be reached.
Why is this/ how can I properly read out of my file?
ifstream fin("input.txt"); will open the file with fin as stream object why calling open member function again ? same goes for fout object too.
Calling open on an already open stream fails, meaning the failbit flag is set to true.
Just open once
ifstream fin("input.txt");
ofstream fout("output.txt");
SO when my program starts, it attempts to read a list of products from a file. but if the file does not exist it displays an error and continue on. the problem im having is when it displays the error, it doesnt continue on to the do while loop
ifstream input;
input.open("data.txt");
if (input.fail())
{
cout << "\n Data file not found \n";
}
ListItemType data;
input >> data.productname;
while(( !input.eof()))
{
input >> data.category;
input >> data.productprice;
addproduct(head, data);
input >> data.productname;
}
input.close();
It's not identical functionality, but it's generally better to move towards something like:
if (std::ifstream input("data.txt"))
{
ListItemType data;
while (input >> data.productname >> data.category >> data.productprice >> data.productname)
addproduct(head, data);
if (!input.eof())
std::cerr << "Error parsing input file.\n";
}
else
cout << "\n Data file not found \n";
If you structure your if/else clauses as above, whatever happens it will continue to the following code as you'd like.
Note that the code above checks for a problem after each input operation. Your code tries to read data.productprice even if reading data.category failed. It's kind of weird you're reading productname twice, and I'm assuming you can call addproduct after the I/O - if not you'll need a while loop like:
while (input >> data.productname >> data.category >> data.productprice)
{
addproduct(head, data);
if (!(input >> data.productname))
break;
}