I have a vector of class "Account". It's private to a class BankingSystem. Here's how I have them defined.
Account Class:
struct newAccount
{
string firstName;
string lastName;
string accountPass;
int accountID;
float accountBalance;
}; //end of structure newAccount
class Account
{
string firstName;
string lastName;
string accountPass;
int accountID;
float accountBalance;
private:
int depositAmount;
int withdrawAmount;
public:
static newAccount createAccount( int, float, string, string, string ); //creates new account
void deposit( int ); //deposits money into account
void withdraw(int); //withdrawals money from account
int retdeposit() const; //function to return balance amount
friend class BankingSystem;
}; //end of class Account
BankingSystem Class:
class BankingSystem
{
int accountID;
char fileName;
private:
std::vector<Account> accounts_;
public:
static void addAccount();
static void storeAccount( newAccount );
void deleteAccount();
void accountInquiry();
void saveAccounts();
void loadAccountsFromFile();
friend class Account;
}; // end of class BankingSystem
I'm trying to store new accounts in the vector in this manner.
1) addAccount function in BankingSystem.h
void BankingSystem::addAccount()
{
int ID;
float balance;
std::string pass, first, last;
cout << "\n\t Enter the Account ID: ";
cin >> ID;
cout << "\n\t Enter the passcode: ";
cin >> pass;
cout << "\n\t Enter Client's first name: ";
cin >> first;
cout << "\n\t Enter Client's last name: ";
cin >> last;
cout << "\n\t Enter starting balance: ";
cin >> setw(6) >> balance;
storeAccount( Account::createAccount( ID, balance, pass, first, last ) );
return;
}
2) createAccount in Account.h
newAccount Account::createAccount( int ID, float balance, string first, string last, string pass )
{
newAccount a;
a.accountID = ID;
a.accountBalance = balance;
a.firstName = first;
a.lastName = last;
a.accountPass = pass;
return a;
}
3) storeAccount in BankingSystem.h
void BankingSystem::storeAccount( newAccount a )
{
accounts_.push_back(a);
}
Everything is working fine except storing data in the vector. The line accounts_.push_back(a); has this error; "invalid use of member 'accounts_' in static member function."
A static method does not have access to a class instance (no this) so inside of storeAccount and addAccount the member accounts_ does not exist.
FYI: nothing after a return statement will be executed so the line cout << "\n\t Account ID: " << a.accountID << " added successfully."; is rather useless in your current code.
Consider the following implementation for reference:
using namespace std;
class Account
{
private: // data members
string firstName;
string lastName;
string accountPass;
int accountID;
float accountBalance;
public:
// constructor that initializes members
Account(int id, float bal, const string& fname, const string& lname, const string& pass)
: accountID(id), accountBalance(bal), firstName(fname), lastName(lname), accountPass(pass) {}
}; //end of class Account
class BankingSystem
{
private: // data members
int accountID;
char fileName;
vector<Account> accounts_;
public:
void addAccount()
{
int ID;
float balance;
string pass, first, last;
// prompt input, initialize values, etc
// construct a new Account from values and add it to vector
accounts_.push_back(Account(ID, balance, first, last, pass));
}
void storeAccount( const Account& newAccount )
{
// add an already initialized account
accounts_.push_back(newAccount);
}
}; // end of class BankingSystem
A static member function doesn't have any special access to member variables like accounts_.
addAccount and storeAccount are static member functions. You must have made them so for a reason but it was a mistake. Remove that static and you will remove this error. I'm guessing you'll then have a different problem. If so ask another question and find out the right way to solve that.
The method is static, so it has no "this" pointer, so it has no idea what object you want to access the accounts_ variable of. Also, you will never see that printout on createAccount() because it's after the return call.
Related
I have a project in my C++ class - we're supposed to make a "simple student management system" comprised of a class for the student attribute variables, and a main function with a branch statement that lets the user input names and IDs for the students. I know that I need to use an array to make "slots" for the students, and that my branch statements need to let the user input values into those slots, but I'm not exactly sure how to do it. Here is the code that I have so far.
#include <string>
#include <iostream>
#include <utility>
using std::string;
using std::cin;
using std::cout;
using std::endl;
struct Student {
private:
int id;
string name;
int birthday;
public:
Student()
{
id = 0;
birthday = 0;
}
Student(int id, string name, int birthday)
{
//set your parameters to the class variables
this->id = id;
this->name = name;
this->birthday = birthday;
}
void setID(int id)
{
this->id = id;
}
int getID() {
return id;
}
void setName(string name)
{
this->name = name;
}
string getName()
{
return name;
}
void setBirthday(int birthday)
{
this->birthday = birthday;
}
int getBirthday()
{
return birthday;
}
void output() {
cout << id << name << birthday << endl;
}
};
int main() {
Student arr[50];
cout << "Student Management System" << endl;
cout << "Press 'a' to add a student" << endl;
char a = 1;
int y = 1;
while (a == 'a') {
switch (y)
{
cout << "Input Student ID:";
cin >> id;
}
}
}
What I'm focusing on most is the fourth line from the bottom. I was told that I need to use my setters, so I said that I want what my user inputs to be treated as the value of the ID variable that I set in the class. However, when I wrote this out, I was given an error. Could someone tell me what the issue is?
You should try to get your switch statement working correctly. To use classes setters, you can store the user input to a temporary variable then from your one student you can call the member function. i.e. in your case:
arr[index].setID(tempInputVariable);
There is no id in your main function or as a global variable.
I suggest you overload operator >> to have your structure extract its members from the data stream:
struct Student
{
//...
public:
friend std::istream& operator>>(std::istream& input, Student& s);
};
std::istream& operator>>(std::istream& input, Student& s)
{
input >> s.id;
input >> s.name;
input >> s.birthday;
return input;
}
Although the above code doesn't use setters, it is the preferred method for inputting data.
The overload can be modified to use setters (kind of overkill):
std::istream& operator>>(std::istream& input, Student& s)
{
int id;
input >> id;
s.setID(id);
std::string name;
input >> name;
s.setName(name);
int birthday;
input >> birthday;
s.setBirthday(birthday);
return input;
}
If you don't like the overload, you can perform the steps in your main function:
//...
Student new_student;
//...
{
int student_id;
std::cout << "Input Student ID:";
std::cin >> student_id;
new_student.setID(student_id);
std::string student_name;
std::cout << "Input Student Name: ";
std::cin >> student_name;
new_student.setName(student_name);
int student_birthday;
std::cout << "Input Student Birthday: ";
std::cin >> student_birthday;
new_student.setBirthday(student_birthday);
}
Edit 1: The Database
You'll probably need to store or remember the students. This is easy using the first method above:
std::vector<Student> database;
Student s;
std::cout << "Enter student information (ID, Name and birthday, separated by spaces:\n";
std::cin >> s;
// Append to the database
database.push_back(s);
If you haven't learned std::vector you can try an array:
const size_t MAXIMUM_STUDENTS = 16;
Student database[MAXIMUM_STUDENTS];
size_t database_index = 0;
//...
Student s;
std::cout << "Enter student information (ID, Name and birthday, separated by spaces:\n";
std::cin >> s;
// Append to database
database[database_index] = s;
++database_index;
#include<iostream>
#include<string>
using namespace std;
/*this program takes a bank customer's info with the use of a class*/
//class definition
class BankCustomer
{
public:
BankCustomer(); //constructor for BankCustomer class
void fullname(string, string);
string firstname();
string lastname();
bool setsocial(int s); //accept a arg. of int type
int getsocial();
private:
string fname, lname, SSNlength; //can't be changed by client; sensitive info should be made private
};
//class implementation
BankCustomer::BankCustomer(){}
void BankCustomer::fullname(string f, string l)
{
fname=f;
lname=l;
}
string BankCustomer::firstname()
{
return fname;
}
string BankCustomer::lastname()
{
return lname;
}
bool BankCustomer::setsocial(int s)//function verifies that entered SSN is 9 digits long by counting # of digits of entered SSN
{
int count, SSNlength;
while(s != 0)
{
s /=10;
++count;
if(count == 9)
{
cout <<"\nValid SSN Entered!" << endl;
SSNlength=s;
return true;
}
}
}
int BankCustomer::getsocial()
{
return SSNlength;
}
//client program
int main()
{
BankCustomer customer; //customer declared as object of BankCust class
string firstname, lastname;
int ssn, s;
//data assignment
cout <<"\n Enter First Name\n" << endl;
cin >> firstname;
cout<<"\n Enter Last Name\n"<< endl;
cin >> lastname;
customer.fullname(firstname,lastname);
do
{
cout<<"\nEnter 9-Digit SSN"<< endl;
cin >> ssn;
customer.setsocial(ssn);
}
while(!customer.setsocial(ssn)); //function will repeat as long as entered user ssn forces setsocial() to evaluate it as false
//data ouput
cout <<"\nFirst Name: "<<customer.firstname()<<"\n"<< endl;
cout <<"\nLast Name: "<<customer.lastname()<<"\n"<< endl;
cout <<"\n SSN is: "<<customer.getsocial()<<"\n" << endl;
}
The error is targeting BankCustomer::getsocial(). The variable SSNlength is declared as an int type and getsocial() has a return type of int. I don't see anywhere in my code where I intend to convert SSNlength to a string. Is it how I'm passing and handling data with the setsocial() function?
That is wrong:
int BankCustomer::getsocial()
{
return SSNlength;
}
since SSNlength is a member variable of the class BankCustomer of type string, visible from BankCustomer::getsocial, even if not declared in the method. That how C++ works.
So the compiler complains that it cannot convert a string to an int (what you want to return).
this is where you declare it:
private:
string fname, lname, SSNlength; //can't be changed by client; sensitive info should be made private
Given the name of the variable, I suspect that you wanted to write:
private:
string fname, lname;
int SSNlength; //can't be changed by client; sensitive info should be made private
be careful, there's an auto variable called the same way in another method.
I suggest a naming rule for members to avoid all that. Example: prefix all members with m_:
private:
string m_fname, m_lname
int m_SSNlength; //can't be changed by client; sensitive info should be made private
These are my two classes that hold my data:
Base Class holding basic person data:
#ifndef H_personType
#define H_personType
#include <string>
using namespace std;
class person
{
public:
//get functions
string getName() const;
string getId() const;
string getAge() const;
string getGender() const;
string getPhone() const;
string getEmPhone() const;
string getAddress() const;
string getEmail() const;
string getEmContact() const;
//set functions
void setName(string, string, string);
void setId(string);
void setAge(string);
void setGender(string);
void setPhone(string);
void setEmPhone(string);
void setAddress(string, string);
void setEmail(string);
void setEmContact(string, string);
//constructors
person();
person(string, string, string,
string, string, string, string,
string, string, string,
string, string, string,
string, string);
private:
string firstName;
string lastName;
string middleName;
string id;
string age;
string phone;
string address;
string streetNumber;
string streetName;
string gender;
string email;
string emergency_phone;
string emergencyFirstName;
string emergencyLastName;
string emergency_contact;
};
Derived Class student that holds member functions to modify data and private members specific for a student.
#ifndef H_studentType
#define H_studentType
#include "personType.h"
#include <vector>
using namespace std;
class student: public person
{
public:
//void sortRecords();
friend int checkSize();
void addRecords();
void input(istream&, int);
void print(ostream&) const;
void printRecords(ostream&);
void loadData();
void displayOnScreen();
void searchID(string, int);
student();
student(string, string, string,
string, string, string, string, string, string,
string, string, string, string, string, string,
string, string, string, string);
protected:
vector<string> tempVec[11];
private:
string gpa;
string hobbies;
string major;
string honors;
vector<student> students;
};
#endif
Those two classes are what hold my data. I use an input function to read a simple text input file that holds rows of data for a student, think name, age etc.. the input function fills the vector of type student.
Input function:
void student::input(istream& inF, int size)
{
//local variables
student stud;
string first, middle, last, addressNum, addressStreet,
phone, gender, email, emContactFirst, emContactLast,
ph, emPhone,ID, age;
while (!inF.eof())
{
for (int index = 0; index < size; index++){
inF >> first >> last >> middle;
stud.setName(first, last, middle);
inF >> ID;
stud.setId(ID);
inF >> age;
stud.setAge(age);
inF >> phone;
stud.setPhone(phone);
inF >> addressNum >> addressStreet;
stud.setAddress(addressNum, addressStreet);
inF >> gender;
stud.setGender(gender);
inF >> email;
stud.setEmail(email);
inF >> emPhone;
stud.setEmPhone(emPhone);
inF >> emContactFirst >> emContactLast;
stud.setEmContact(emContactFirst, emContactLast);
inF >> stud.gpa >> stud.hobbies >> stud.major;
students.push_back(stud);
}
}
}
After this all my data from my input file is stored in the vector of type student, basically a vector of classes that hold my data. In order to perform manipulation on this data (search by studentID, delete record by studentID, modify record by student ID) I want to load it from the vector of classes into an array of string vectors. This is where my mind is melting and I've been stuck for a long time. Here is my load data function and displayOnScreen that simply won't cooperate. The display on screen function is simply for debugging purposes so I can see my filled array printed out.
void student::loadData()
{
int i = 0;
for (vector<student>::iterator it = students.begin(); it != students.end(); it++)
{
for (i = 0; i < 11; i++)
{
cout << "ID = " << it->getId();
tempVec[i].push_back(it->getName());
tempVec[i].push_back(it->getId());
tempVec[i].push_back(it->getAge());
tempVec[i].push_back(it->getPhone());
tempVec[i].push_back(it->getAddress());
tempVec[i].push_back(it->getEmail());
tempVec[i].push_back(it->getEmPhone());
tempVec[i].push_back(it->getEmContact());
tempVec[i].push_back(it->gpa);
tempVec[i].push_back(it->honors);
tempVec[i].push_back(it->major);
}
if (i = 10)
break;
}
}
void student::displayOnScreen()
{
for (vector<string>::iterator it = tempVec[1].begin(); it != tempVec[1].end(); it++){
for (int u = 0; u < 11; u++)
{
cout << tempVec[1].at(u) << " ";
}
cout << endl;
}
}
Please, I know this is a huge question and any assistance is much appreciated.
This is an anti-pattern
while (!inF.eof())
{
}
See: Why is iostream::eof inside a loop condition considered wrong?
This is a bug:
if (i = 10) // Notice this sets i to 10 which is true
break; // So this breaks the first time.
// Use == for testing (notice two of them)
You can stop this bug by making sure you fix all your warnings.
Compile your code with all warnings enabled and ask the compiler to treat warnings as errors (as they are logical errors in your code).
If you want to display a vector of student it is easier to do this:
for(auto const& s: students)
{
std::cout << s << std::endl;
}
Then define the output operator for student
std::ostream& operator<<(std::ostream& str, student const& s)
{
str << s. getName() << ... etc ...;
return str;
}
You should probably also define the input operator for student that way you can localize the reading of a student to the operator>>
PS: I f you want a code review, but only once it is working.
I am new to vectors and new to classes.That being said, I have found some posts about how to create a vector of objects. I want to know how would one go about creating a vector of objects from user input? Say the program asks the user to give the number of employees(class) he/she wants to create. The user wants to add 5 employees. So user must input the employee's last name and first name. I have a for loop in mind but I am not sure how to go about grabbing the user input (Maybe using getline and push_back?) and storing it in the vector.
//Lets say class.h looks like this
class Employee
{
private:
string lastName;
string firstName;
public:
void setLastname(string);
void setFirstname(string);
string getLastname() const;
string getFirstname() const;
}
Your Employee class should have a constructor. When gathering input, you need all the constructor arguments. Then, to add an Employee to a vector<Employee>, call employees.emplace_back( ctor-arguments ).
std::vector has a nice method called emplace_back, which
Appends a new element to the end of the container. The element is constructed through std::allocator_traits::construct, which typically uses placement-new to construct the element in-place at the location provided by the container.
So the only thing you are missing to be able to use it is an appropriate constructor.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Employee
{
private:
string firstName;
string lastName;
public:
void setLastname(string);
void setFirstname(string);
string getLastname() const{return lastName;}
string getFirstname() const{return firstName;}
//create a constructor
Employee(string firstName, string lastName)
: firstName(firstName), lastName(lastName)
{}
};
int main()
{
vector<Employee> emp;
int count = 0;
cout << "Enter the amount of employees to add:" << endl;
cin >> count;
string firstName, lastName;
for(int i = 0; i < count; ++i)
{
cout << "Please enter the first and last names" << endl;
cin >> firstName;
cin >> lastName;
emp.emplace_back(firstName, lastName);
}
for(const Employee & e : emp)
{
cout << "Employee:" << endl;
cout << e.getFirstname() << " " << e.getLastname() << endl;
}
}
Other users have provided a good examples explaining how to use emplace_back in modern C++.
If you work with pre-C++11 versions, there is no emplace_back method. In this case, you can collect data in your vector manually using old-style push_back. You can simply define a vector:
vector<Employee> employees;
Then, you can read your data line by line, create new objects, fill them according to your business logics and append to your vector:
int n;
int main()
{
cout << "Enter number of employyes: "; cin >> n;
for (int i = 0; i < n; i++)
{
std::string s;
Employee employee; // Create object
cout << "Employee " << i << ". First name: "; cin >> s;
employee.setFirstname(s); // Fill object
cout << "Employee " << i << ". Last name: "; cin >> s;
employee.setLastname(s); // Keep filling it
cout << "Welcome, " << employee.getFirstname() << " " << employee.getLastname() << endl;
employees.push_back(employee); // Add to vector
}
}
You can also define a constructor taking both firstname and lastname as arguments to make it easier to work with.
class Employee
{
private:
string lastName;
string firstName;
public:
Employee(string paramLastName, string paramFirstName) : lastName(move(paramLastName)), firstName(move(paramFirstName)) {}
void setLastname(string);
void setFirstname(string);
string getLastname() const;
string getFirstname() const;
}
You need a constructor that takes two strings as input. Obviously you could do without this but this reduces verbosity.
Employee(string paramLastName, string paramFirstName) :
lastName(move(paramLastName)), firstName(move(paramFirstName)) {}
You will need to call it in this way.
vector<Employee> inp;
string tmp1, tmp2;
while(std::cin>>tmp1 >> tmp2) {
inp.emplace_back(tmp1, tmp2);
}
(This is assuming that you will compile with c++11 support)
I have a Person class that has the private data members id, lastName, firstName, and age. I created file containing 50 Person objects with "unassigned" and 0 for the data members, using this function:
void createPersonFile(ofstream &outputPersonFile){
Person blankPerson;
blankPerson.setID(0);
blankPerson.setFirstName("unassigned");
blankPerson.setLastName("unassigned");
blankPerson.setAge(0);
for (int x = 0; x < 50; x++)
outputPersonFile.write(reinterpret_cast<const char *>(&blankPerson),
sizeof(Person));
}
I have to create functions that will let me write a new Person, update a Person, delete a Person, and display a Person but I don't know how to use the seekp function to write them. This is what I have for a function that will write a new Person to the file. I already have two separate functions not shown here that I am calling to open input/output files.
void writeNewPerson(ofstream &outputPersonFile){
int inputID;
int userNumber;
string userInput;
Person person;
cout << "Please enter a record number (1-50): ";
cin >> inputID;
cout << "Enter the person's first name: ";
cin >> userInput;
person.setFirstName(userInput);
cout << "Enter the person's last name: ";
cin >> userInput;
person.setLastName(userInput);
cout << "Enter the person's age: ";
cin >> userInput;
person.setAge(userNumber);
cout << endl;
outputPersonFile.seekp( WHAT GOES HERE??? );
outputPersonFile.write( reinterpret_cast<const char*>(&person), sizeof(Person) );
}
I'm stumped on how to use the seekp function above...
Person.h
// Person.h
// Class Person definition
#ifndef PERSON_H
#define PERSON_H
#include <string>
using namespace std;
class Person
{
public:
// default Person constructor
Person(int = 0, string = "unassigned", string = "unassigned", int = 0);
// accessor functions for id
void setID(int);
int getID() const;
// accessor functions for lastName
void setLastName(string);
string getLastName() const;
// accessor functions for firstName
void setFirstName(string);
string getFirstName() const;
// accessor functions for age
void setAge(int);
int getAge() const;
private:
int id;
char lastName[15];
char firstName[15];
int age;
}; // end class Person
#endif