Trouble reading and storing user input - c++

I am having serious trouble with my program in C++. I need to read in a line of information entered by the user such as:
Bill Jones 20 07:30 09:30 08:00 14:00 00:00 00:00 10:00 13:00 00:00 00:00
This should all be stored in one instance of a Worker class. What I am having trouble with are the times since they use a semicolon. I am completely stuck and have looked everywhere but can't find any help. This is the code I have so far:
#include <iostream>
#include <string>
using namespace std;
class Time;
class Worker;
ostream &operator << (ostream &, const Time &);
istream &operator >> (istream &, Time &);
class Time
{
private:
int hour;
int minute;
public:
Time();
void setHour(int a)
{ hour=a; }
void setMinute(int a)
{ minute=a; }
int getHour() const
{ return hour; }
int getMinute() const
{ return minute; }
Time operator + (const Time &);
};
class Worker
{
public:
int start;
int end;
string fName;
string lName;
double payrate;
double payment;
Time monday,tuesday,wednesday,thursday,friday;
friend istream &operator >> (istream &, Time &);
friend ostream &operator << (ostream &, const Time &);
};
Time::Time()
{
hour = 0;
minute = 0;
}
ostream &operator << (ostream &strm, const Worker &obj)
{
strm << obj.fName << " " << obj.lName << " " << obj.payrate;
return strm;
}
istream &operator >>(istream &strm, Worker &obj)
{
strm >> obj.fName;
strm >> obj.lName;
strm >> obj.payrate;
string token;
int h,m;
string t;
for (int i=0; i<token.size(); i++) {
if(token[i]==':')
{
h = atoi (t.c_str());
t.clear();
}
else
{
t=t+token[i];
}
m=atoi(t.c_str());
}
obj.monday1.setHour(h);
obj.monday1.setMinute(m);
return strm;
}
Time Time::operator+ (const Time &right)
{
Time temp;
temp.hour = hour + right.hour;
temp.minute = minute + right.minute;
return temp;
}
int main ()
{
Time time1, time2;
Worker worker[100];
int num;
cout << "Please enter the number of workers on the payrole: ";
cin >> num;
cout << "Please input the worker’s last name, first name, pay rate, start time, and end time from "<< endl;
cout << "Monday through Friday separated by space." << endl;
for (int i=0; i<num; i++)
{
cin >> worker[i];
}
for (int i=0; i<num; i++)
{
cout << worker[i];
}
return 0;
}

In the following block of code, you're using the contents of token and t without having previously initialized their values:
string token;
int h,m;
string t;
for (int i=0; i<token.size();i++){
if(token[i]==':')
{
h = atoi (t.c_str());
t.clear();
}

Related

C++ how can i get the name in class to make it as a ranking system based on the time I input

Can I store my object in a class in a variable so that I can print the ranking name?
The question is to write a program that asks for the names of five runners and the time it took each of them to finish a race. The program should display who came in first, second, and third place. Only accept positive numbers for the times.
Any modification that I should make?
#include <iostream>
using namespace std;
class runner{
public:
char name[50];
float time;
void input(){
cout <<"\n Enter the name: ";
cin>> name;
cout <<"\n Enter the time taken to finish the race (mins): ";
cin>> time;
}
};
int main(){
runner runners[5];
for(int i =0;i<5; i++){
runners[i].input();
}
int i,first, second, third, fourth, fifth;
fifth = fourth = third = first = second = INT_MIN;
char firstname, secondname, thirdname, fourthname, fifthname;
for(int i =0;i<5; i++){
if(runners[i].time>first){
fifth = fourth;
fourth = third;
third = second;
second = first;
first = runners[i].time;
}
else if(runners[i].time> second){
fifth = fourth;
fourth = third;
third = second;
second = runners[i].time;
}
else if(runners[i].time>third){
fifth = fourth;
fourth = third;
third = runners[i].time;
}
else if(runners[i].time>fourth){
fifth = fourth;
fourth = runners[i].time;
}
else if(runners[i].time>fifth){
fifth = runners[i].time;
}
}
cout << first <<","<< second <<","<< third <<","<< fourth<< ","<< fifth<<endl;
return 0;
}
Yes, you can.
You can write a custom compare function:
class runner
{
public:
std::string name; // why not std::string?
float time;
void input()
{
std::cout <<"\n Enter the name: ";
std::cin >> name;
std::cout <<"\n Enter the time taken to finish the race (mins): ";
std::cin >> time;
}
};
bool cmp (const runner &lhs, const runner &rhs)
{
return lhs.time < rhs.time;
}
std::ostream& operator<< (std::ostream& out, const runner& run)
{
out << run.name << ' ' << run.time;
}
int main()
{
runner runners[5];
for(int i =0;i<5; i++)
{
runners[i].input();
}
std::sort(runners, runners + 5, cmp);
for(int i {4}; i >= 0; --i)
{
std::cout << runners[i] << ' ' << i << ',';
}
}
Or you can overload the < operator:
class runner
{
public:
std::string name;
float time;
void input()
{
std::cout <<"\n Enter the name: ";
std::cin >> name;
std::cout <<"\n Enter the time taken to finish the race (mins): ";
std::cin >> time;
}
};
bool operator< (const runner &lhs, const runner &rhs)
{
return lhs.time < rhs.time;
}
int main()
{
runner runners[5];
for(int i =0;i<5; i++)
{
runners[i].input();
}
std::sort(runners, runners + 5);
for(int i {4}; i >= 0; --i)
{
std::cout << runners[i] << ' ' << i << ',';
}
}
You can simplify your program by using std::multiset as shown below:
#include <iostream>
#include <string>
#include <set>
//using namespace std; //don't use this
class runner{
public:
std::string name; //use string instead of array of char
float time;
void input(){
std::cout <<"\n Enter the name: ";
std::cin>> name;
std::cout <<"\n Enter the time taken to finish the race (mins): ";
std::cin>> time;
}
//overload operator< since we are using std::set
bool operator<( const runner &r ) const
{
return ( time < r.time );
}
};
int main(){
std::multiset<runner> runners; //use multiset instead of array
for(int i =0;i<5; i++){
runner tempRunner;
tempRunner.input();
runners.insert(tempRunner);
}
int i = 0;
//print out the details as asked in the assignment question. You can adjust
//the output according to your needs for example if you want to display only first
//3 position details or what if all the first three persons in the multiset have the same timing
for(const runner &tempRunner: runners)
{
std::cout<<tempRunner.name <<" came: "<<i+1<<std::endl;
++i;
}
return 0;
}
Note multiset is used instead of set because more than one runner can have the same time.

Implicit instantiation of undefined template 'std::__1::vector<Item *>' error

I'm trying to store pointers of a class in a vector but get the error
Implicit instantiation of undefined template 'std::__1::vector<Item *>'
The code is:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Item{
private:
string itemName;
float itemPrice;
int itemQuantity;
public:
Item(string name = "NULL", float price = 0, int quantity = 0){
itemName = name;
itemPrice = price;
itemQuantity = quantity;
}
friend ofstream & operator<<(ofstream &ofs, Item &i);
friend ifstream & operator>>(ifstream &ifs, Item &i);
friend ostream & operator<<(ostream &os, Item &i);
};
ofstream & operator<<(ofstream & ofs, Item &i){
ofs << i.itemName << endl;
ofs << i.itemPrice << endl;
ofs << i.itemQuantity << endl;
return ofs;
}
ostream & operator<<(ostream &os, Item &i){
os << i.itemName << endl;
os << i.itemPrice << endl;
os << i.itemQuantity << endl;
return os;
}
ifstream & operator>>(ifstream & ifs , Item & i){
ifs >> i.itemName;
ifs >> i.itemPrice;
ifs >> i.itemQuantity;
return ifs;
}
int main() {
int n;
string name;
float price;
int qty;
cout<<"Enter number of Item:";
cin>>n;
vector<Item *> items;
cout<<"Enter All Item "<<endl;
for(int i=0;i<n;i++)
{
cout<<"Enter "<<i+1<<" Item Name , price and quantity";
cin>>name;
cin>>price;
cin>>qty;
items.push_back(new Item(name,price,qty));
}
ofstream fos("Items.txt");
for(int i=0;i<n;i++)
{
fos<<*items[i];
}
Item item;
ifstream fis("Items.txt");
for(int i=0;i<3;i++)
{
fis>>item;
cout<<"Item "<<i<<item<<endl;
}
}
It looks like a basic error, but I couldn't find a way over it.How can I store pointers of a user defined class inside a vector? Is my syntax off or vectors just won't work that way?
You didn't include
#include <vector>
adding it, your code will compile cleanly.

C++ friend operator overloading cin>>

I am replacing a Read in function with a friend operator. I am having trouble referencing the friend operator in a void function. I am receiving and error "No member named 'Read' in Date" in the void GetDates function. Does anyone know how to fix this? Thank you!
Question 2:
I am now using cout<< operator but I am receiving errors for my variables: "'mn' is a private member of 'Date'"
class Date {
private:
int mn; //month component of a date
int dy; //day component of a date
int yr; //year comonent of a date
public:
//constructors
Date() : mn(0), dy(0), yr(0)
{}
Date(int m, int d, int y) : mn(m), dy(d), yr(y)
{}
//input/output functions
friend istream& operator>>(istream& Read, Date& d); //overload friend Read
friend ostream& operator<<(istream& write, Date& d); //overload friend write
void GetDates();
void Sort();
};
//Date class member functions
istream& operator >>(istream& Read, Date& d) //**NEED TO REPLACE with overload vs as friends to Date function**
{
char skip_char;
Read >> d.mn >> skip_char >> d.dy >> skip_char >> d.yr;
return Read;
}
void GetDates(Date l[], int &n) //reads list l, and returns count in n
{
cout << "How many date values are to be processed (1 - 100)? ";
cin >> n;
while ((n < 0) || (n > 100)) {
cout << "Invalid value; enter number between 0 and 100: ";
cin >> n;
}
for (int i = 0; i < n; i++) {
cout << "Enter a date (mm/dd/yyyy): ";
l[i].Read(); //ERROR HERE
}
}
ostream& operator <<(ostream& write, Date& d) //friend write
{
if (d.mn < 10)
cout << '0';
cout << d.mn << '/';
if (d.dy < 10)
cout << '0';
cout << d.dy << '/';
if (d.yr < 1000)
cout << '0';
if (d.yr < 100)
cout << '0';
if (d.yr < 10)
cout << '0';
cout << d.yr;
return write;
}
Read is the name of the stream that you are extracting from. An example of a stream that you can read from is cin. You need to replace this line:
l[i].Read(); //ERROR HERE
with
cin >> l[i];
Inside operator>> the cin object is now called Read.
The issue with your operator<< is that it needs to be declared as a friend, the same way you've done with operator>>.
Also, you are writing to cout instead of writing to write. This will not work, as soon as you try to writing to any other stream.

save and load c++ program

Ok so I figured out and learned a lot of stuff today and I want to thank the community for that. I haven't had any bump in the roads for a few hours now but now I'm stuck.
The last bump in the road. Saving and Loading my program. I have no idea where to start. I looked at how fwrite... and fread... works and all the examples are for programs that aren't split. I don't know where to start with my files. I'll put up 2 functions. If someone can help me how to do save those I can probably figure out the rest.
in gradebook.h
class Student {
public:
string last;
string first;
int student_id;
};
class Course {
public:
string name;
int course_id;
vector <Student> students;
};
class Gradebook {
public:
Gradebook();
void addCourse();
void addStudent();
private:
vector <Course> courses;
};
in gradebook.cpp
void Gradebook::addCourse() {
int i, loop=0;
cout << "Enter Number of Courses: ";
cin >> loop;
for(i=0; i<loop; i++) {
//create newEntry to store variables
Course newEntry;
cout << "Enter Course ID: ";
cin >> newEntry.course_id;
cout << "Enter Course Name: ";
cin >> newEntry.name;
//set variables from newEntry in Courses
courses.push_back(newEntry);
}
}
void Gradebook::addStudent() {
int i, loop=0;
cout << "Enter Number of Students: ";
cin >> loop;
for(i=0; i<loop; i++) {
//create newEntry to store variables
Student newEntry;
cout << "Enter Student ID: ";
cin >> newEntry.student_id;
cout << "Enter Last Name: ";
cin >> newEntry.last;
cout << "Enter First Name: ";
cin >> newEntry.first;
//set variables from newEntry in Students
courses[0].students.push_back(newEntry);
}
}
So if a user was to input some variables in courses and students how would i use fwrite... to save the data?
I wouldn't recommend fwrite, instead look into <fstream>. ifstream, ofstream
Basic saving:
ofstream out("data.txt"); //save file data.txt
out << thedata; //use the << operator to write data
Basic loading:
ifstream in("data.txt"); //reopen the same file
in >> thedata; //use the >> operator to read data.
Here's some sample code that might help without solving the whole thing for you.
#include<iostream>
#include<string>
#include<vector>
#include<fstream>
class Student {
public:
Student()
: student_id(0)
{
}
Student(const std::string &f, const std::string &l, int id)
: first(f)
, last(l)
, student_id(id)
{
}
std::string last;
std::string first;
int student_id;
};
std::ostream &operator <<(std::ostream &os, const Student &s)
{
os << s.last << '\t'
<< s.first << '\t'
<< s.student_id << '\t';
return os;
}
std::istream &operator >>(std::istream &is, Student &s)
{
is >> s.last
>> s.first
>> s.student_id;
return is;
}
bool WriteIt(const std::string &sFileName)
{
std::vector<Student> v;
v.push_back(Student("Andrew", "Bogut", 1231));
v.push_back(Student("Luc", "Longley", 1232));
v.push_back(Student("Andrew", "Gaze", 1233));
v.push_back(Student("Shane", "Heal", 1234));
v.push_back(Student("Chris", "Anstey", 1235));
v.push_back(Student("Mark", "Bradtke", 1236));
std::ofstream os(sFileName);
os << v.size();
for (auto s : v)
os << s;
return os.good();
}
bool ReadIt(const std::string &sFileName)
{
std::ifstream is(sFileName);
int nCount(0);
is >> nCount;
if (is.good())
{
std::vector<Student> v(nCount);
for (int i = 0; i < nCount && is.good(); ++i)
is >> v[i];
if (is.good())
for (auto s : v)
std::cout << s << std::endl;
}
return is.good();
}
int main()
{
const std::string sFileName("Test.dat");
return !(WriteIt(sFileName) && ReadIt(sFileName));
}
Bonus points if you recognise who my "students" are. :-)

Outputting Vector of Type Class

There is more code to this question in this previous question: C++ Trouble Inputting Data into Private Vector (invalid use)
I'm trying to output a vector of type "Account"
Account:
class Account
{
string firstName;
string lastName;
string accountPass;
int accountID;
float accountBalance;
private:
int depositAmount;
int withdrawAmount;
public:
static Account 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
This is the way I'm declaring the vector:
std::vector<Account> accounts_;
And here's how I'm trying to print it to the screen:
for(int i=0; i < accounts_.size(); i++)
{ cout<< accounts_[i] <<endl; }
But I'm getting this error "invalid operands to binary expression".
Current code;
class BankingSystem
{
int accountID;
char fileName;
private:
std::vector<Account> accounts_;
public:
void addAccount();
void storeAccount( Account );
void deleteAccount();
void accountInquiry();
void saveAccounts();
void loadAccountsFromFile();
friend class Account;
friend std::ostream& operator << (std::ostream&, const Account&);
}; // end of class BankingSystem
#endif
std::ostream& operator << (std::ostream& os, const Account& acc)
{
// output members to os
return os;
}
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;
}
//function gets data from createAccount
void BankingSystem::storeAccount( Account newAccountToAdd )
{
//append to vector "accounts_"
accounts_.push_back(newAccountToAdd);
}
void BankingSystem::deleteAccount()
{
cout << "\nEnter The Account ID: ";
cin >> accountID;
}
void BankingSystem::accountInquiry()
{
int n;
cout << "\n\t Enter The Account ID (-1 for all): ";
cin >> n;
//cout << accounts_.size();
if (n == -1)
{
cout << "\n\t List of all Accounts; (" << accounts_.size() << ") TOTAL: ";
for(int i=0; i < accounts_.size(); i++)
{
cout<< accounts_[i] << endl;
}
}
else
{
cout << "\n\t Listing Account: " << n;
cout << "\n\t I should search the vector for the ID you input";
}
}
You need to provide the insertion operator:
std::ostream& operator<<( std::ostream& out, const Account& acct );
Then implement it internally by dumping each one of the fields with the appropriate format.
You should overload operator << for Account class. In class:
friend std::ostream& operator << (std::ostream&, const Account&);
In global (or yours, where Account is defined) namespace
std::ostream& operator << (std::ostream& os, const Account& acc)
{
// output members to os
return os;
}
or create some output function in class for example
void print(std::ostream& os) const { }
And then free-operator <<
std::ostream& operator << (std::ostream& os, const Account& acc)
{
acc.print(os);
return os;
}