c++ Fstream string combination error - c++

I'm trying to make a function that writes a .ps1 script. I'm learning fstream functions and methods and I ran in to some troubles. I can't figure a way to make Fstream create the file at the given path (path1) and add in the same time a given name for the file and the extension.
void write(string s, string name) {
ostringstream fille;
fille << "$client = new-object System.Net.WebClient\n" << s;
string fil = fille.str();
ostringstream pat;
pat << path1 << "/" << ".ps1";
string path = pat.str();
fstream file(path);
if (file.open()) {
file << fil;
file.close();
}
}
I get the following error message (on the if line) during compilation:
no instance of overloaded function "std::basic_fstream<_Elem, _Traits>::open [with _Elem=char, _Traits=std::char_traits<char>]" matches the argument list
C2661 'std::basic_fstream<char,std::char_traits<char>>‌​::open': no overloaded function takes 0 arguments

First of all you don't use name parameter.
Second you don't define path1 variable.
And you do not need to call fstream::open method if you use fstream's initialization constructor.
void write( const std::string & s, const std::string & name )
{
std::string fil("$client = new-object System.Net.WebClient\n");
fil += s;
std::ostringstream path;
path << "C:/Folder/" << name << ".ps1";
std::ofstream file( path.str() );
if ( file.is_open() ) {
file << fil;
file.close();
}
}

if (file.open()) {
Look at a reference: as the error message states, there isn't a member function of fstream called open that takes no arguments.
This is probably a typo for:
if (file.is_open()) {

Related

I'm trying to write a char into a .txt file by using the ifstream getline function. But i get an Error Message

E0304 no instance of overloaded function "std::basic_ifstream<_Elem, _Traits>::getline [with _Elem=char, _Traits=std::char_traits]" matches the argument list
Im using a struct for the Information:
struct customer {
int id;
char name;
char phone;
char address;
};
And im trying to write the Customers Information into a .txt file:
void customerData()
{
ifstream ifs;
ifs.open("Customer.txt");
int custNum = 0;
while (!ifs.eof())
{
ifs >> cust[custNum].id;
ifs.ignore();
ifs.getline(cust[custNum].name, 100, ';');
ifs.getline(cust[custNum].phone, 15, ';');
ifs.getline(cust[custNum].id, 15, ';');
ifs.getline(cust[custNum].address, 1500);
custNum++;
}
}
I cant figure out how to fix the above posted Error on the getline functions.
There are big mistakes in your code that guys pointed out.
You are not writing to the file, you are reading it.
You cannot store a full name in a single character.
Actually, if you want to store this data, you should use character array or std::string.
So your struct will be like this :
struct customer {
int ID;
char name[100];
char phone_number[15];
char address[1500];
/*
OR
int ID;
std::string name;
std::string phone_number;
std::string address;
in this case it's better to use std::string instead of using 1500 characters for address
*/
}
Also, getline is not for writing to the file (as you said you want to write in file) , it is used for reading from the file.
So your customerData function will look like this:
// saving in file
ofstream ofs(Customer.txt);
// check if file is created
if(ofs.is_open(){
ofs << name << '\n';
ofs << address << '\n';
ofs << phone_number << '\n';
ofs << id << '\n';
// This is a simple way to store data in a file.
// There are other ways to store data in a file..
// I used this because you can use getline to read them and get the data as lines.
}

cpp compiler could not generate operator = for class fstreambase, istream and ostream

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.

Referencing cout to a variable location (file or cmd)

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);

Returning ifstream in a function

Here's probably a very noobish question for you: How (if at all possible) can I return an ifstream from a function?
Basically, I need to obtain the filename of a database from the user, and if the database with that filename does not exist, then I need to create that file for the user. I know how to do that, but only by asking the user to restart the program after creating the file. I wanted to avoid that inconvenience for the user if possible, but the function below does not compile in gcc:
ifstream getFile() {
string fileName;
cout << "Please enter in the name of the file you'd like to open: ";
cin >> fileName;
ifstream first(fileName.c_str());
if(first.fail()) {
cout << "File " << fileName << " not found.\n";
first.close();
ofstream second(fileName.c_str());
cout << "File created.\n";
second.close();
ifstream third(fileName.c_str());
return third; //compiler error here
}
else
return first;
}
EDIT: sorry, forgot to tell you where and what the compiler error was:
main.cpp:45: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here
EDIT: I changed the function to return a pointer instead as Remus suggested, and changed the line in main() to "ifstream database = *getFile()"; now I get this error again, but this time in the line in main():
main.cpp:27: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here
No, not really. ifstream doesn't have a copy constructor, and if you try to return one, that means copying the instance in your function out to wherever the return needs to go.
The usual workaround is to pass in a reference to one, and modify that reference in your function.
Edit: while that will allow your code to work, it won't fix the basic problem. Right now, you're mixing two rather different responsibilities into a single function: 1) obtain a file name, 2) open or create that file. I think if you separate those, the code will be simpler, and make it much easier to eliminate the source of the problem you're seeing.
Edit 2: Using a reference like this works perfectly well without an operator=. The general idea is something like:
int open_file(char const *name, fstream &stream) {
stream.open(name);
}
The assignment operator is neither necessary nor useful in this case -- we simply use the existing fstream via the reference. An operator= would be necessary if and only if we had to pass the argument to the ctor. With a stream, we can default construct a stream that doesn't connect to a file, and then use open to connect to the file after the fact.
bool checkFileExistence(const string& filename)
{
ifstream f(filename.c_str());
return f.is_open();
}
string getFileName()
{
string filename;
cout << "Please enter in the name of the file you'd like to open: ";
cin >> filename;
return filename;
}
void getFile(string filename, /*out*/ ifstream& file)
{
const bool file_exists = checkFileExistence(filename);
if (!file_exists) {
cout << "File " << filename << " not found." << endl;
filename = getFileName(); // poor style to reset input parameter though
ofstream dummy(filename.c_str();
if (!dummy.is_open()) {
cerr << "Could not create file." << endl;
return;
}
cout << "File created." << endl;
}
file.open(filename.c_str());
}
int main()
{
// ...
ifstream file;
getFile("filename.ext", file);
if (file.is_open()) {
// do any stuff with file
}
// ...
}
ifstream does not support copy construct semantics (that what the error message basically sais), so you cannot return an ifstream. Return an ifstream* instead, and pass to the caller the responsability to delete the allocate pointer.
As an option, ifstream may be extended and custom constructor added to new class.
I've extended it to create test resource stream, encapsulating test resource lookup inside of it.
// test_utils.h
class TestResourceStream : public std::ifstream {
public:
TestResourceStream(const char* file_path);
};
// test_utils.cpp
namespace fs = std::filesystem;
fs::path test_resource_path(const char* file_path) {
fs::path path{std::string{"tests/resources/"} + file_path};
if (!fs::exists(path))
throw std::runtime_error{std::string{"path "} +
fs::absolute(path).c_str() + " does not exist"};
return path;
}
TestResourceStream::TestResourceStream(const char* file_path)
:std::ifstream{test_resource_path(file_path).c_str()} {}
// usage in test
TEST_CASE("parse") {
std::list<GosDump::Expertise> expertises;
TestResourceStream stream("requests/page_response.json");
GosDump::Json::parse(expertises, stream);
REQUIRE(10 == expertises.size());
}

Spot the error in this file reading code (C++)

Can anyone please tell my why this method won't compile?
void Statistics::readFromFile(string filename)
{
string line;
ifstream myfile (filename);
if (myfile.is_open())
{
while (! myfile.eof() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}
else cout << "Unable to open file";
}
Should work, right? Yet, I always get the following error message:
Line Location Statistics.cpp:15: error:
no matching function for call to
'std::basic_ifstream<char, std::char_traits<char> >::
basic_ifstream(std::string*)'
any help would be greatly appreciated.
ifstream myfile (filename);
should be:
ifstream myfile (filename.c_str() );
Also, your read-loop logic is wrong. It should be:
while ( getline( myfile,line ) ){
cout << line << endl;
}
The eof() function that you are using is only meaningful after you have tried to read read something.
To see why this makes a difference, consider the simple code:
int main() {
string s;
while( ! cin.eof() ) {
getline( cin, s );
cout << "line is "<< s << endl;
}
}
If you run this and type ctrl-Z or ctrl-D to indicate EOF immediately, the cout will be performed even though no line has actually been input (because of the EOF). In general, the eof() function is not very useful, and you should instead test the return value of functions like getline() or the stream extraction operators.
Read the compiler error:
no matching function for call to 'std::basic_ifstream >::basic_ifstream(std::string*)
No matching function for call to: It can't find the function you're trying to call
std::basic_ifstream >:: - a member function of ifstream
:basic_ifstream(std::string*) - the constructor which takes a string pointer as its argument
So you try to create an ifstream by passing a string pointer to its constructor. And it can't find a constructor that accepts such an argument.
Since you're not passing a string pointer in the above, the code you've posted must be different from your actual code. Always copy/paste when asking about code. Typos make it impossible to figure out the problem. In any case, as I recall, the constructor does not accept a string argument, but only a const char*. So filename.c_str() should do the trick
Apart from that, you can do this a lot simpler:
ifstream myfile (filename);
std::copy(std::istream_itrator<std::string>(myfile),
std::istream_itrator<std::string>(),
std::ostream_iterator<std::string>(std::cout));
}
You should use fileName.c_str() so that you pass the const char* pointer to the myFile construction.
The ifstream constructor has the following signature
explicit ifstream ( const char * filename, ios_base::openmode mode = ios_base::in );
You need to pass in a constant char* and a mode, for example:
ifstream ifs ( "test.txt" , ifstream::in );
The mode is optional, since it has a default value defined, so you can just use:
ifstream myfile ( filename.c_str() );
The C++11 standard has resolved this defect. std::ifstream myfile(filename); should now compile, when filename has type std::string.