Here is what I am trying to do:
1) Open an ofstream object in my main body. I can do this no problem.
2) Associate this object with a filename. No problem.
3) Pass this object to a class and send output within this class. I can't do this.
Here is my code. I would appreciate any help. Thanks!
#include <fstream>
#include <iostream>
using namespace std;
typedef class Object
{
public:
Object(ofstream filein);
} Object;
Object::Object(ofstream filein)
{
filein << "Success";
}
int main (int argc, char * const argv[])
{
ofstream outfile;
outfile.open("../../out.txt");
Object o(outfile);
outfile.close();
return 0;
}
You must pass stream objects by reference:
Object::Object( ofstream & filein )
{
filein << "Success";
}
And why are you using a typedef on the class? It should look like this:
class Object
{
public:
Object(ofstream & filein);
};
It is worth mentioning, that in c++0x you will have another options (besides passing by reference or by pointer):
std::move. Streams are not copyable, but you will be able to move them into another place (it depends if streams will implement the move operator, but they probably will).
unique_ptr. Streams are not copyable. When using pointers, a risk of resource leak arises. Using shared_ptr incorporates unnecessary costs when you want to have streams stored in a collection, and nowhere else. Unique_ptr solves this. You will be able to store streams in a collection in safe and efficient way.
Related
I am toying around with streams for a bit and can't get my head around the following.
Here we have a basic ostream ptr that is set to different output streams, whether it is cout, cerr or a file.
// ostream ptr
std::ostream* outstream;
// set output ostream
void setOutput(std::ostream & os)
{
outstream = &os;
}
// write message to ostream
void writeData(const std::string & msg)
{
*outstream << msg << '\n';
}
int main (int argc, char * const argv[])
{
// init to std out
setOutput(std::cout);
writeData("message to cout");
setOutput(std::cerr);
writeData("message to cerr");
std::ofstream fileout("test.txt", std::ofstream::out | std::ofstream::app);
setOutput(fileout);
writeData("message to file");
//fileout.close();
setOutput(std::cout);
writeData("message2 to cout");
return 0;
}
The above works perfectly and shows the strength of the c++ iostream implementation. Perfect.
However, since the setOutput is set by reference the referenced object has to stay in scope. This is where the issue emerges. I want to figure out a way to default the output to std::cout if the ofstream or any other ostream is invalidated. That is, referenced object is or went out of scope.
For example:
// write message to ostream
void writeData(const std::string & msg)
{
if (/*stream or memory is invalid*/)
setOutput(std::cout);
*outstream << msg << '\n';
}
// local fileout goes out of scope
void foo()
{
std::ofstream fileout("test.txt", std::ofstream::out | std::ofstream::app);
setOutput(fileout);
writeData("message to file");
}
int main (int argc, char * const argv[])
{
setOutput(std::cout);
writeData("message to cout");
foo();
/* problem the local fileout is no longer referenced by the ostream ptr*/
/* the following should be redirected to std::cout cuz of default*/
writeData("message2 to cout");
return 0;
}
The above is fine until the foo() returns to the main function. There it goes horrible wrong because the locally defined ofstream is not reachable anymore.
Obviously this is not advisable and the user should realise this. However I want to wrap all this in a logging class and thus keep the state of the object valid even thought this misuse might happen. It will cause an invalidate access violation which can be hard to find.
Concrete question. Is there any way to figure out whether an ostream ptr or any ptr for that matter is still referencing a valid object or memory location?
ps: I could use heap memory and do something with smart pointers but frankly I'd want to keep it like this if possible
Concrete question. Is there any way to figure out whether an ostream ptr or any ptr for that matter is still referencing a valid object or memory location?
No. There is no way to figure that out with raw pointers. Not in standard c++ at least.
You will need to guarantee that the pointed object stays alive as long as it's pointed to.
A common pattern that is used to provide that guarantee is RAII, as detailed in other answers. Another approach to guaranteeing validity of of a pointer is to use a smart pointer instead of a raw one. However, those are not compatible with automatic variables.
It would be OK to keep pointing to dead objects as long as you could guarantee that the pointer is not dereferenced. Which is often difficult to guarantee, because, as already stated, there is no way to test whether the pointed object exists.
This sounds like a great use case for RAII.
Write a class that takes a filename and a std::ostream** as parameters to its constructor. In the constructor of the said class, construct the ofstream (as a member), and set the pointer to the ofstream. In the destructor, revert to stdout.
Then, replace the first two lines of the following function with a declaration of the new class.
void foo()
{
std::ofstream fileout("test.txt", std::ofstream::out | std::ofstream::app);
setOutput(fileout);
writeData("message to file");
}
You should use RAII to force the stream to be set correctly and then set back to std::cout if the object is destroyed.
class OutputStream
{
protected:
static std::ostream*& internalGlobalStateOfOutputStream()
{
static std::ostream* out = &std::cout;
return out;
}
public:
static std::ostream& getOutputStream()
{
return *internalGlobalStateOfOutputStream();
}
};
template<typename T>
class OutputStreamOwner: public OutputStream
{
T ownedStream;
public:
OutputStreamOwner(T&& obj)
: ownedStream(std::move(obj))
{
internalGlobalStateOfOutputStream() = &ownedStream;
}
template<typename... Args>
OutputStreamOwner(Args... args)
: ownedStream(args...)
{
internalGlobalStateOfOutputStream() = &ownedStream;
}
~OutputStreamOwner()
{
internalGlobalStateOfOutputStream() = & std::cout;
}
// Delete copy
OutputStreamOwner(OutputStreamOwner const&) = delete;
OutputStreamOwner& operator(OutputStreamOwner const&) = delete;
};
The usage is:
void foo()
{
OutputStreamOwner<std::ofstream> output("test.txt", std::ofstream::out | std::ofstream::app);
writeData("message to file");
}
A possible approach is to create a RAII class that wraps the stream before passing it into setOutput. This class should be designed to work like shared_ptr such that it maintains a shared ref count. writeData then checks to see if it has the only remaining reference and if so then destroys the ostream and defaults to cout.
You could avoid these complications altogether with a function that takes the stream as input.
void writeData(std::ostream& os, const std::string & msg)
{
os << msg << '\n';
}
You can further refine it by returning the stream, to allow one to chain calls to it:
std::ostream& os writeLine(std::ostream& os, const std::string & msg)
{
os << msg << '\n';
return os;
}
// declare stream
stream << writeLine(stream, "Foo") << writeLine(stream, "Bar");
In fact this function is nicer and easier to maintain, as you don't have to remember which stream is set at any given time. For large programs, this is an important quality.
Concrete question. Is there any way to figure out whether an ostream
ptr or any ptr for that matter is still referencing a valid object or
memory location?
ps: I could use heap memory and do something with smart pointers but
frankly I'd want to keep it like this if possible
No, there is no standard way to test if a raw pointer or reference is still referring to a valid object.
RAII is the standard C++ solution to this type of problem so you should be looking at smart pointers, in my opinion. I am not aware of any library provided smart pointer that would solve this particular problem but an RAII solution based on shared ownership seems the best solution here.
To take in a string (including spaces) and write it to a file, I use:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ofstream myFile("readme.txt");
string a;
getline(cin, a);
myFile << a;
myFile.close();
}
But should I be managing the memory assigned to the string, and if so what's the easiest way?
No, std::string manages its own memory.
No, you don't need to. Unlike C (where strings are pointers to arrays that have to be managed), The std::string class is an object which manages its own memory. The memory for a is released correctly when the variable a goes out of scope at the end of the program.
As others have stated, std::string (a d every other STL container, for that matter) manages its own memory, and will be freed when it goes out of scope. If you want more control over when it goes out of scope, you can do this:
int main()
{
ofstream myFile("readme.txt");
{
string a;
getline(cin, a);
myFile << a;
} // <-- string is freed here
// do other things...
}
In C++ string template class provided in is a typedef for std::basic_string<char> and it manages the memory dynamically. So you shouldn't. You have still options however to help this class in this task. String provides for this purpose appropriate interface, for example
void reserve( size_type new_cap = 0 );
Informs a std::basic_string object of a planned change in size, so
that it can manage the storage allocation appropriately.
I'm quite new to C++. I've been trying to figure this out for days - there'll be an easy solution no doubt but I haven't been able to find it (after much googling)! My problem is this:
I'm trying to create a class with a member function that reads in characters from a file and stores them in an array. I want to be able to create multiple objects (not sure how many - decided by the user), each with their own arrays filled with characters taken from different files. I think I've managed to do that. How would I then go about accessing the object's array in main?
The code I'm working on is long and messy but something along these lines (char.txt contains simply '12345' in this case):
#include <iostream>
#include <fstream>
using namespace std;
class Something{
public:
void fill_array(char array_to_fill[]){
char next;
ifstream input;
input.open("chars.txt");
input.get(next);
while(!input.eof())
{
for(int i = 0; i < 6; i++)
{
array_to_fill[i] = next;
input.get(next);
}
}
}
};
int main()
{
Something* something = new Something[1];
char array_to_fill[5];
something->fill_array(array_to_fill);
//I'd like to be able to access the array here; for example - to cout the array.
return 0;
}
Apologies if a) my terminology is wrong b) my code is rubbish or c) my question is stupid/doesn't make sense. Also I should add I haven't learnt vectors yet and I'm not supposed to use them for the program I'm making. Any help would be much appreciated. Cheers!
Your class does not store the array at all. It is simply a holder for a method. You probably want something like this, where each instance of the class holds the array. (I changed it to std::string since they are nicer to work with.)
class Something
{
private:
std::string data;
public:
void fill_data( const std::string& filename )
{
ifstream file( filename );
file >> data;
file.close();
}
std::string get_data() const
{
return data;
}
}
int main()
{
std::vector<Something> my_things;
my_things.push_back( Something() );
my_things[0].fill_data( "chars.txt" );
cout << my_things[0].get_data() << std::endl;
my_things.push_back( Something() );
my_things[1].fill_data( "another_file.txt" );
cout << my_things[1].get_data() << std::endl;
}
Since you are using C++, not C, get used to writing C++ code instead of C. (std::vector instead of C arrays (for unknown length arrays), std::string instead of char*, etc).
I think your question is too general for the format of stack overflow, but what you want in this case is to either create a public member, or create a private member with setters and getters.
class Something
{
public:
std::string m_string;
}
int main()
{
Something A;
A.m_string = "toto";
cout << A.m_string;
return 0;
}
Put a string for convenience (you could use a const char* but you will have to understand what is the scope to know when it will not be accessible anymore and you are not quite there yet) and there may be typos since I typed this from a phone.
If you really want to access the chars themselves, pass a char* with a size_t for the length of the array or use std::array if possible.
Right now the method fill_array is creating a local copy of array_to_fill, so any changes that you make to array_to_fill only happen in the local method. To change this, pass by pointer. This way the pointer gets copied instead of the whole array object. I didn't test this but it should look more like this:
void fill_array(char* array_to_fill){
...
}
You don't need to change anything in the main method.
To actually access the elements you can use [] notation. I.e. cout << array_to_fill[0] in the main method.
Edit: I think that change should work.
I am trying to read from a file using a shared_ptr pointer. I don't know how I can use insertion operator with it. Here is the code:
#include <iostream>
#include <regex>
#include <fstream>
#include <thread>
#include <memory>
#include <string>
#include <map>
using namespace std;
int main()
{
string path="";
map<string, int> container;
cout<<"Please Enter Your Files Path: ";
getline(cin,path);
shared_ptr<ifstream> file = make_shared<ifstream>();
file->open(path,ifstream::in);
string s="";
while (file->good())
{
file>>s;
container[s]++;
s.clear();
}
cout <<"\nDone..."<< endl;
return 0;
}
simply doing:
file>>s;
doesn't work.
How can I get the current value that file is pointing (I don't want to get the whole line, I just need to get the words and number of their occurrences this way).
By the way, I used shared_ptr to avoid closing the file myself, does making a pointer of this type, shared_ptr (smart) will it suffice not to write the file->close() myself ? or they are irrelevant?
The simplest way would be to use the dereference operator *:
(*file) >> s;
But looking at the code, I see no reason whatsoever to use a smart pointer. You could just use an ifstream object.
std::ifstream file(path); // opens file in input mode
Why do you want it to be a pointer? It's that that is causing you pain.
ifstream file;
file.open( ...
...
file>>s;
Streams are intended to be treated as value (rather than pointer types). The file will be closed when the destructor is called on the ifstream.
If you need to pass the stream object round other parts of your code, you simply use references (to the base class):
void other_fn( istream & f )
{
string something;
f>>something;
}
ifstream file;
other_fn( file );
Because the f parameter is a reference, it doesn't attempt to close the stream/file when it goes out of scope - that still happens in the scope that defines the original ifstream object.
I have written a piece of code which writes either to console or to a file depending upon the boolean value set by user.
The code looks like this.
#include <iostream>
#include <fstream>
int main()
{
bool bDump;
std::cout<<"bDump bool"<<std::endl;
std::cin>>bDump;
std::ostream* osPtr;
std::ofstream files;
if(bDump)
{
files.open("dump.txt");
osPtr = &files;
}
else
{
osPtr = &std::cout;
}
std::ostream& stream = *osPtr;
stream<<"hello";
if(bDump)
{
files.close();
}
return 0;
}
Here I am creating a std::ostream pointer and depending upon boolean value I am assinging address of either an ofstream object or std::cout. My only concern here whether the file operation like open or close are done properly or not. As I am new to c++ please help me out. Also point out if any bad programming practice is being followed here.
Its correct and works.
The main thing I would do differently is not to explicitly call close() as this is done automatically by the destructor.
You can simplify your code slightly (and get rid of the pointer) with the ternary operator;
#include <iostream>
#include <fstream>
int main()
{
bool bDump;
std::cout << "bDump bool"<<std::endl;
std::cin >> bDump;
std::ofstream files;
std::ostream& stream = (bDump) ? (files.open("dump.txt"), files)
: std::cout;
stream<<"hello";
}
There's no potential leak. However, if an exception is thrown by
stream<<"hello";
then
files.close();
will never be called, but for your specific example of code there's no concern. ofstream's destructor happens to call close() for you.
You did everything fine, but there is no need for the close() at the end, because in C++ we rely on destructors to clean up for us, and std::ofstream has one which closes the file automatically.
You can also omit the return 0; statement at the bottom of main() in C++: 0 (success, really) will be returned by default.