const char* usage in constructor - c++

#include "Board.hpp"
#include <iostream>
using namespace std;
Board::Board (const char* filename){
filename = "puz1.txt";
Board::fin (filename);
if(!fin) fatal("Error in opening the file");
}
This is my cpp file...my hpp file is:
#ifndef BOARD_H
#define BOARD_H
#include <iostream>
using namespace std;
#include "tools.hpp"
#include "square.hpp"
class Board {
private:
SqState bd[81];
ifstream fin;
public:
Board(const char* );
ostream& print(ostream& );
};
inline ostream& operator <<(ostream& out, Board& b) { return b.print(out);}
#endif //Board.hpp
I got the below errors while I compile:
Error at line in cpp filename = "puz1.txt".
and error is:
const char* shadows a //parameter.
Error at line in cpp Board::fin (filename);
and error is:
no match call to //(std::basic_ifstream})
How do I fix them?

You can only initialize fin in the contructor initialization list. You also need to #include <fstream>. This would work:
Board::Board (const char* filename): fin(filename)
{
....
}
It is unclear why you are setting filemane to something different to what is passed in the constructor. If you want a default parameter, use
Board::Board (const char* filename="puz1.txt"): fin(filename) {}

About the first error:
filename = "puz1.txt";
You are supposed to pass the filename as an argument, not to assign it there. If you just need to use "puz1.txt" then use than instead of filename.
The second error:
Board::fin (filename);
You can't initialize the ifstream object like that. Simply call open().
fin.open("puz1.txt");
if(fin.is_open()) // you can pass additional flags as the second param
{
}

Related

How to initialize an object that declared as const on header file?

I want to initialize std::ifstream object only in the main() function after declare it in the header.
Is there any way to do it in C++?
I wrote this but it's not compiling
//header.h
#include <iostream>
#include <fstream>
class class1{
static const std::ifstream fs;
};
//proj.cpp
#include "header.h"
void main(){
class1::fs("Employee.txt")
}
static variables need to be defined at global scope, not inside a function.
main should also return int not void.
A const std::ifstream doesn't make much sense as most of the methods you would need to use are non-const so wouldn't be callable on your const stream.
Fixing these issues gives:
//header.h
#include <iostream>
#include <fstream>
class class1{
static std::ifstream fs;
};
//proj.cpp
std::ifstream class1::fs("Employee.txt");
int main(){
return 0;
}
If you want to open the stream in main then you need to do:
const std::ifstream class1::fs;
int main(){
class1::fs.open("Employee.txt");
return 0;
}

Command line arguments for C++?

For my assignment, it says that I am to use the command line argument ./a.out user1.txt (the text file name can change) in my main.cpp.
I have the following in my main.cpp
int main(int argc, char* argv[]){
string name;
name = argv[1];
}
but don't know how I can get name into my BBoard setup function in BBoard cpp
#include "BBoard.h"
#include <fstream>
#include <algorithm>
using namespace std;
User user_l;
BBoard::BBoard(){
title = "Default BBoard";
vector<User> user_list;
User current_user;
vector<Message> message_list;
}
BBoard::BBoard(const string &ttl){
title = ttl;
}
void BBoard::setup(const string &input_file){
ifstream fin;;
fin.open(input_file);
while(!fin.eof()){
user_list.push_back(user_l);
}
}
with BBoard header here
#ifndef BBOARD_H
#define BBOARD_H
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class User
{
public:
User() { }
User(const std::string& _name, const std::string& _pass)
: name(_name), pass(_pass)
{ }
friend bool operator==(const User& lhs, const User& rhs)
{
return (lhs.name == rhs.name) &&
(lhs.pass == rhs.pass);
}
private:
std::string name;
std::string pass;
};
class Message{
};
class BBoard{
private:
string title;
vector<User> user_list;
User current_user;
vector<Message> message_list;
public:
BBoard();
BBoard(const string &ttl);
};
#endif
Edit: How do I use an object in main cpp to send over name to my BBoard function? When I try including main cpp into my board cpp, I get errors.
What about creating an BBoard and then calling the setup function:
if (argc > 1) {
string name = argv[1];
BBoard board;
board.setup(name);
}
You're so close. You simply need to edit your main() function to create a BBoard object, and pass the name to it the same way you pass argv[1] to std::string. You can then call functions on that object, or pass that object to other functions.
Style advice:
What should happen if somebody forgets to pass the filename to the program? As it stands, you crash. It's pretty easy to tell the user what's wrong and bail if argc is only 1:
if (argc == 1) {
cout << "usage: a.out file.txt\n";
return 1;
}
Not all programmers use using namespace std. There's nothing wrong with doing so in .cpp files, but I personally get upset when #include-ing a header file has the effect of calling using namespace XXX for me without my consent. As it is, your header file already fully qualifies things in the std namespace, so you can remove that line from your header without needing to make other changes. To keep me from getting upset when I use your header, you simply need to remove using namespace std from the header and use std::vector instead of simply vector.

Simple C++ logging class - ostream reference initialization

I've read several similar questions here that have been answered, but I don't grok yet, so please bear that in mind before closing as duplicate :). I want a simple Log object with a Print() method. If Log is constructed with no parameters, logging is to cout. Otherwise, parameters describe a file to which logging is done.
(I suspect part of the problem is understanding the relationship between all the stream classes.)
When compiled, error is:
Log.cpp:11:23: error: invalid initialization of reference of type ‘std::ofstream& {aka std::basic_ofstream<char>&}’ from expression of type ‘std::ostream {aka std::basic_ostream<char>}’
Log.h:
#ifndef LOG_H
#define LOG_H
#include <string>
#include <fstream>
class Log {
public:
Log();
Log(const char*, const char*);
void Print(const char* msg,...);
private:
// instance contains a reference to ostream
std::ofstream& output_stream;
};
#endif
Log.cpp:
#include "Log.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <fstream>
// Constructor w/no parms = log to cout
Log::Log() :
output_stream(cout)
{}
// Constructor w/parms = log to file
Log::Log(const char* dir, const char* file) {
string output_file_name = string(dir) + "/" + string(file);
output_stream.open(output_file_name.c_str(), std::ofstream::out);
}
// Print() sends output to the stream (we'll do printf semantics later)
void
Log::Print(const char* msg,...) {
output_stream << msg << endl;
}
cout is not of type ofstream, so you cannot bind an ofstream reference to it. output_stream should be type ostream& instead, which will allow it to refer to either cout and a file stream, since ofstream is a subclass of ostream.
Also, in the case that the user provides a filename, you still need something for the reference to refer to, you can't just use it as is. I recommend that you store an actual ofstream object, (or a unique_ptr<ofstream>), and make output_stream refer to it. Make sure you declare the ofstream object before the ostream reference in your class definition, otherwise you will have undefined behavior when you try to bind the reference in the initialization list. Or you can make it a pointer, instead of a reference, and assign it in the body of the constructor.
I suggest shuffling filebufs or other streambufs.
#include <string>
#include <ostream>
#include <fstream>
class Log {
public:
Log();
Log(const char*, const char*);
void Print(const char* msg,...);
private:
// instance contains a reference to ostream
std::ostream output_stream;
std::ofstream _file;
};
And the cpp:
#include <iostream>
#include <string>
#include <fstream>
// Constructor w/no parms = log to cout
Log::Log()
: output_stream(std::cout.rdbuf())
{}
// Constructor w/parms = log to file
Log::Log(const char* dir, const char* file)
: output_stream(nullptr)
{
std::string output_file_name = std::string(dir) + "/" + std::string(file);
_file.open(output_file_name.c_str(), std::ofstream::out);
output_stream.rdbuf(_file.rdbuf());
}
// Print() sends output to the stream (we'll do printf semantics later)
void Log::Print(const char* msg,...) {
output_stream << msg << std::endl;
}

how to initialize static reference to std::ofstream?

I have a class Cl with public member
static std::ofstream &_rout;
In main file
ofstream out("output.txt");
ofstream& Cl::_rout(out);
But I have a compilation error: illegal definition or redefinition.
How can I correct it?
Try this.
Logger.h
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
class Logger{
public:
static void open( const string & logFile);
static void close();
// write message
static void write( const string & message);
private:
Logger();
ofstream fileStream;
//Logger instance (singleton)
static Logger instance;
};
Logger.cpp
#include "Logger.h"
Logger Logger::instance;
Logger::Logger(){}
void Logger::open( const string& logFile){
instance.fileStream.open(logFile.c_str());
}
void Logger::close(){
instance.fileStream.close();
}
void Logger::write(const string& message){
ostream& stream = instance.fileStream ;
stream << message<< endl;
}
main.cpp
#include "Salida/Logger.h"
int main(){
Logger::open(path);
Logger::write("text");
Logger::close();
return 0;
}
You can only set the reference at the static/global scope
#include<CL.h>
ofstream& Cl::_rout(out);
int main() {
// ...
}
It is not possible to re-set a reference after it was declared (and initialized). You could achieve what you are after by using pointers instead of references:
class Cl {
static std::ofstream* _rout;
};
std::ofstream* CL::_rout = NULL;
int main() {
ofstream out("output.txt");
Cl::_rout = &out;
}
Note that the pointer will be valid only until out goes out of scope. If this is an issue, allocate the memory dynamically:
ofstream* out = new ofstream("output.txt");
Cl::_rout = out;
And don't forget to delete it when you no longer need the object to avoid memory leaks
Well, you could use the following approach:
#include <fstream>
class CI
{
public:
static std::ofstream &_rout;
};
static std::ofstream out("output.txt");
std::ofstream& CI::_rout = out;
int main()
{
}
The problem with this, however, is that the name of the output file is fixed (hard-coded into the program).
I suggest that you use a pointer instead of a reference:
#include <cstddef>
#include <fstream>
class CI
{
public:
static std::ofstream *_rout;
};
std::ofstream* CI::_rout = NULL;
int main()
{
const char *output_file = "output.txt";
std::ofstream out(output_file);
CI::_rout = &out;
}

why am I getting an error when I pass an ifstream&?

I'm trying to code a simple program that uses an ifstream and scanner to read a text file. For some reason I'm getting this error: "In passing argument 1 of 'bool ReadVector(std::ifstream&, Vector<double>&)'". Any idea what I've done wrong?
#include <iostream>
#include <fstream>
#include <string>
#include "scanner.h"
#include "genlib.h"
#include "simpio.h"
#include "vector.h"
// prototype
bool ReadVector(ifstream & infile, Vector<double> & vec);
// main
int main(){
Vector<double> vec;
ifstream infile;
infile.open("SquareAndCubeRoots.txt");
if (infile.fail()) Error("Opening file screwed up");
bool foo = ReadVector(&infile, &vec); // stub
cout << foo;
infile.close();
return 0;
}
// stub
bool ReadVector(ifstream & infile, Vector<double> & vec){
return true;
}
ReadVector accepts a reference, but you are giving a pointer. Just call
bool foo = ReadVector(infile, vec);
You're trying to pass a pointer, while the argument is a reference. Remove address-of operators (ReadVector(infile, vec)).