Defining Scope in C++ OOP Program - c++

I am trying to get better at C++ by challenging myself by creating a program that manages employees. Given a certain salary vs. sales you will either be hired, fired or keep your job. I have been working with OOP a lot recently and thought that structuring it by class would make the exercise easier. I've gone over this again and again and I can't seem to find a solution. That being said I would very much appreciate some insight on what I am doing wrong. Keep in mind I am new to C++ and OOP but the more I learn the better I will be in the future.
Originally it was all one file then I separated the classes into header files. It seems to run a little smoother now but I still get the error that name, salary and scope (my variables) aren't defined in the scope of my program.
main.cpp
#include "Boss.h"
#include "Employee.h"
#include "PotentialEmployee.h"
#include <iostream>
using namespace std;
int main ()
{
Boss Boss1;
Boss Boss2;
Boss Boss3;
Employee Employee1;
Employee Employee2;
Employee Employee3;
PotentialEmployee PotentialEmployee1;
PotentialEmployee PotentialEmployee2;
Employee1.name = "Michael";
Employee2.name = "John";
Employee3.name = "Lisa";
Boss1.name = "Luke";
Boss2.name = "Ben";
Boss3.name = "Jack";
PotentialEmployee1.name = "Bill";
PotentialEmployee2.name = "Fred";
Employee1.salary = 55000;
Employee2.salary = 65000;
Employee3.salary = 75000;
Boss1.salary = 88000;
Boss2.salary = 95000;
Boss3.salary = 88000;
PotentialEmployee1.salary = 55000;
PotentialEmployee2.salary = 65000;
Employee1.sales = 12000;
Employee2.sales = 40000;
Employee3.sales = 80000;
Boss1.sales = 200000;
Boss2.sales = 250000;
Boss3.sales = 280000;
PotentialEmployee1.sales = 55000;
PotentialEmployee2.sales = 65000;
if (sales <= salary)
std::cout << "I'm sorry " << name << "you have been fired";
else if (sales >= salary)
std::cout << "Good job " << name << "you get a bonus";
else
std::cout << "Try and do better next quarter";
return 0;
}
main.cpp: In function ‘int main()’: main.cpp:66:7: error: ‘sales’ was
not declared in this scope if (sales <= salary) { ^ main.cpp:66:16:
error: ‘salary’ was not declared in this scope if (sales <= salary) {
^ main.cpp:67:34: error: ‘name’ was not declared in this scope
std::cout << "I'm sorry " << name << "you have been fired"; ^
main.cpp:71:35: error: ‘name’ was not declared in this scope std::cout
<< "Good job " << name << "you get a bonus";

As the error tries to tell you there is no sales and no salary declared in main. You probably want to refer to the Employees sales and salary, that would be
if (Employee1.sales <= Employee1.salary)
std::cout << "I'm sorry " << name << "you have been fired";
Some more tips:
better use small starting letters for object names and capitals for types. In your code it is not easy to see what is a variable and what is a type.
whenever you find yourself naming variables foo1, foo2, foo3 etc you should use a std::vector or an array instead. This will help you to loop over all employes and evaluate their sales/salary.
the {} for if and else are optional, but it is often better to write them any way.
your two cases are not exclusive. If sales == salary then both conditions would be true, but only the first one will get evaluated. Hence there is a tiny confusion: Looking at the else condition one might expect that a employee with sales == salary did a good job, but they will get fired :(
last and least, a company that keeps their employess even if they generate zero income is a very nice one :)
PS:
I was hoping to do it in a more general way where I wouldn't have to
write out Boss1, Boss2, Boss3 each time but it looks like that's the
best way to do it
When you find yourself writing a block of code that has lots of Boss1.some_member then that block of code is a good candidate to be actually implemented in a member function (where you dont need to prefix the object). Eg the employee could have a bool Employee::evaluate_salary_vs_sales(); that contains the logic you now have in main and returns whether they get fired or not.

Related

c++: Function using method of object defined in main

Good Morning.
Me and my team are facing a problem with our c++ assignment.
In main we are defining two instances of a class called Team, "Team famous, Team fighters". Inside main we are calling a function called "team details"; inside that function we are trying to access public methods of the instances we just created(famous.getName). The following message appears:
error: request for member 'getName' in 'famous', which is of non-class type 'teamdetails() ::team_t'
The message concerns the calls made inside that switch loop you can see in the code below. We can't find out where the problem comes from.
*Is it a problem that 'famous.getName' is used in a function in which object 'famous' was not declered in? *
NOTE: function 'teamdetails()' is called by function 'menu()', which is called by main.
Thank you for your help!
#include "Player.h"
#include "Team.h"
using namespace std;
void teamdetails();
int main(){
Team famous;
Team fighters;
cout<<"Welcome to the \"Survivor Experience of a lifetime\" !!!"<<endl;
menu();
return 0;)
void teamdetails(){
cout << " Which team are you interested in ? <famous/fighters>\t";
enum team_t {famous = 0, fighters = 1};
team_t team_as_enum;
// cin >> team_as_enum; // -> does not work. Below I am trying
//another alternative.
string team;
cin >>team;
for(;;)
if((team == "famous") || (team == "fighters"))
break;
if (team == "famous")
team_as_enum = famous;
else if(team == "fighters")
team_as_enum = fighters;
else
cout<<"sth went wrong with your input";
switch (team_as_enum){
case famous:
cout<<"The name is"<< famous.getName() <<endl;
cout<<"The number of players is "<<famous.getPlayers()<<endl;
cout<<"Portions are "<<famous.getPortions()<<endl;
cout<<"Victory : "<<famous.getVictories()<<endl;
break;
case fighters:
cout<<"The name is"<<fighters.getName()<<endl;
cout<<"The number of players is "<<fighters.getPlayers()<<endl;
cout<<"Portions are "<<fighters.getPortions()<<endl;
cout<<"Victory : "<<fighters.getVictories()<<endl;
break;
default:
cout<<"Ooop Entry not correct . Next time enter one of the following
team's name <famous/fighters>"<<endl;
}
}
You reuse famous variable name inside of your teamdetails function by declaring enum team_t {famous = 0, fighters = 1};. Chose a different name. And variable famous of type Team is not visible inside of that function at all as it is declared inside of main function scope, you need to pass it to teamdetails as argument.

Why are my variables giving a different value when they are printed outside of the class I set them in?

I am making fairly new to C++ and I am using it to make a text based game for a school project. However during the first section of the game the player answers questions by entering the number shown beside the answer they choose. However when I tested the variables the input going to using std::cout they return different values depending on where they are outputted. If I outputted them in the class I am using to set them (Introduction) the they return the correct value such as 1 or 3 etc. However when I output them in any file other than Introduction.cpp, the value displayed is -858993460 for all of the values. I get the same result from Main.cpp when I call them in my main function and if I call them from another function in a different class to Introduction.
This is an example of some of the code used to get input from the user:
void Introduction::CharacterCreation()
{
Universal universal;
std::fstream creation("Introduction_CharacterCreation.txt");
universal.line = 5;
for (int i = 0; i < universal.line; i++)
{
if (i > 0)
{
std::getline(creation, universal.displayText);
std::cout << universal.displayText << std::endl;
}
if (i == 4)
{
std::cout << std::endl;
std::cin >> universal.gender;
while (universal.gender <= 0 || universal.gender >= 3)
{
std::cout << "Please make a valid choice" << std::endl;
std::cin >> universal.gender;
}
}
}
// Code cut out here
}
The gender variable is an int declared in the Universal class, and the user is prompted to enter 1 for male or 2 for female by text pulled from a separate file. If the input is not 1 or 2 then a while loop forces the player to keep re-answering the question until they enter 1 or 2. The line variable is also an int however that is used for the for loops to ensure the right lines are read by the program.
To output the gender variable this is the code I use:
std::cout << gender << std::endl;
There is no universal. as it is being called within the Universal class itself.
This has confused me massively and I can't get my head around what is causing the problem. Any help or explanation would be great, thanks in advance.
Short answer: you're declaring a Universal object in your CharacterCreation() method. When this function exits since the scope of the universal variable was local so the entire object is destroyed.
Whatever you are outputting is just uninitialized garbage. It could really be any number depending on what system is compiling / running the program. To test this right after you input the gender, while still inside the function, try running
std::cout << universal.gender << std::endl;
This should output just fine.
There are a lot of ways you can go about fixing this. Since you didn't post where you call this method or your Universal class I can't say for sure. But I can speculate one such solution which is to declare the Universal object outside the method and then pass it in as a parameter:
Universal universal = Universal();
Introduction::CharacterCreation(universal);
std::cout << universal.gender << std::endl;
And just declare your function header to accept a Universal object:
void Introduction::CharacterCreation(Universal & universal)
{
//code here
}

Problems With linesearch and Bubblesort

Im making a program in c++ that takes a few persons puts them in a vector with name and age and i got all the code down for it but i cant get it to compile properly.
this is my code so far
#include <iostream>
#include <string>
using namespace std;
class person
{
public:
string name;
int age;
void SetInfo(const string _name, int _age) //Här läggs den viktigaste informationen in
{
name = _name;
age = _age;
}
int getAge(){ return age; }
};
void bubblesort(person mylist[], int n) // Här startar Bubblesort funktionen
{
for (int i = 1; i<n; i++)
{
for (int j = 0; j<i - 1; j++)
{
if (mylist[j].getAge() > mylist[j + 1].getAge())
{
person temp;
temp = mylist[j];
mylist[j] = mylist[j + 1];
mylist[j + 1] = temp;
}
}
}
}
int main() //Program start
{
person mylist[4]; //lista på personer
mylist[0].SetInfo("Johan", 25);
mylist[1].SetInfo("Nathalie", 20);
mylist[2].SetInfo("Jessica", 60);
mylist[3].SetInfo("Coco", 54);
//anropar bubblesort()
bubblesort(mylist, 4);
int index = Linesearch(mylist, 25);
if (index == -1)
cout << "person ej funnen!";
else
cout << "personen du letade efter " << mylist[index].name;
cin.get();
return 0;
system("pause");
}
The problem i think is my knowledge since im new to programming and has only done it for 4 weeks. I put this code together from myself and from examples found online. So every answer will help me learn more :)
EDIT:
Still the same code added error message here.
50 39 C:\Skrivbordet\Skola\ccxcxcxcvx.cpp [Error] 'Linesearch' was not declared in this scope
A C++ program starts out fairly blank, without any function to use at all except for main. (There is more to say on that. I'm sure comments are going to point that out. ;)) You include headers for <iostream> and string, so you can use all of the functions declared in them, which is a good thing! Lots of stuff is already written for you; you don't have to find out how to write text out to your screen, for example.
All other functions are to be written by yourself -- which is also a good thing! After all, what would be the fun of a programming language where you cannot do the stuff you want because "there is no function for it".
You already wrote (or possibly copied) one custom function: bubblesort. From that point on, you can use it anywhere you want. It is not in the standard headers, but the compiler sees it as a general function nevertheless; all it has to do is read your code top to bottom, and store the names of new functions when it encounters them.
On to your problem: Linesearch is the name of a function. The compiler assumes that because it is followed by a parenthesized argument list. So, it looks up Linesearch in the standard headers, finds it's not in there, then goes through your source code -- and still does not find it. Presto! error.
The solution is to use an existing standard function that does what you need, if there is one (I cannot recall), or write the function yourself and place it in your source code somewhere above main. (It needs¹ to be above the first function in which it is used, and in this case that is main.)
¹ I'm telling only a half-truth there; but I guess before expanding on that in turn, you are better off reading a C++ primer first.

Search vector of objects by object data member attribute

I'm writing a Jukebox simulator and I'm trying to search a vector of Album objects by album title and return the index for use in other functions. The function is to be used for a number of different things such as deleting an album, printing an album etc.
I have gotten it to work in a previous application when the function was in the same Class as the data member to search for. I can however for some reason not get it to work using getters. No matter what I input as search key the idx returns 3 although the vector only contains indexes 0, 1 and 2 (only 3 albums right now).
The lambda function seem to be able to access data by using the getAlbum()-getter but somehow the comparison doesn't work.
My approach might be entirely wrong and I'd be grateful for any pointers in the right direction, or suggestions on how to accomplish the desired result using some other technique.
int Jukebox::findAlbumIdx(string key)
{
// Get search predicate
auto it = find_if(albvec.begin(), albvec.end(), [key](Album const &a)
{
return (a.getAlbum() == key);
});
int idx = it - albvec.begin();
return idx;
}
void Jukebox::delAlbum()
{
cin.get();
string key;
cout << "Input title of album to delete: ";
getline(cin, key);
int idx = findAlbumIdx(key);
if(idx > albvec.size() - 1)
cout << "No hits." << endl;
else
albvec.erase(albvec.begin() + idx);
}
getAlbum is just a simple inline getter as such:
string getAlbum() const {return album_title;}
Following Jonathan Wakely's suggestion to add std::cout << a.getAlbum() << " == " << key << std::endl; in the lambda the output is this:
Input title of album to delete: Abbey Road
== Abbey Road
== Abbey Road
== Abbey RoadLonely Hearts Club Band
No hits.
Obviously the getter isn't actually getting much to use for comparison. Not sure why it only gets the last entry and on the right hand side of the comparison.
If I add this to any of the functions above it gets and displays the Album titles correctly. The vector seems to be fine just before calling findAlbumIdx(key); and also inside the findAlbumIdx function.
for(unsigned int i = 0; i < albvec.size(); ++i)
cout << albvec[i].getAlbum() << endl;
The original playlist file that is read into the vector to be searched had dos newlines, after converting it using dos2unix (since I'm running Linux) the search, and I presume a lot of other things, is working correctly.
I suppose trimming newline characters while reading the file into the vector would be the more correct approach.

Function and selection issue in C++

I revised this post. I am new to programming and do not know if the functions are set up correctly or even how to allow the selection of packages. Below is my objective.
I have a class assignment to write a C++ program that will calculate a customers monthly internet bill. It would input a customer name, which package the customer purchased, and how many hours were used.
The Requirements are:
Input validation: to be sure the user only selects package A B or C. Display and error message if the wrong package is entered.
Calculation:
PackA for 9.95 a month with 10 hours of acess. 2 bucks per additional hour.
PackB for 14.95 a month with 20 hours of acess. 1 bucks per additional hour.
PackC for 19.95 a month with unlimited acess.
I then have to create the output as a bill.
The code I wrote so far is:
/*
James Hayek
CIS 165
Passaic County Community College
Program 04
*/
#include <iostream>
#include <iomanip>
using namespace std;
double calcBill(double packageChoosen, double hours, double basePack, char name); // This is the function prototype for calcBill
void dispBill(char packageChoosen, double hours, double basePack, char name, char bill); // This is the function prototype for dispBill
int main()
{
char packageChoosen;
double bill;
char name;
double hours;
double basePack;
cout << "Welcome To Your Personal Bill Caclculator!\n\n";
cout << "Please enter your name: \n";
cin >> name;
cout << "Please choose your package by entering A, B, or C: \n";
cin >> packageChoosen;
bill = calcBill(name, packageChoosen, hours, basePack); // call function calcBill
dispBill(name, packageChoosen, hours, basePack, bill); // call function dispBill
return 0;
} // end main
double calcBill(char packageChoosen, double hours, double basePack, char name) //This is the function for calcBill
{
if (packageChoosen == 'A' || packageChoosen == 'a' && hours <= 10)
{
bill = 9.95;
}
else if (packageChoosen == 'A' || packageChoosen == 'a' && hours > 10)
{
bill = 9.95 + (2 * hours);
}
else
{
cout << "Please choose an apropriate package";
}
return bill;
} // end main
void dispBill(double packA, double packB, double packC, char name, char bill) //This is the function for dispBill
{
cout << bill;
return;
} // end dispBill
I am not really sure where to begin, any advice would be greatly appreciated.
The && operator binds more tightly than the || operator in C++. Rather than
packageChoosen == 'A' || packageChoosen == 'a' && hours > 10
as a boolean expression, you most likely want
(packageChoosen == 'A' || packageChoosen == 'a') && hours > 10
The top expression looks either for a "package A" or a "package a with hours > 10". The bottom expression looks for a "package A or package a" and "hours > 10".
As Platinum Azure mentions in his answer, it is also possible to convert whatever character you have to lowercase, then do a single comparison against a lowercase letter.
#include <cctype>
// ...
std::tolower(packageChoosen) == 'a' && hours > 10
This makes your code a little more readable, and you don't have to worry about operator precedence.
Zeke's answer is solid; however, you could #include <cctype> and use std::tolower(packageChoosen == 'a' as part of your condition.
You need to think more in terms of OO. You're stuck in C world. I would suggest that Package would be a great candidate for an object.
As to the errors, you haven't said what they are so I can't really help you there. I'm too lazy to run a compile myself just to get what you should have already posted.
create an abstract class PackageAbstract
create a class called user
create a class called bill
create concretes class PackageA, packageB, packageC
in the user class add method :
addPackage(packageAbstract* packageAbs){}
add the member m_vector package choosen
for billing create a bill with user fedded with package...
each month you loop through users to create bills
for a real app you'll need a class custormers wich is feeded by users
...
Nice solution:
Create an abstract class Package, like so:
class Package{
public:
virtual double calculate(double hours) = 0;
}
Then subclass concrete package types from it, like so:
class PackageA : public Package{
public:
virtual double calculate(double hours){
return hours < 10 ? 9.92 : 9.95 + hours*2;
}
}
Then, you can use something like this code to calculate the bill:
Package* bill_calculators[3];
bill_calculators[0] = new PackageA();
bill_calculators[1] = new PackageB();
bill_calculators[2] = new PackageC();
char packageChosen;
cin >> packageChosen;
packageChosen = toupper(packageChosen) - 'A';
if(packageChosen >= 0 && packageChosen < 3) cout << bill_calculators[packageChosen]->calculate(hours);
else cout << "Invalid package\n";
I haven't actually compiled or tested the code, but you get the idea: create an abstract interface, implement algorithms for particular packages in subclasses, then create instances and decide which instance to use for calculation based on user input.
Btw, you'll have to #include to use the toupper() function
Cheers.