If I have a simple function that prints to standard output maybe something like an integer or lets say a string like "Flipy flops", then is there a way to call the same function but instead of printing to standard output it prints the string "Flipy flops" to a file stream? (provided of course I've opened the file and all that stuff).
Yes just give it an ostream& parameter
void my_function(...)
{
cout << ...
}
becomes
void my_function(ostream& out, ...)
{
out << ...
}
Using fstream works just like cin and cout.
void SomeMethod( )
{
ofstream myFile( "myFile.txt" );
myFile << FlipyFlops( );
myFile.close( );
}
char* FlipyFlops( )
{
return "flipy flops"; // or "flippy floppies", whichever you prefer
}
ofstream is for output to a file and ifstream is for reading from a file.
Related
I am trying to concatenate the contents of file1 and file2 into file3 using operator overloading in c++, but it is giving me 3 errors as mentioned
below :
Error : compiler could not generate operator= for class 'fstreambase'
Error : compiler could not generate operator= for class 'istream'
Error : compiler could not generate operator= for class 'ostream'
Here is my code :
#include<iostream.h>
#include<conio.h>
#include<string.h>
#include<fstream.h>
class myfile
{
fstream file;
char filename[10],data[50];
public:
myfile()
{
//cout<<"File3 created\n";
}
myfile(char *fn)
{
strcpy(filename,fn);
}
void accept()
{
cout<<"\nEnter data for file "<<filename<<" :\n";
cin.getline(data,50);
file.open(filename,ios::out);
file<<data;
file.close();
}
void display()
{
char ch;
cout<<"Contents of "<<filename<<" :\n";
file.open(filename,ios::in);
while(file)
{
file.get(ch);
cout<<ch;
}
file.close();
cout<<endl;
}
myfile operator+(myfile &f2)
{
myfile f3("file3.txt");
fstream file1,file2,file3;
file1.open(this->filename,ios::in);
file2.open(f2.filename,ios::in);
file3.open(f3.filename,ios::out);
char ch;
while(file1)
{
file1.get(ch);
file3<<ch;
}
return f3;
}
};
void main()
{
clrscr();
myfile f1("file1.txt");
myfile f2("file2.txt");
myfile f3("file3.txt");
f1.accept();
f1.display();
f2.accept();
f2.display();
f3=f1+f2; //Those 3 errors generates on this line
f3.display();
getch();
}
Ps: The code is not yet complete(inside overloading function) and I'm using TurboC3 compiler
This is the question btw
What am I doing wrong here? Please help. Thank you.
You are over-engineering the problem. Modern C++, in particular, already makes copying file data around ridiculously easy.
To concatenate two files in memory:
Read the first file to a std::string
Read the second file to a std::string
Concatenate the strings
std::string read_file( const std::filesystem::path & filename )
{
std::ostringstream ss;
std::ifstream f( filename );
ss << f.rdbuf();
return ss.str();
}
std::string s = read_file(...) + read_file(...);
Steps 2 and 3 could be done at the same time
std::ostringstream ss;
std::ifstream f1(...);
std::ifstream f2(...);
ss << f1.rdbuf();
ss << f2.rdbuf();
std::string s = ss.str();
Write the string to the new file the usual way:
std::ofstream f3(...);
f3 << s;
To concatenate two files on disk:
std::ifstream f1(...);
std::ifstream f2(...);
std::ofstream f3(...);
f3 << f1.rdbuf() << f2.rdbuf();
Compilers
You really should have a modern C++ compiler working with C++17 at the bare minimum language standard.
However, if there is some reason you are constrained to an ancient, pre-standard C++ compiler, you can still use it. I never learned Borland’s pre-standard version of C++ file streams, so, alas, I cannot help much there. Read the documentation. It may not be possible to use the << operator to simply copy the stream buffer, but that is again just a read and write chars until EOF operation. You can make it into a little helper function taking both file objects by reference.
I'm currently working with std::fstream and have the following class:
(Note that the file is opened on constructor and should stay open during all read / write operation, only close when destructed).
MyFileClass
{
public:
MyFileClass( const std::string& file_name ) { m_file.open( file_name ) };
~MyFileClass() { m_file.close() };
bool read( std::string& content );
bool write( std::string& data );
private:
std::fstream m_file;
}
Now I have some sample code:
MyFileClass sample_file;
sample_file.write("123456");
sample_file.write("abc");
Result will be "abc456" because when the stream is open and we're writing with truncate mode it will always write on top of what's currently in there.
What I would like to have is to clean up everytime before we write so at the end I'll have only what's newest in there, in this case "abc".
And the current design is if the file is not there, it will be created only on write, but not on read (read will return error code if file is not present).
My write function is:
bool
MyFileClass::write( const std::string& data )
{
m_file.seekg( 0 );
if ( !m_file.fail( ) )
{
m_file << data << std::flush;
}
return m_file.fail( ) ? true : false;
}
Is there any way to clear the current content of the file before flushing the data?
to be able to write to the end of file use flag ios::app instead.
your code is full of mistakes:
1- you also trying to write a class string to file which is not correct. if you want to do so use serialization. in your case just convert it to constant character string.
2- your write and read functions defined to take a reference to string but you pass by value! (passing "12345" and "abc")
3- why you seek input pointer? (seekg)? as long as you are trying to write??!!
you may meant seekp() seeking output pointer; even in this case for what reason to do so? if you want to append text to the end use ios::app at the opening file.
if you want to clearing the content at any write operation then you should have two file streams one for reading and other for writing so the one for writing uses flag ios::out | ios::trunc. because ios::trunc does nothing in reading/writing mode.
4- if you really want to pass by reference then you must declare string objects in main passing to them values ("abc" and "12345" for each one) then pass these strings to write and read not the values.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class MyFileClass
{
public:
MyFileClass( std::string file_name );
~MyFileClass() { m_file.close(); }
bool read ( std::string content );
bool write( std::string data );
private:
std::fstream m_file;
};
MyFileClass::MyFileClass( std::string file_name )
{
m_file.open( file_name.c_str(), ios::out | ios::in | ios::app);
if(!m_file)
cout << "Failed to open file!" << endl;
}
bool MyFileClass::write( const std::string data )
{
if ( !m_file.fail( ) )
{
m_file << data.c_str() << std::flush;
}
return m_file.fail( ) ? true : false;
}
int main()
{
std::string sFile = "data.dat";
MyFileClass sample_file(sFile);
sample_file.write("123456");
sample_file.write("abc");
return 0;
}
This was a question from a coding challenge and I couldn't figure out the way to do it -
Implement encode() and decode() for a simple wire protocol per the prototypes below:
void encode ( const std::string& inputFilename, std::ostream& out );
void decode ( std::istream& in, const std:string& outputFilename );
Lets say there are several files and each contains a single message. As it already says from the prototype, encode must read single specified file from disk and place message in the ostream.
Decode must read single encoded message from istream and place it in the specified file. The contents of the two corresponding files must be identical.
It is easy if I could read the file in the encode method and place the data in a buffer and send them to another file in the decode method, but that is not the question. How do I read data from std::istream without someone actually typing the data on the console (like std::cin)?
Thank you in advance for your time and would love to see responses for this!
istream is a parent class for ifstream (input file stream) and istringstream (input string stream), so you can pass as a input parameter ifstream or istringstream. Do not need to use cin.
The same applies to out parameter, you can provide object of the ofstream or ostringstream. This is well know mechanism in C++ to abstract what particular type of stream you deal with.
I wrote a piece of code that works with the prototypes given in the question. I am sure there could be more ways of doing it but I thought I would share this.
class fileIO
{
private:
std::string inBuf;
public:
std::stringstream testbuf;
void encode(const std::string& inputFilename, std::ostream& out);
void decode ( std::istream& in, const std::string& outputFilename);
};
void fileIO::encode(const std::string& inputFilename, std::ostream& out)
{
//read from the input file and stream it to ostream
ifstream infile(inputFilename);
while(infile.good()){
getline(infile, inBuf);
out << inBuf;
}
cout << "Value stored in outBuf: " << inBuf << endl;
infile.close();
}
void fileIO::decode(std::istream& in, const std::string& outputFilename)
{
//read from istream and output it to a file
string val;
ofstream ofile(outputFilename);
in >> val;
cout<< "Read the istream contents: " << val << endl;
ofile << val;
ofile.close();
}
int main( int argc, char ** argv )
{
fileIO File;
string inputFile;
cout << "Enter input File Name: "<< endl;
cin >> inputFile;
File.encode(inputFile, File.testbuf);
File.decode(File.testbuf, inputFile);
return 0;
}
I am passing "a stringstream" to both encode and decode since istream and ostream are the parent class of stringstream. In this solution, the value from the input file is stored in the stringstream and gets passed on to decode where the value from the same stringstream gets written to output file.
I would like to write output either to the cmd window or a log file using one function only. The best I found to do this was this treed here.
So this code (minor changes from the referenced source) works for me to 90%:
void outputTest(){
cout << "Testing a new version of output." << endl;
std::ofstream realOutFile;
bool outFileRequested = true;
if(outFileRequested)
realOutFile.open("foo.txt", std::ios::out);
std::ostream & outFile = (outFileRequested ? realOutFile : std::cout);
outFile << "test" << endl;
keep_window_open();
}
Now instead of "foo.txt" I would like to write the file to another location. So I added the following:
string LogFile = config_.outputFiles+config_.projectName; //+"/RoomData.log"
ofstream realOutFile;
if (logFileRequested && config_.saveLogs){
realOutFile.open(LogFile+"/foo.txt", ios::out);
}
std::ostream & outFile = (logFileRequested ? realOutFile : cout);
I also tried passing only a string but in both cases I get that the function call does not match.
Is there a way to fix that?
Why is passing a string different than passing "string content"?
Thanks for your help.
P.S. Sorry I did not het the C++ code formatted properly.
Please see next link for function prototype: http://www.cplusplus.com/reference/fstream/ofstream/open/
open function receives const char* as 1st parameter.
This way it should work ->
string LogFile = config_.outputFiles+config_.projectName; //+"/RoomData.log"
ofstream realOutFile;
if (logFileRequested && config_.saveLogs){
LogFile += "/foo.txt";
realOutFile.open(LogFile.c_str(), ios::out);
}
std::ostream & outFile = (logFileRequested ? realOutFile : cout);
struct GPattern() {
int gid;
....
}
class Example() {
public:
void run(string _filename, unsigned int _minsup);
void PrintGPattern(GPattern&, unsigned int sup);
....
};
Eample::run(string filename, unsigned int minsup) {
for(...) { // some condition
// generate one GPattern, and i want to ouput it
PrintGPattern(gp, sup);
}
}
Example::PrintGPattern(GPattern& gp, unsigned int sup) {
// I want to ouput each GPattern to a .txt file
}
run is used to generate a GPattern accordingly.
What I want to output to a file is some texts that reconstruct the original GPattern.
I can't store all GPattern in advance and output all of them. I have to output one GPattern to a file when I generate it, but I don't know how to implement it.
I have tried to declare ofstream outGPatter("pattern.txt") in class Example, but it is of no use...
Well, ofstream is the right way to go:
Example::PrintGPattern(GPattern& gp, unsigned int sup) {
ofstream outGPattern("pattern.txt")
outGPattern << gp.gid; << " " << gp.anotherGid << " " ....
outGPattern.close()
}
Have you looked at the correct place for the pattern.txt? It should either be in the folder where your .exe is, or in the folder where all your .h and .cpp files are (for VS at least).
If you want to write all patterns into the same file then you need to make sure you append (and not overwrite) the pattern.txt
ofstream outGPattern("pattern.txt",ios::app)
So you can first make an ofstream without ios::app (to clear the textfile) at the start of your program. Then you construct all other ofstreams with ios::app to append new text, instead of overwriting it.
Alternatively you can make the ofstream a member variable of Example. Then you construct it only once.
I think you can use append mode, such as:
ofstream outGPattern;
outGPattern.open("GPattern.txt", ios::app);
The way I see it, you want to append information of multiple GPattern and you simply need to set the I/O mode to ios::app in the constructor.
struct GPattern {
int gid;
friend ostream& operator <<(ostream& o, GPattern gp) {
return o << "(gid=" << gp.gid << ")";
}
...
}
Example::PrintGPattern(GPattern& gp, unsigned int sup) {
ofstream fout("pattern.txt", ios::app)
fout << gp << endl;
fout.close()
}