Telephone Directory: dividing code/making menu - c++

I am making a Telephone Directory. Now, as someone said dividing code in small section is a better code. I want to make it something like, but the problem is I can't access the object from main function to a class's member function or a traditional function. I am not sure how pass an object (arrays of objects) as a parameter (to a function).
case 2:
{
print_header("Update Menu");
print_update_menu();
break;
This is my code:-
case 2:
Print_Header("Update Menu");
while (1)
{
cout<<"Please enter a Name or ID to Update:"<<endl;
cin>>search_ID_name;
for(int j=0 ; j<=records-1 ; j++)
{
if((search_ID_name==Telephone_directory[j].ID) || (search_ID_name==Telephone_directory[j].Name) )
{
Telephone_directory[j].Phone_Directory_data_display();
cout<<"Do you want to update this record? [1/0]"<<endl;
cin>>choice;
if(choice==1)
{
Telephone_directory[j].Phone_Directory_data_input();
cout<<"Record successfully updated"<<endl;
Telephone_directory[j].Phone_Directory_data_display();
}
else if (choice==0)
{
cout<<"Record not updated"<<endl;
break;
}
}
}
cout<<"Want to update another record? [y/n]"<<endl;
cin>>choice_y_n;
if(choice_y_n=='y')
{
cout<<"Redirecting to Update Menu again"<<endl;
}
else if (choice_y_n=='n')
break;
}
break;

In C++ there are two ways to pass an object to a function.
Pass by value (copy)
Pass by pointer (reference to memory location)
Of these you usually pass by reference for objects.
If you want to pass an object of type A to a function called f you would do it like so:
void f(A& a) {
// You can access a's members here i.e if a has a method called b you do a.b();
}

Related

Can't access my vector variables in different conditions

I'm trying to do creating objects in a one condition and listing this objects in another condition, but it doesn't work.
void fillVector(vector<Account>& newcreateAccObj){
string name;
string password;
cout<<"Enter your surname:"<<endl;
cin>>name;
cout<<"Enter your password:"<<endl;
cin>>password;
Account newAcc(name,password);
newcreateAccObj.push_back(newAcc);
cout<<endl;
}
This works fine.
void printVector(vector<Account>& newcreateAccObj){
unsigned int size=newcreateAccObj.size();
for(unsigned int i=0;i<size;i++){
cout<<"Account"<<i+1<<endl;
cout<<"-----------"<<endl;
newcreateAccObj[i].getId();
newcreateAccObj[i].getName();
cout<<endl;
}
}
This works fine too when I execute these 2 functions in same condition.
But when I do this:
int main(){
int whileCondition=-1;
string girisSecim;
vector<Account> createAccObj;
while(whileCondition==-1){
cout<<"--------------------------------------------------------"<<endl;
cout<<"??????????????????????????????????????????????????????"<<endl;
cout<<"1-create acc 2-transferring"<<endl;
cout<<"3-enter acc 4-exit"<<endl;
cout<<"--------------------------------------------------------"<<endl;
cin>>girisSecim;
if(girisSecim=="1"){
fillVector(createAccObj); //BURDA OBJE OLUSTURULUYOR
}
else if(girisSecim=="2"){
printVector(createAccObj);
}
else if(girisSecim=="3"){
}
else if(girisSecim=="4"){
return 0;
}
else{
cout<<"Hatali tuslama."<<endl;
}
whileCondition=0;
cout<<"Programa devam etmek icin -1'i, cikmak icin herhangi bir seyi tuslayiniz."<<endl;
cin>>whileCondition;
}
Edit: I edited the main part.
I choose option 1 first. I create my object and returning the select menu, after that I choose option 2 and it gives me a blank output.
follow the lifetime of createAccObj.
it seems like you do not send the same vector to both functions.
I will have a guess, your code looks like this:
while (input}(
vector<Account> createAccObj;
if(input=="1"){
fillVector(createAccObj);
}else if(input=="2"){
printVector(createAccObj);
}
here, on each iteration, new vector is created, so when you try to print, you print empty vector.
If this is the case, simply, remove the vector deceleration outside the loop.
Edit:
looking into the code again, seems like you forgot cout in newcreateAccObj[i].getId(); and newcreateAccObj[i].getName();

Adding to a private variable not working

I'm currently learning c++ and trying to make a vending machine! I know my code is really bad and I am sorry about that.
I am trying to implement a bank and have the user take a loan from it, the only problem is that the bank is unable to add money to the user. Here's my code.
void Bank::askLoan() {
//ColaMachine object
ColaMachine cola;
bool loanGranted = false;
cout << string(100, '\n');
cout << "You do not have enough money!\n\n";
cout << "Would you like to take a loan?\n\n(1)-Yes\n(2)-No\n\n\n";
int choice;
cin >> choice;
switch (choice) {
case 1:
//Print the bank menu!
printBank();
while (loanGranted != true) {
cout << "Enter the amount to lend: $";
cin >> _loanValue;
//Test if _loanValue is less than or = to bankmoney, so they would scam the bank.
if (_loanValue <= _bankMoney) {
//Supposed to add money to the user.
cola.addMoney(_loanValue);
break;
}
else {
cout << "You entered too much! Try again..." << endl;
}
}
break;
case 2:
//User does not want to take a loan! Quit the game!
//Not implemented, yet.
break;
default:
cout << "Bad input! Please retry..." << endl;
}
}
If the amount entered was within the correct range it calls the addMoney() Func from ColaMachine class.
void ColaMachine::addMoney(int money) {
//This part doesnt seem to modify the actual value
//Whenever It goes back to the main game loop it doesnt change.
_money += money;
}
From what I understand += is the same as _money = _money + money;
What am I doing wrong here?
Full source on GitHub-
https://github.com/Rohukas/-LearningCPP
The problem is that you are creating new cola object inside askLoan() method which gets destroyed at the end of the function, so call to addMoney() method modifies state of that temporary cola object. One option is to provide cola object by pointer to the askLoan() method.
For example, in ColaMachine::chooseDrink() you would call bo.askLoan(this). this is pointer to the object from where you call bo.askLoan().
You would need to modify your askLoan() signature:
void askLoan(ColaMachine * cola) and remove ColaMachine cola; from askLoan() itself.
The problem is here
void Bank::askLoan() {
//ColaMachine object
ColaMachine cola;
bool loanGranted = false;
...
everytime you call Bank::askLoad you create a new ColaMachine, that's what the code above says. But the problem is that any changes to that ColaMachine are thrown away when you exit Bank::askLoan and the ColaMachine is destroyed. That's why the changes you make to the ColaMachine don't stick.
Instead you want to use same ColaMachine each time that you call Bank::askLoad. I can't say the best way to do that without seeing the rest of your code, but one way would be to pass ColaMachine as a reference parameter to Bank::askLoad
void Bank::askLoan(ColaMachine& cola) {
bool loanGranted = false;
...
Another way would be to make ColaMachine a class member variable of Bank
class Bank
{
...
void askLoan();
private:
ColaMachine cola;
};
Which is better? No idea. I think you need to read up on class design, and how the objects in your program should relate to each other. That seems to be the bit you're not getting at the moment.
=========================================================================
Having looked at your full code I can see that you make the same mistake in more than one place. In your main function you declare a Bank and a ColaMachine.
//ColaMachine Object
ColaMachine cola;
//Bank Object
Bank bank;
Those should be the only two Bank and ColaMachine objects you create, so this is wrong
void ColaMachine::chooseDrink() {
Bank bo;
...
bo.askLoan();
That Bank bo is a completely different bank from the one you declared in main. And like the previous code this Bank bo gets created and destroyed each time you call ColaMachine::chooseDrink.
I think that what you should be doing is passing the ColaMachine and Bank variables declared in main as reference parameters to the other parts of you code that need to use them. So (for instance)
void ColaMachine::chooseDrink(Bank& bank) {
...
bank.askLoan();
You have quite a lot of rewriting of this code to do.

How to make a function change a global array permanently

Recently I've been working on an inventory system for a text-based game that uses a global array for the inventory system and a corresponding function to read true or false in said array. The problem I've run into is this, the function I'm using to modify the array
void playerGet(bool items[], int itemNumber) //this function takes an assigned argument of the array indices variable, and changes that array indices from true, to false.
{
items[itemNumber] = true;
}
only modifies the array within the scope of the function its housed in. The array is defined in a .cpp file like this:
void inventoryArray(bool items[]) //This function establishes all the items in the game, the true false statement expresses whether or not the item is in the player's inventory.
{
items[WEAPON_RELIC_RIFLE] = false;
items[WEAPON_SCALPEL] = false;
items[MISC_ACTION_FIGURE] = false;
items[MISC_FIRE_EXTINGUISHER] = false;
items[MISC_LIFE_RAFT] = false;
}
and is then declared in a .h file like this:
void inventoryArray(bool items[]);
the enums used in the array are defined in a header file like this:
enum equipment //This declares a list of enums for each item in the game, consumables, not included.
{
WEAPON_RELIC_RIFLE, // = 0
WEAPON_SCALPEL, // = 1
MISC_ACTION_FIGURE, // = 2
MISC_FIRE_EXTINGUISHER, // = 3
MISC_LIFE_RAFT, // = 4
MAX_EQUIPMENT
};
the function that reads the inventory array is this:
void twoScavengerCombat(bool items[])
{
for (int item = 0; item < MAX_EQUIPMENT; ++item)
{
if (items[item] == true) //if true proceed
{
switch (item)
{
case 0: //if array indices identifier = 0, print relic rifle
cout << "1: Use the Relic Rifle\n";
break;
case 1:
cout << "2: Use the Scalpel\n";
break;
case 2:
break;
case 3:
cout << "3: Use the Fire Extingusher\n";
break;
case 4:
cout << "4: Use the Life Raft\n";
break;
default:
cout << "Error";
break;
}
}
else
cout << "Option Unavailible\n"; //if false print Option Unavailible
}
compiled, with the array and enums headers declared the main file would look like this:
int toolSearch()
{
bool items[MAX_EQUIPMENT];
inventoryArray(items);
playerGet(items, 0);
}
void twoScavengerCombat(bool items[])\\ declared in this file, but since its just above here i left it as a forward declaration to save space
int main()
{
toolSearch();
twoScavengerCombat(items);
return 0;
}
Ideally this would produce the result: Use Relic Rifle
Option Unavailable
Option Unavailable
Option Unavailable
Option Unavailable
but instead it produces 5 Option Unavailable's. What am I missing?
You would want
//bunch of #include<> directives
bool items[MAX_EQUIPMENT];
int toolSearch()
{
inventoryArray();
playerGet( 0);
}
void twoScavengerCombat()
...
// other functions here
int main()
{
toolSearch();
twoScavengerCombat();
return 0;
}
Note that bool items[MAX_EQUIPMENT]; is not defined in a function. It is off on it's own at the top of the file in plain view of anything defined below it. This is what it means to be global. Anyone and everyone can access it, if they know where it is or you tell them where it is with an extern statement. It is created when the program starts (even before main and that can cause some really fun debugging if the initialization logic of the variable is faulty) and dies only when the program does.
Lightness Races in Orbit delves a bit deeper here, but is more concerned with making a global variable extend past a single file
There is no need to pass items into any function because everyone can see items The downside is there is one and only one items so if you have multiple players each with different item lists, you're going to have problems.
You might want to look into std::vector (resizable array) and std::map (which will allow you to look items up by name items["sword"].attackFoe(foe);) and std::set (which makes it really easy to see what a player has (if (items.find("Vorpal Hand Grenade") != items.end()) BlowStuffUp();) rather than having to search through each item every time.

Tennis Score Keeper

I am willing to write a code of a tennis score keeper in C++ that keeps track of the score, but there are 2 problems that occur when I run the program:
I can't quit the loop with while(cin!="q")
The functions wouldn't initialize the variables
#include<iostream>
#include<string>
using namespace std;
int points1=0, points2=0;
int set1=0, set2=0;
int games1=0, games2=0;
string in="";
void score(int point,int set,int game);
int main()
{
do
{
cout<<"POINTS: "<<points1<<":"<<points2<<endl<<"SETS: "<<set1<<":"<<set2<<endl<<"GAMES: "<<games1<<":"<<games2<<endl;
cout<<"Who scored - player 1 or player 2? (p1/p2) : ";
cin>>in;
if(in=="p1")
{
void score(int points1,int set1,int games1);
}
else if(in=="p2")
{
void score(int points2,int set2,int games2);
}
else {cout<<endl<<"Error!"<<endl<<endl;}
}
while(cin!="q");
system("pause");
return 0;
}
void score(int& point,int& set,int& game){
if(set<5)
{
switch(point)
{
case '30':
point=point+10;
case '40':
set++;
point=0;
default:
point=point+15;
}
}
else game++;
}
while(cin!="q");
should be
while(in!="q");
In your function, your switch is on an integer value, so your cases should use an integer value as well:
case '30':
should be
case 30:
The others as well.
This is a function prototype:
void score(int points1,int set1,int games1);
This is a function call:
score(points1,set1,games1);
Make sure you have function calls where you want to execute the function. You have a lot of prototypes where they don't belong.
Some Tennis tips: you need to be two points ahead to win a set, two sets ahead to win a match. You may want to take that into account in your functions. Points and sets of a single player will not be enough to decide who won a set or game.
Edit:
In addition, if you want variables you pass to a function to change outside of this function, you need to pass them by reference.
void score(int& points1, int& set1, int& games1);
Note the ampersands.
Passing parameters to a function will make a [b]copy[/b] of the parameters. This is refered to as pass-by-value, because the value is passed. You can pass-by-reference, which means you don't create a copy but instead pass the location of the actual variable. Changes to it will then be reflected back to your main program.
You want an infinite while loop with a break, also get rid of type defs in function calls -- something like:
while (true) {
cin >> in;
if (in == "p1") {
score(points1, set1, games1);
}
else if (in == "p2") {
score(points2, set2, games2);
}
else if (in == "q") {
break;
} else {
cout << endl << "Error!" << endl << endl;
}
}
The following line is wrong: while(cin!="q");
Instead of cin you need to use in!="q"
The second issue is because you're calling the function in the wrong way.
When you call a function, you just write its name and pass the specified arguments, you don't need to write the function return type when calling it. Also you don't need to specify the types of the arguments you're passing. Your function call should be :
score(points2, set2, games2)
And finally you're switching on an integer, so your cases should check for integers.

Calling a class function from a Vector instead of an Array

I am currently working on a way to load a bunch of different NPCs from a file and loading it into my game. I have everything working correctly with arrays but I would like to change it to using a vector since I can change the size in case I need more NPCs than the space available in the array and so I don't just have a mostly empty array if I dont need many NPCs at the current time. Note that the following code is from a testing program, not my actual programming. I made it so I dont mess with the complete project by accident.
int main()
{
char input;
bool Running = true;
NPC Creatures[MAX_NPCS];
//InitCreatures loads the X, Y and Type from the file. I know with vectors I have to
//resize it as I go along, Which would be included in the function.
if(Creatures[MAX_NPCS].InitCreatures(Creatures) == false)
{
Creatures[MAX_NPCS].CleanUp(Creatures);
return 0;
}
while(Running == true)
{
cout << "(C)heck an NPC, (A)ttack and NPC or (E)xit the program\n";
cin >> input;
switch(input)
{
case 'C': Creatures[MAX_NPCS].Check(Creatures); break;
case 'c': Creatures[MAX_NPCS].Check(Creatures); break;
//The Check function just shows the X, Y and Type of the NPC
case 'A': Creatures[MAX_NPCS].Attack(Creatures); break;
case 'a': Creatures[MAX_NPCS].Attack(Creatures); break;
//Attack shows X, Y and type and then removes that NPC from the array.
case 'E': Running = false; break;
case 'e': Running = false; break;
default: cout << "That was not a valid input\n"; break;
}
}
Creatures[MAX_NPCS].CleanUp(Creatures);
cout << "Exiting\n";
system("PAUSE");
return 0;
}
Really the only problem I am having is getting Main to run the NPC Class functions from a vector instead of using the Array like I have now. I can easily change the other things in the functions I'm calling to accept the vector and handle it correctly.
When trying to use a vector to run the functions I was only able to call them when I had something like this:
Creatures[1].Attack(Creatures);
Of course when I call them like that the values don't return correctly and I usually get an error and Besides I don't know how many NPCs will be loaded for the current map, if Any.
Any help with this would be appreciated. I realize I am a newbie when it comes to programming, especially when it comes to Vectors. If my function code is needed I will gladly post it.
You could just create a vector and have the first element in there to be able to call the InitCreatures function (you could also overwrite the first creature later).
vector<NPC> Creatures(1);
Creatures[0].InitCreatures(Creatures);
I'm assuming that in class you have the parameter passed by reference.
bool InitCreatures(vector<NPC>& x) { ... }
But since you give creatures as a parameter to every function you have (do you need it in check or attack?) - wouldn't it be better to have a class to hold the NPC vector?