ofstream returning error "No matching function to call std::basic_ofstream<char>::close(const char [14])" - c++

Need help fixing my code, not sure what's wrong. I'm using C++11, trying to write a vector to a file by individually writing each struct. The section of code returning an error is:
string craigSave = "craigSave.txt";
ofstream file(craigSave.c_str());
file.open("craigSave.txt");
for (int i=0; i<finalVector.size(); i++){
file << finalVector[i]<<endl;
}
file.close("craigSave.txt");
cout<<"Thanks for shopping!"<<endl;
done = true;
The error returned is on the "file.close" line and is:
error: no matching function for call to 'std::basic_ofstream::close(const char [14])'
I research on this error seems to point to needing to use char* as an argument instead of a string, but I'm using C++11, so it should accept strings. Also it is strange that there is no error for the file.open line, as all research shows the error being there, not at file.close

Just use file.close();, there's no need to pass the file name again.
See http://www.cplusplus.com/reference/fstream/ofstream/close/.
Also, ofstreams are RAII objects, which means that the file will automatically be closed once the ofstream object goes out of scope (see do I need to close a std::fstream?):
{
ofstream out("name");
// do something with out...
} // out.close is called automatically

Related

Saving a struct array to an external file in c++

I have an assignment where I need to:
save the list that the user inputs to an external file.
load the info from the file previously saved.
I managed to write in the code for the 1st task, but since I have errors, I couldn't continue to the 2nd task. Please take a look and let me know what your thoughts are.
First Error:
When you create an array, the name of the array is a pointer to the beginning of where the array is in memory. In line 42, you cannot compare an int with a pointer like that. Instead, I assume you want to do this:
for (int i = 0; i < size; ++i) {
Second Error:
In line 43, you are trying to input an std::ofstream object into a function. In order to do this, std::ofstream must be copy-able. ofstream has a deleted copy constructor, meaning that it cannot be copied and thus cannot be passed as an input to a function. Instead, you could simply create the ofstream object and open the file within your pet::save function. Also, make sure you close the ofstream. As an example:
void pet::save()
{
ofstream file;
out.open("animal.txt");
if (!out.is_open())
cout << "Unable of open file." << endl;
file << pet_info << endl;
file.close();
}
You could also use a pointer to the ofstream as an input to your save function, since pointers can be copied (then use out->operator<<(pet_info) to input to the file). This would make it run faster, but this situation does not seem to prompt such optimization. The function prototype would look like
void pet::save(ofstream* file);
and you would pass &out as the input to the function.
Third Error:
You are trying to use the array called animal within your pet class. Since animal is an array of pets that is created outside of your pet class, the pet class does not have access to it (so animal was not declared in the scope of pet). I am guessing your pet class stores a string which contains a pet's information (which I call pet_info). Given that is true, you can call the above save function that I wrote for all of your pets in the animal array to save them to a file.
Fourth Error:
On line 109 of pet.cpp, it appears you are missing a semicolon. That could be why the bracket error is there, or you are just missing a bracket.

How to pass in filename as a parameter and opening it properly?

void openfile(const string &db_filename) {
ifstream file;
file.open("db_filename");
if(file.is_open())
{
cout<<"true"<<endl;
}
else cout<<"false"<<endl;}
I have this simple code here that checks if file is open. However, whenever I run this, I get false. which means that the file is not open. I dont know why but Im sure that the files are in the same folder and the file name is entered correctly. Is there anything wrong with this code?
You are passing a string literal "db_filename" to open() instead of passing your db_filename string object. Simply remove the quotes:
file.open(db_filename);
If your version of the STL doesn't support passing a std::string to open(), call the string's c_str() method instead:
file.open(db_filename.c_str());

c++: ifstream delete contents of a file? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am using following function:
int getline_count()
{
boost::smatch resultc;
string sLine;
int line_add_tmp;
ifstream infile;
infile.open("scripts.txt", ios_base::in);
if (!infile){
cerr << "scripts.txt could not be opened!" << endl;
}
else {
getline(infile, sLine);
if (boost::regex_match(sLine, c)) {
line_add = 2;
}
else {
line_add = 1;
}
return line_add;
infile.close();
}
}
Intension for the above function is to test if the first line in the file contains '// new' If true, 2 is returned. If false, 1 is returned. This works fine so far.
What I am confused about is that after the run the file scripts.txt is empty. How can that be since
1.) The '// new' line was correctly identified as I am getting '2' returned (running on an empty file returns 1 as expected). So it can't be that during opening the file scripts.txt it was overwritten with an empty file
2.) ifstream was designed to read only
What is it what I am missing?
Edit:
Definition for c is
static const boost::regex
c("^(\\/)(\\/)(new|New| new| New)"); // Regexp for line count
An ifstream should never manipulate your file. You will need to look elsewhere for your problem, it's not inside this code. Your best bet is to provide a Minimal, Complete, and Verifiable example that demonstrates your problem.
However, you should check your coding, you are missing essentials like error handling and treating compiler warnings. Most likely, if your other code looks the same, that's the source of your problem.
Personally, I'd write your function like this:
bool first_line_in_file_matches(const std::string& filename, const boost::regex& c)
{
std::string line;
std::ifstream infile(filename.c_str());
if (!infile)
{
cerr << filename << " could not be opened!" << endl;
// TODO: THROW AN EXCEPTION MAYBE? OR RETURN FALSE? EXIT HERE
}
return getline(infile, line) && boost::regex_match(line, c);
}
This function will not clear the contents of the file. So if in fact the file is cleared it is cleared externally to getline_count.
To prove this lets inspect the functionality of each call on ifstream relative to the file:
ifstream::open This will only clear the file if the mode is set to ios_base::trunk
ifstream::operator bool This is a const method so the ifstream cannot be modified
ifstream::getline TLDR: This can only extract, not write to a file:
Internally, the function accesses the input sequence by first constructing a sentry object (with noskipws set to true). Then (if good), it extracts characters from its associated stream buffer object as if calling its member functions sbumpc or sgetc, and finally destroys the sentry object before returning.
ifstream::~ifstream This is implicitly declared, so it simply destroys the object, closing the file; if this deleted file contents no one would ever have been able to use an ifstream
The recommended steps to finding the culprit of the file clearing are:
Ensure that you are looking at the correct file and don't have some process external to your code which is clearing the file
Search your code for "scripts.txt" something else has to access the file by name and debug it
Disable writing to "scripts.txt" and see if you can locate the code that fails to write to the file

Fstream Initialization in a Class - Checking if File Opened

Example:
//Header File
class Example
{
private:
fstream InputObject;
public:
Example();
}
//Implementation File
Example::Example():InputObject("file_name.txt", ios::in) {}
From what I've read so far from similar questions, the only way, in the "older" version of C++, for initializing an fstream object in a class is to do so via member list initialization shown above.
Question:
If that really is the "only" way of initializing an fstream object in a class, what do we do if the file should fail to open?
Normally I'd run the fstream object through a check to make sure it opened properly, but this doesn't seem possible in this case. Also, even if I could, how could I reinitialize the object if it failed to do so the first time through?
#define WIN32_LEAN_AND_MEAN // This makes it so it doesn't look through libs that are not included when running
#include <fstream> //To Read write to files, to be able to
#include <iostream> // The basic stuff, cout, cin, etc.
using namespace std; // the capability of typing cout instead of std::cout
int main() // our main loop
{
fstream InputObject; // declaring InputObject as something that can write to a file
if(!Inputobject.open("File Name Here") // if it cant open the file
{
cout << "File not Open" << endl; // then write to console, " File not Open"
}
return 0;
system("pause");
}
You want to find out if the file is open, so using ! before the functio for opening file means , not open, so an if statement with !InputObject.open, will check if it is not open, if that is true, do something, so cout << "File is not open" will tell u if it is open or not.
From what I've read so far from similar questions, the only way, in the "older" version of C++, for initializing an fstream object in a class is to do so via member list initialization shown above.
That's not strictly true.
It is probably the preferred way of doing it. But you don't need to do it that way. And a failure simply sets the state to failed that can then be tested in the body of the constructor.
If that really is the "only" way of initializing an fstream object in a class
No.
what do we do if the file should fail to open?
Test and re-try in the body of the constructor.
Normally I'd run the fstream object through a check to make sure it opened properly, but this doesn't seem possible in this case. Also, even if I could, how could I reinitialize the object if it failed to do so the first time through?
There are standard API to reset the state of a stream after a failure.
Example::Example()
:InputObject("file_name.txt", std::ios::in)
{
if (!InputObject) {
InputObject.clear();
InputObject.open("AlternativeFile", std::ios::in)
}
}

Checking existence of a txt file with C++ code

First of all, i'd to establish that i do have the text file in my Folders directory. Im using visual studio and it is where my source code is compiling.
The code below should demonstate why its not working. In visual studio.
int main( const int argc, const char **argv )
{
char usrMenuOption;
const char *cFileName = argv[ 1 ];
checkName( cFileName ); // supplying the checkName function with contents of argv[1]
usrMenuOption = getUsrOption(); // calling another function
fgetc(stdin);
return 0;
}
ifstream *openInputFile( const char *cFileName )
{
// this function might be the pronblem.
ifstream *inFile;
inFile = new ifstream;
inFile->open( cFileName, ios::in );
return inFile;
}
bool checkName( const char *cFileName )
{
// it works fine if i use a regular ifstream obj and not the one from the function
ifstream *inFile;
inFile = openInputFile( cFileName );
inFile->open( cFileName, ios::in );
if ( inFile->good() )
{
return true;
}
else
{
cout << '"' << cFileName << '"' << ": File does not exist! " << endl;
return false;
}
}
It does work if i use a non-pointer object for the ifstream.
however i need to open all of my input files this way, using the function i made.
I'm a little confused because i did not have this issue compiling in dev-cpp
You have a few options:
The one you've tried - opening the file.
Using stat.
Using GetFileAttributes.
Using FindFirstFile.
The only way to guarantee that it exists and that you can use it is to open it. If you use other methods you end up with a race condition (because the file could be deleted or locked after you check to see if it exists.
EDIT: You have a couple of other issues in your code. Firstly, you allocate a infile via new, but you never delete it. Secondly, you call open twice.
That's a poor way to test for existence: because if the file is open by another process, then the file exists but you can't open it.
A better way to test might be to use the GetFileAttributes Function: if it doesn't return INVALID_FILE_ATTRIBUTES then the file exists.
If you don't mind using Boost, there is a simple function boost::filesystem::exists( path ) that would be useful to you I guess !
I always check ifs.is_open() where ifs is a ifstream.
To check for the existence of a file (POSIX.1 compliant):
#include <unistd.h>
if (! access (file_name, F_OK))
{
// File exists.
}
How do i check if a file exists using ANSI C++?
#include <fstream>
inline bool FileExists(const char * filename)
{
return std::ifstream(filename);
}
You're trying to open the file twice inside checkName(): the first time in the constructor call inside the call to openInputFile(), the second time inside checkName() itself. Why the second call to open()?
I don't know what happens when an ifstream with an already-open file attempts to open() another file, but it won't be good, and it may well depend on the exact library implementation (hence the different behaviour between Dev-C++ and MSVC++). In short, don't do it.
There is at least one other bug: You aren't closing inFile anywhere inside checkName().
But Anyway, Do This Instead
Really, it's better not to have a separate checkName() function -- just have openInputFile() attempt to open the file, and if it fails, report the error right there and/or return a NULL pointer (or even throw an exception). That way, the operation is "atomic" -- as things stand, if the file exists at the time checkName() is called but is deleted before a subsequent call to openInputFile(), your code will get very confused.