I am working on this code. It is not yet done. The problem is that I do not get why I cannot update numAccount in my simple_account.h. It just keeps printing out "1" if I print out numAccount. Can anyone tell me why I cannot access and change the private value here?
main.cc
#include <iostream>
#include "simple_account.h"
using namespace std;
int main() {
char job;
int i = 0;
while (true) {
cout << "Job?" << endl;
cin >> job;
if (job == 'Q')
break;
if (job == 'N') {
Admin* user = new Admin[10];
(user+i)->newAccount(i);
cout << "i: " << i << endl;
i++;
}
}
simple_account.h
#pragma once
#include <iostream>
class Account {
public:
int id;
int b = 0;
};
class Admin {
class Account {
int id;
int b = 0;
};
int numAccount = 0;
Account **acnt[10];
public:
void newAccount();
void deposit(Account id, int money);
void withdrawal(Account id, int money);
void transfer(Account id1, Account id2, int money);
void check(Account id);
};
simple_acount.cc
#include "simple_account.h"
void Admin::newAccount() {
numAccount += 1;
}
The problem occurs when you press 'N' to open a new account.
if (job == 'N') {
Admin* user = new Admin[10];
(user+i)->newAccount(i);
cout << "i: " << i << endl;
i++;
}
This code creates ten new Admin objects, and initializes each one with the default constructor. Each Admin has its own numAccount member, which is initialized to zero because that's the default value you specified here: int numAccount = 0;
After creating ten Admin objects, the code then picks one with (user+i) and calls newAccount(i). This should not compile, because the newAccount() method does not take a parameter. But if it worked, it would increment that one Admin's numAccount member to 1 from the initial 0.
(There's another problem here, which is that when i reaches 10, you will be trying to call newAccount() on something that's outside your array of Admin objects, so you're going to see some undefined behavior.)
How to fix this.... depends on what you're trying to do. As suggested, you can make numAccounts a static member of the Admin class. But I think you'll need to review your design: what is an Admin, and how many should there be?
Related
I am trying to develop a text adventure in C++ where users can input string commands (ex. "take apple").
Here is a very naive sample of code I came up with:
# include <iostream>
using namespace std;
class fruit{
public:
string actual_name;
fruit(string name){
actual_name = name;
}
take() {
cout << "You take a " << actual_name << "." << endl;
}
};
fruit returnObjectFromName(string name, fruit Fruits[]){
for(int i = 0; i <= 1; i++){ // to be modified in future depending on Fruits[] in main()
if (Fruits[i].actual_name == name)
return Fruits[i];
}
}
int main(){
string verb;
cout << "Enter verb: ";
cin >> verb;
string object;
cout << "Enter object: ";
cin >> object;
fruit apple("apple");
fruit Fruits[] = { apple }; // to be extended in future
// returnObjectFromName(object, Fruits). ??? ()
}
How can I possibly get the fruit method with something similar to the function returnObjectFromName, if this is even possible?
I began the development with Python (independently), and there I can at least use eval(), but as I understand in C++ this is not an option.
I tried also with map, but I didn't manage to make it work with methods.
Thank you all for your answers.
Its not good way to rely on reflection in C++ and i think there is no way to list methods in classes. Maybe you can use function pointers but pointer to instance methods are hell.
I recommend to use polymorphism and good design. If some items might be taken, then use interface like this:
#include <iostream>
using namespace std;
class ITakeable {
public:
virtual bool isTakeable() = 0;
virtual void take() = 0;
virtual void cannotTake() = 0;
};
class fruit : public ITakeable {
public:
string actual_name;
fruit(string name){
actual_name = name;
}
bool isTakeable() {
return true;
}
void take() {
cout << "You take a " << actual_name << "." << endl;
}
void cannotTake() {
cout << "not needed to be implemented";
}
};
class airplane : public ITakeable {
public:
string actual_name;
airplane(string name){
actual_name = name;
}
bool isTakeable() {
return false;
}
void take() {
cout << "not needed to be implemented";
}
void cannotTake() {
cout << "You CANNOT take a " << actual_name << "." << endl;
}
};
int main() {
fruit apple("apple");
if (apple.isTakeable()) {
apple.take();
}
airplane plane("boeing");
if (plane.isTakeable()) {
plane.take();
} else {
plane.cannotTake();
}
// use of interface in general
ITakeable * something = &apple;
if (something->isTakeable()) {
something->take();
}
something = &plane;
if (something->isTakeable()) {
something->take();
} else {
something->cannotTake();
}
return 0;
}
Since fruit is a user defined type, you have to declare your own methods for your type or you inherit from one previously defined.
There are a lot of method for "built-in" string type
that Performs virtually the same job as eval (...) in python.
Also I noticed your function need not be defined independently outside of class fruit.
I have the following files:
main.cpp
shop.hpp
player.hpp
With the following code in each of them:
main.ccp:
#include <iostream>
#include <cstdlib>
#include "shop.hpp"
using namespace std;
string *inventory= new string[3];
int invGold= 355;
int main(void){
shop store;
store.store();
}
shop.hpp:
#include <iostream>
#include <cstdlib>
using namespace std;
class shop{
public:
string shopOption;
string shopOptions[6]= {"Buy", "buy", "Sell", "sell", "Leave", "leave"};
string shopInv[3]= {"Sword", "Potion", "Arrows x 25"};
int shopInvAmount= sizeof(shopInv)/sizeof(shopInv[0]);
int shopPrices[3]= {250, 55, 70};
shop(){
cout << "Shopkeeper: We buy, we sell, what's your buisness?" << endl;
}
void store(void){
getline(cin,shopOption);
if(shopOption.compare(shopOptions[0]) == 0 || shopOption.compare(shopOptions[1]) == 0){
buy();
}
else if(shopOption.compare(shopOptions[2]) == 0 || shopOption.compare(shopOptions[3]) == 0){
sell();
}
else if(shopOption.compare(shopOptions[4]) == 0 || shopOption.compare(shopOptions[5]) == 0){
leave();
}
}
void buy(){
srand(time(0));
string buyQuotes[3]= {"What are you buyin', hon?", "Make it quick, I ain't got all day.", "Another day, another sell."};
int quotePick= rand() % sizeof(buyQuotes)/sizeof(buyQuotes[0]) - 1;
if (quotePick < 0){
quotePick= 0;
}
else if (quotePick > (sizeof(buyQuotes)/sizeof(buyQuotes))){
quotePick= sizeof(buyQuotes)/sizeof(buyQuotes);
}
cout << "TEST:" << sizeof(shopInv)/sizeof(shopInv[0]) << endl;
cout << buyQuotes[quotePick] << endl;
cout << "SHOP INVENTORY" << endl << "--------------" << endl;
cout << endl;
for (int i=0; i < sizeof(shopInv)/sizeof(shopInv[0]); i++){
cout << shopInv[i]<< ": " << shopPrices[i] << endl;
}
cout << endl << "What'll it be?:";
getline(cin,shopOption);
}
void sell(){
}
void leave(){
}
};
and player.hpp
class player{
public:
int playerHP= 18;
string playerInv[5] {};
int playerGold= 355;
};
Now, what i'd like to do, is that after the character selects the items they want to buy, and te amount of it, (Not programmed yet) check the price of the combined items, and see if the character has enough money on hand, and if the character buys the items, add them to the player's inventory.
But i'd like to keep the values the store uses, and everything related to the player in different class files.
Thing is, I have no idea how to pull something like that.
So, is t possible to access a class' variable from another class that is in another file althogether?
And if isn't, how would you suggest i get around this problem?
Start reading here: How does the compilation/linking process work? to get multiple files working for you. Odds are pretty good that whatever coding environment you are using will automate the process for you.
Then consider making an item class
class Item
{
public:
Item(string name, int price): mName(name), mPrice(price)
{
}
string getName()
{
return mName;
}
string getPrice()
{
return mPrice;
}
// other functions
private:
string mName;
int mPrice;
// other stuff
}
In Shop and Player, keep a list of Items
vector<Item> items;
When a Player tries to buy an item, find it in the list, ensure the Player can afford it, remove it from the Shop's list and add it to the Player's list.
#include "assert.h"; // for some reason assert wouldn't work on my compiler without this
#include <iostream>
#include <string>
#include <limits> // This is helpful for inputting values. Otherwise, funny stuff happens
using namespace std;
class Product
{
public:
Product();
Product(string the_name, int the_price, int number_of);
string return_name();
void reduce_amount();
void print_data() const;
private:
string prod_name; // name of your product
int price_in_cents; // it's price in cents
int amount; // the number of the product that you have
};
Product::Product()
{
prod_name = "NULL_NAME: NEED DATA";
price_in_cents = 0;
}
Product::Product(string the_name, int the_price, int number_of)
{
assert(the_price>0);
assert(number_of>0);
assert(number_of<21);
assert(prod_name !="NULL_NAME: NEED DATA");
prod_name = the_name;
price_in_cents = the_price;
amount = number_of;
}
void Product::print_data() const
{
cout<<prod_name << endl;
cout<<"The price in cents is: " <<price_in_cents<< endl;
cout<< "Amount left: " << " " << amount << endl;
}
void Product::reduce_amount()
{
amount = amount -1;
}
string Product::return_name()
{
return prod_name;
}
class Vending_Machine
{
public:
Vending_Machine();
void empty_coins();
void print_vend_stats();
void add_product();
Product buy_product();
private:
int income_in_cents;
Product product1();
Product product2();
Product product3();
Product product4();
Product product5();
};
void Vending_Machine::empty_coins()
{
cout << "The total amount of money earned today is " << income_in_cents << " cents" << endl;
income_in_cents = 0;
cout << "All the coins have been withdrawn. The balance is now zero." << endl;
}
void Vending_Machine::print_vend_stats()
{
cout<< "Total income thus far: " << income_in_cents << endl;
if (product1().return_name() != "NULL_NAME: NEED DATA")
{
//stuff happens
}
}
int main()
{
return 0;
}
So, I'm not sure if I did all the identation correctly, but I'm having a problem with the boolean statement in vending machine print_vend_stats() function. It's saying I am making an undefined fereence to product1(). What does this mean?
When you declare
Product product1();
you declare a member function, the parentheses is what makes it a function.
If you drop the parentheses
Product product1;
you declare a member variable, an actual instance of the Product class.
Another example, you wouldn't write e.g.
int income_in_cents();
do declare income_in_cents as a variable, now would you?
It doesn't matter if the type is a primitive type like int, or a class like Product, Member variables are declared like normal variables like you do anywhere else.
So I'm having trouble understanding how Struct works in C++ I have develop a code in which I've been playing for a while but I don't seem to display for the results I'm looking for. I don't get any compiler errors or mistakes so it seems to be running ,This is what I have ...
Question: How do I display the results in "void Save_Player_Name(Player_Data Player)" later on in the future... ?
struct Player_Data
{
public: string Player_Name;// name of the player will be store here
}Customer[1];
int main()
{
Save_Name_File();
}
void Save_Name_File()// will capture the name of the player
{
int n;
int i = 1;// number of players
//cin.get();
for (n=0; n<i; n++)// will the player
{
cout << string(30, '\n');
cout << "Player Amount " << n << " Out of : " << i;
cout << "\n Please enter the name you wish to play \n\n Name: ";
getline (cin,Customer[n].Player_Name);
}
}
void Save_Player_Name(Player_Data Player)// will store the name of the player in a file
{
ofstream scores_data;
scores_data.open ("scores.dat", std::ios_base::app);
cout << Player.Player_Name << endl;
scores_data<< Player.Player_Name << "\n";
scores_data.close();
}
Edit: minor fixes.
Edit: Added class consideration.
Question: How do I display the results in "void
Save_Player_Name(Player_Data Player)" later on in the future... ?
If you are asking how to read the data in from a file:
const bool readFile()
{
ifstream ip;
ip.open("scores.dat", ifstream::in);
if( !ip )
{
printf("Unable to open file.");
return false;
}
// loop over every line in the file
string bffr;
while( getline(ip, bffr) )
{
<do something>
}
}
If you are referring to how to access the data stored in the variable:
Technically, you should be able to do the following from main:
Save_NameFile();
printf("Player name: %s", Customer[n].Player_name.c_str());
However, having Customer be global is bad for a number of reasons. Instead, you should create a local instance in main and pass it to your functions. You will then be able to access it in the same manner.
Note: I used printf instead of cout. I would recommend getting familiar with it. You'll need to include stdio.h, I believe.
Also, you need to make sure you are passing your struct by reference. There are a number of reasons why you should do this, but you will need to in order to get the data back out.
void Save_Player_Name(Player_Data &Player) {<<stuff here>>}
You should also be declaring your functions before main:
struct Player_Data
{
public: string Player_Name;// name of the player will be store here
};
void askUserForName(Player_Data &);
void writeNameToFile(Player_Data &);
void main()
{
Player_Data player;
askUserForName(player);
return;
}
void askUserForName(Player_Data &player)
{
<<do stuff>>
writeNameToFile(player);
return;
}
etc.
Unless you really need to use a struct, I would recommend going with classes. Structs make everything (variables and methods) public by default, whereas classes are private by default. In reality, structs and classes are identical--you can use them fairly interchangeably (don't shoot me!); in practice, structs are generally used when you need to aggregate some data (i.e., variables) without methods.
Your class might end up something like this (I haven't tested it, and I've been coding in Python lately, so please forgive any minor errors):
class PlayerData
{
public:
PlayerData()
{
}
~PlayerData()
{
}
void askUserForName()
{
<<code here>>
}
void writeNameToFile()
{
<<code here>>
// also write to screen
printf("[Write to console] name: %s\n", this->name_.c_str());
}
private:
std::string name_;
};
void main()
{
PlayerData player;
player.askUserForName();
player.writeNametoFile();
return;
}
In reality, you'd want to use a header file and separate things out, but I'll leave that for another day.
You haven't called the method that saves the player after you call Save_Name_File()
You need some logic fixes for your code
#include <iostream>
#include <fstream>
using namespace std;
struct Player_Data
{
public: string Player_Name;// name of the player will be store here
}Customer[1];
void Save_Player_Name(Player_Data Player)// will store the name of the player in a file
{
ofstream scores_data;
scores_data.open ("scores.dat", std::ios_base::app);
cout << Player.Player_Name << endl;
scores_data<< Player.Player_Name << "\n";
scores_data.close();
}
void Save_Name_File()// will capture the name of the player
{
int n;
int i = 1;// number of players
//cin.get();
for (n=0; n<i; n++)// will the player
{
cout << "Player Amount " << n << " Out of : " << i;
cout << "\n Please enter the name you wish to play \n\n Name: ";
getline (cin,Customer[n].Player_Name);
Save_Player_Name(Customer[n]);
}
}
int main()
{
Save_Name_File();
return 0;
}
I hope I got the relevant code in here. I have some problem when I want to fetch the menu option that I've added into to menu_1. I have this function on_select(int) that I use to fetch one sub-menu's options, which I do by using the display() function. But when I compile it will say that there are no function named display() in menu_option() class, which is the Base class, but what I want to is to access the display() function which is located in the sub_menu() class.
I have tried multiple thing to get the relevant object from the array without any success, so I'm here now asking for help with this one.
I have this following main()
#include <iostream>
using namespace std;
#include "menu.h"
int main()
{
sub_menu* main_menu = new sub_menu("Warehouse Store Menu");
sub_menu* menu_1 = new sub_menu("Menu1");
main_menu->add_option(new sub_menu("Menu2"));
main_menu->add_option(menu_1);
product_menu->add_option(new add_item("sub_item1"));
product_menu->add_option(new add_item("sub_item2"));
product_menu->add_option(new add_item("sub_item3"));
main_menu->display();
main_menu->on_select(1);
delete main_menu;
return 0;
}
header file
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;
const int MAX_SIZE = 9;
class menu_option
{
public:
menu_option(string const& n) : title(n) {};
virtual ~menu_option();
virtual void on_select(int) = 0;
string get_title() { return title; }
protected:
string title;
};
/* ------------------------------------- */
class sub_menu : public menu_option
{
public:
sub_menu(string const& n)
: menu_option(n) { no_item = 0; }
~sub_menu() { delete[] list; };
void on_select(int);
void add_option(menu_option*);
void display();
private:
menu_option* list[MAX_SIZE]; //container for options in the sub_menu
int no_item;
};
implement file
void sub_menu::on_select(int i)
{
cout << (list[i])->get_title() << endl;
cout << (list[i])->display() << endl; //<------ Doesn't work
}
void sub_menu::add_option(menu_option* item)
{
list[no_item] = item;
no_item++;
}
void sub_menu::display()
{
cout << ">> " << get_title() << " <<"<< endl;
for( int i = 0; i < no_item; i++ )
{
cout << setw(2) << i << ": " << (list[i])->get_title() << endl;
}
}
You can do what you want to do, but it's bad. You have to cast down to sub_menu when you call display() in on_select(). Of course it's not going to work the way you have it, and the compiler is telling you exactly why.
The other option, which is probably better (though without a clear understanding of the problem space may not be the best) would be to add display() as a virtual function to the menu_option class.
To solve your immediate problem you'll want to use dynamic_cast to turn a menu_option* into a sub_menu*, like so:
sub_menu* submenu(dynamic_cast<sub_menu*>(list[i]));
Note that if the cast fails (i.e., the menu_option pointed to by list[i] is not a sub_menu after all) the value of the submenu pointer will be NULL, so make sure you check that it is a valid pointer before using it in subsequent code.