Command line arguments for C++? - 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.

Related

Several strange errors when building project using separate files C++

I'm able to build and run a particular project in Visual Studio when all of the code is in one main .cpp file, but when I separate the file into a class (.cpp and .h) and main .cpp file, I get several weird errors.
Here is the code when it's in 3 separate files, and not working:
//main.cpp
#include "student.h"
#include <string>
#include <iostream>
using namespace std;
int main()
{
std::cout << "Hello World!\n";
Student student;
student.setStudentID("A1C");
student.print();
}
//Student.h
#ifndef STUDENT_H
#define STUDENT_H
class Student
{
public:
Student();
string getStudentID() const;
void setStudentID(string studentID);
void print();
private:
string studentID;
};
#endif
//Student.cpp
#include "Student.h"
#include <string>
#include <iostream>
using namespace std;
Student::Student() {
this->studentID = "default";
}
string Student::getStudentID() const {
return this->studentID;
}
void Student::setStudentID(string studentID) {
this->studentID = studentID;
}
void Student::print() {
cout << "student ID: " << studentID << endl;
}
Here is the code when it's all in one main.cpp file, and working:
#include <string>
#include <iostream>
using namespace std;
class Student
{
public:
Student();
string getStudentID(); //const?
void setStudentID(string studentID);
void print();
private:
string studentID;
};
int main()
{
std::cout << "Hello World!\n";
Student student;
student.setStudentID("A1C");
student.print();
}
Student::Student() {
this->studentID = "default";
}
string Student::getStudentID() { //const?
return this->studentID;
}
void Student::setStudentID(string studentID) {
this->studentID = studentID;
}
void Student::print() {
cout << "student ID: " << studentID << endl;
}
Here are some of the errors that I get:
In the file Student.h you are using string, but string is not (yet) known. Read the Include file from top to bottom. Nowhere in the file is there any hint as to what string is supposed to be.
#include <string> in your Student.h file will introduce std::string to the file. From here on, std::string will be valid. But that's still not enough, since you are using string and not std::string in your class.
Do not include a using namespace std in your header file. If you do so, you force this namespace on all your "customers" of the header file. If any other file includes your Student.h with the using namespace in it, they will also get the using namespace... statement, even if they do not want it. Headerfiles should be self contained and should not introduce stuff, others may not want.
Also do not add a using std::string in your header file. While not as bad as a using namespace std there may be (and later in your professional life will be) instances, where you have different kinds of string. Perhaps a std::string and an oldfashioned::string or utf_something::string.
For simplicity, just write std::string studentId. IOW, use the fully qualified name of string in your header file.
In .cpp files these rules are somewhat relaxed, since no other file will include your .cpp file.
Bonus:
lookup #pragma once
always include system headers before your own headers
But beware of include order. Every header file should include all headers it needs, because ...
... the worst thing that can happen is that your code changes depending on the order in which you include headers. It should not matter. Including "Student.h" should introduce the Student class and nothing else.
Bonus++
take your time to learn about the C(++) preprocessor. #include is not really a C++ language statement like class, for etc... It is just a directive for the compiler to read the included file first.
Your compiler will have a switch (such as /P with Microsoft Visual C++) which will not compile the code but produce the actual included files and store the in a *.p (or something) file. It will let you see what the preprocessor does with your code before it is passed on to the compiler. It's an interesting and teaching experience. Try it. Don't be put off by the seemingly complex file. Search for "class Student" in that file and take it from there.
change student.h to this
//Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
class Student
{
public:
Student();
std::string getStudentID() const;
void setStudentID(std::string studentID);
void print();
private:
std::string studentID;
};
#endif
and it compiles and runs fine
BTW.
dont do this
void Student::setStudentID(string studentID) {
this->studentID = studentID;
}
have a naming convention for fields in a class so they are distinct
ie
//Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
class Student
{
public:
Student();
std::string getStudentID() const;
void setStudentID(std::string studentID);
void print();
private:
std::string studentID_; <<<<========
};
then
void Student::setStudentID(string studentID) {
studentID_ = studentID;
}
why, because
First its the accepted way in c++ world (the naming standard might differ, m_ prefix is common too)
second you might write this
void Student::setStudentID(string studentID) {
studentID = studentID;
}
which will compile but is maybe not what you mean. Of course here its obvious but in denser code, not so much

Why can't my .cpp file resolve variables declared in my .h file?

I just started learning how to write C++ code using CLion but I am running into some issues using classes. To my understanding, functions and methods are declared in the .h file and then they can be used in the .cpp file. If I do it this way then I get the error message "Can't resolve variable studentName". The message goes away if I declare the variable in the .cpp file but then doesn't that defeat the purpose of the .h file? Thank you in advance to whoever can help me resolve this issue.
Student.h
#ifndef PRACTICE_STUDENT_H
#define PRACTICE_STUDENT_H
#include <string>
class Student {
std:: string studentName;
int gradeLevel;
Student :: Student(std:: string studentName, int gradeLevel);
std:: string getName();
};
#endif //PRACTICE_STUDENT_H
Student.cpp
#include "Student.h"
#include <string>
Student:: Student(std:: string i_studentName, int i_gradeLevel){
gradeLevel = i_gradeLevel;
}
std:: string getName() {
return studentName;
}
main.cpp
#include <iostream>
#include "Student.h"
using namespace std;
int main(){
Student Carlton = Carlton.("Carlton", 16);
cout << Carlton.getName();
return 0;
}
getName is a member function of the Student class. To implement it in your .cpp file, you need to properly indicate that it belongs to that class:
std::string Student::getName() {
return studentName;
}

How to reference functions from other classes to add value to vector

I'm trying to add an Object to a vector using a setter function. My files are as follows
#ifndef ROOM_H
#define ROOM_H
#include <string>
#include <vector>
#include "User.h"
using namespace std;
class Room {
vector<User> users;
public:
Room();
void addToRoom(User user);
vector<User> getUsers();
};
#endif
addToRoom is just
users.push_back(user);
My user.h is
#ifndef USER_H
#define USER_H
#include <string>
#include <vector>
using namespace std;
class User {
string password;
string username;
public:
User(string user, string pass);
string getPass();
string getName();
};
#endif
I am trying to do
void
IRCServer::addUser(int fd, const char * user, const char * password, const char * args)
{
string myUsername = user;
string myPassword = password;
User *newUser = new User(myUsername, myPassword);
Room *newRoom = new Room();
newRoom->addToRoom(newUser);
return;
}
However, if I pass in newUser, I get an error saying there is no matching function, there is no known conversion for argument 1 from 'User*' to 'User'. Passing &newUser says that there is no known conversion for argument 1 from 'User**' to 'User'. Do I need to alter my vectors, or is there another way to do this?
I suspect you are coming from Java. In C++, a typename indicates a value, not a reference, and you don't need to use new to allocate an object:
User newUser(myUsername, myPassword); // creates a User
Room newRoom; // creates a Room
newRoom.addToRoom(newUser);
You are confusing a pointer to a User with the User itself. Your addToRoom function has a signature of void()(User), but you're calling it with the signature void()(User*).
In your particular example, there also isn't any reason to allocate memory with new. You can do everything by just creating objects on the stack.

Writing to String and Binary Files

Not too many have answered my questions at all. What I want to do a to use private copy constructors and assign them to variables as string or binary files.
Here is the code.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class President
{
private:
President() {};
President(const President&);
const President& operator=(const President&);
string Name;
public:
static President& GetInstance()
{
static President OnlyInstance;
return OnlyInstance;
}
string GetFile()
{
cout<<"Enter the name of the file you want to protect: ";
cin>>Name;
ofstream fsOut;
fsOut.open(Name, ios_base::out, ios_base::binary);
if(fsOut.is_open())
{
cout<<"Writing to binary file."<<endl;
fsOut<<Name<<endl;
cout<<"File open successful."<<endl;
fsOut.close();
}
return Name;
}
void SetFile(string InputFile)
{
Name=InputFile;
}
};
int main()
{
string Name;
President& OnlyPresident=President::GetInstance();
OnlyPresident.SetFile(Name);
cout<<President::GetInstance().GetFile()<<endl;
return 0;
}
I have compiled it and it was fine. However, it was not running correctly or it did not correspond to the file, in which I have typed. How could I protect files correctly using private copy constructors?
John P.

const char* usage in constructor

#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
{
}