How to compare a vector to a map [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Okay so I have an inventory class that accesses a static vector from my base class MainShop. I also have a SwordShop class which inherits from MainShop. (Both Inventory and SwordShop are derived classes).
//SwordShop class
void SwordShop::Shop
{
//I have a setter function where it takes an integer and a string and adds its to my hashmap.
//Also have a getter function which has a for loop displaying my items in my map
this->setWeaponSoldier(1, "1) Meito Ichimonji\n +4 Damage\n 150Gold");
this->setWeaponSoldier(2, "2) Shusui\n +10 Damage\n 230Gold");
this->setWeaponSoldier(3, "3) Elixir\n +16 Damage\n 300Gold");
this->setWeaponSoldier(4, "4) Blade of scars\n +24 Damage\n 550Gold");
this->setWeaponSoldier(5, "5) Ragnarok\n +32 Damage\n 610Gold");
this->setWeaponSoldier(6, "6) Eternal Darkness\n +40 Damage\n 690Gold");
this->setWeaponSoldier(7, "7) Masamune\n +52 Damage\n 750Gold");
this->setWeaponSoldier(8, "8) Soul Calibur\n +60 Damage\n 900Gold");
}
//Function in my inventory class
void Inventory::DisplayInventory()
{
int choice;
cout << "\nWhat do you want to do?\n1) Check Status\n2) Equip Weapons\n";//Equip what is in your inventory
cin >> choice;
switch (choice)
{
case 1: this->DisplayStats();
break;
case 2:cout << WeaponInventory.size() << endl;//debug
if (!WeaponInventory.empty())//Make sure inventory is not empty
{
cout << "Your current Weapons are: \n";
for (unsigned int i = 0; i < WeaponInventory.size(); ++i)
cout << i+1 << ") " << WeaponInventory[i] << endl;//cout whats currently in my inventory
cout << "What item weapon would you like to equip?";
/***********Here is the problem*******************/
//how can I make the user choose the actual and correct item in the inventory?
//cin >> equipChoice;
//code goes here
}
else cout << "Error! You currently do not own any items\n";
break;
}
So for example lets say the user adds Meito Ichimonji into my WeaponInventory vector and then adds another one. How can I make the user have the ability to pick the right item? Im looking for something like this:
//PseudoCode
Displays my inventory with for loop
I have two items in it which user buys
1)Meito Ichimonji
and
2)Elixir
cout << "what would you like to equip?";
cin >> equipChoice
if (equipChoice == 1)//chooses whatever item is first
check to see what the attack that the weapon has and add it to my attack
attack += 20;//lets say the sword had 20 attack
else if (equipChoice == 2)//chooses whatever is second
do something else
etc...
Sorry if I have not explained it clearly, but I tried my best!

This is not really an issue of coding/code-design but rather a conceptual design issue. I would propose to start from a blank slate and formalise the design, possibly using a 'relational' perspective, even though you might not use an RDMS in an implementation (or some other formalism like UML) just to put some clear stakes in the ground. At least such model would give a clear view of the relationships between the various entities and help understanding what is needed in order to access/retrieve information from the model. Most likely the code will then be the least you'll have to worry about.

Related

C++ an array of pointers to the base class [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
There are several classes which are made in different files.
Here are the class name: Hospital class and patient class.
Basically, for hospital class, it has array of pointers for patient which can store the information of patient based on their patient type. For patient class(base class) has four derived classes as follows: male, female, inpatient, outpatient. What I am trying to do is, in hospital class, I want to assign the object according to the patient type.
#include <iostream>
#include "Hospital.h"
#include "Female.h"
#include "Male.h"
#include "Inpatient.h"
#include "Outpatient.h"
using namespace std;
Hospital::Hospital(const char * name, int capacity)
{
hospitalName=name;
patientCapacity=capacity;
totalPatients=0;
}
void Hospital::determinePatientType()
{
int selection;
cout << "What is the patient type?" << endl;
cout << "1. Female" << endl;
cout << "2. Male" << endl;
cout << "3. Outpatient" << endl;
cout << "4. Inpatient" << endl;
cin >> selection;
if(selection==1)
{
patients = new Patient[totalPatients];
Female* female = new Female();
patients = female;
}
else if(selection==2)
{
patients = new Patient[totalPatients];
Male* male = new Male();
patients = male;
}
else if(selection==3)
{
patients = new Patient[totalPatients];
Outpatient* outpatient = new Outpatient();
patients = outpatient;
}
else
{
patients = new Patient[totalPatients];
Inpatient* inpatient = new Inpatient();
patients = inpatient;
}
totalPatients++;
}
This is my code, but I am not sure if it's correct or not.
And I will upload the class diagram for your understanding what I am doing.
Thank you for your assistance in advance.
enter image description here
No your code is not correct.
Lets take a look at this code snippet:
if(selection==1)
{
patients = new Patient[totalPatients];
Female* female = new Female();
patients = female;
}
With
patients = new Patient[totalPatients];
you allocate an array of totalPatients objects. You make patients point to the first element of that array.
Then two lines down you do
patients = female;
That reassigns the variable patients to point to the single object female.
You will lose the original memory from the first allocation, which will lead to a leak. It will most likely also lead to undefined behavior if you then use delete[] patients since patients no longer point to an array.
Unless your exercise is to lean how to use pointers and dynamic memory allocation, you should use std::vector.
There's also another potential issue, and that relates toobject slicing and polymorphism (if the classes are polymorphic, i.e. they have virtual member functions).
If you solve the first problem the natural way, by doing e.g.
patients[totalPatients] = female;
Or if you use a std::vector<Patient> and do a simple push_back(female).
Then you slice the female object, and lose all data specific for the Female class. And since you no longer have a Female objects, all virtual functions will think they are called on a Patient object, making polymprphism not working either.
To solve this problem you should have a vector (or array) of pointers to the base Patient class. Like e.g. std::vector<Patient*>.
Or better yet use a smart pointer like std::unique_ptr as in std::vector<std::unique_ptr<Patient>>.

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 use typedef in function?

I am coding Quicksort to sort binary files that contains different data type(structs). This is what i wrote so far:
void quicksort(){
int izbor;
char naziv_datoteke[20];
cout << "Izaberite datoteku koju zelite sortirati: "<<endl;
cout << "1 - sifra.ind "<<endl;
cout << "2 - ime.ind "<<endl;
cout << "3 - prezime.ind "<<endl;
cin >>izbor;
switch(izbor){
case 1:strcpy(naziv_datoteke, "sifra.ind");
typedef tsifra slog;
break;
case 2:strcpy(naziv_datoteke, "ime.ind");
typedef time slog;
break;
case 3:strcpy(naziv_datoteke, "prezime.ind");
typedef tprezime slog;
break;
}
int broj_zapisa;
dat.open(naziv_datoteke, ios::in|ios::out|ios::binary);
dat.seekg(0, ios::end);
broj_zapisa=dat.tellg()/sizeof(slog);
// quicksort(0, broj_zapisa-1);
dat.close();
}
I am getting this error:
conflicting declaration 'typedef struct time slog'
I would like to define slog as data type that is stored in file so I can use it later for getting the size of that struct and few other things.
Touching on what Sam mentioned: please have a look at this answer and this page for further information on the topic. Hopefully they help you understand the bigger picture.
To answer your question directly: Defining slog as a data type at runtime is just gonna be messy. More details here.
A quick solution to what you want would be to define a struct slog, which can hold different information for you, like so:
struct slog()
{
int my_val_int = -1;
char* my_val_char = "";
}
Once it's time to return the value, you just check which value is actually set by checking if my_val_int is anything different than your default or if char is not empty.
Mind you, this is a very quick and dirty way of doing it. Please use it only as a starting point to develop your own idea of how to structure the program, so it works in a lean and mean manner! :-)
Goodluck!

Intro to classes (c++) project wants us to create two constructors, but neither of them need any parameters - what should i do here?

I think I'm just confused on the wording to this project, but I'm posting here to make sure I have the basics on classes correct (like I said, we just started learning them).
The beginning of the project prompt is as follows:
Declare and define a class called Odometer. This class will have two private variables, one for the miles driven and the other for the gallons of gas pumped into the car.
The member functions should include:
A constructor that takes initial values for both of the private variables.
A default constructor that sets both values to zero.
Along with more member functions that aren't important for my problem. I understand the default constructor fully, but the other is the one I'm having troubles with. If he (my professor) wants us to gather initial variables, then why would it need any parameters at all? I guess I could pass an empty string into it as a parameter, but I feel like there's something I'm missing here...
To expand on the point of this project, in case it's needed, we are creating a program that allows the user to continually enter (on a menu screen) either miles driven or gallons put into their tank. The program will then find the mpg, when the user requests it. Very simple.
Here's part of the program, which should be enough for someone to help me with this. The second/non-default constructor seems like it would work, except obviously I need some type of parameter. Any suggestions or help is greatly appreciated.
#include <iostream>
using namespace std;
class Odometer{
public:
Odometer(); // sets values to 0
Odometer(WHAT GOES HERE); // gathers initial values
void get_miles();
void get_gallons();
void add_in_trip_miles();
void add_gas();
private:
double milesDriven; // represents the miles the car has driven
double gallonsGas; // represents the number of gallons pumped into car
};
int main() {
Odometer userInfo; // creates object for the user-inputted values
bool quit = false; // true when user wants to quit
int userChoice; // for navigating the menu screen
while(!quit){
cout << "To view total miles, enter 1. To view total gallons, enter 2.\nTo record more miles driven, enter 3. To record gallons pumped into the tank, enter 4.\n To view the average MPG, enter 5. To reset the odometer, enter 6.\n To quit the program, enter 7." << endl;
cin >> userChoice;
if(userChoice == 1) userInfo.get_miles(); // TODO: switch/case statement instead?
if(userChoice == 2) userInfo.get_gallons();
if(userChoice == 3) userInfo.add_in_trip_miles(); // TODO: "function which increases the miles by the amount sent in its parameter
}
cout << "Have a nice day!" <<endl;
return 0;
}
Odometer::Odometer(){ // sets values to 0 (default)
milesDriven = 0;
gallonsGas = 0;
}
Odometer::Odometer(WHAT GOES HERE?){ // gathers initial values
cout << "Please enter an initial value for miles driven." << endl;
cin >> milesDriven;
cout << "Please enter an initial value for how many gallons were put into the car." << endl;
cin >> gallonsGas;
}
Your teacher is asking you to implement the second constructor with parameters so user will be able to initialize the object with the state he wants. I would implement it like this:
Odometer(double milesDriven_, double gallonsGas_) :
milesDriven(milesDriven_),
gallonsGas(gallonsGas_)
{}

Somehow my values don't seem to all be inserting into a list [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I am doing a homework assignment where I am supposed to use our professors contiguous list class to store a list of personal record which can then be printed or searched for a specific record. The personal record struct contains only member data for a first_name, last_name and int code.
My problem is inserting the records. We have to insert in correct alphabetical order, and any records with the same first and last name are discarded. My code is below:
string input;
cout << endl << "Enter Data File Name:" << endl;
getline(cin, input);
ifstream insertion_file;
insertion_file.open(input.c_str());
if(!insertion_file.fail()){
record_list.clear();
while(!insertion_file.fail() && !insertion_file.eof()){
Personal_record input_rec;
string code_string;
getline(insertion_file, input_rec.last_name);
getline(insertion_file, input_rec.first_name);
getline(insertion_file, code_string);
input_rec.code = string_to_int(code_string);
//implementation of requirement 1
if (record_list.empty()) record_list.insert(0, input_rec);
else {
int i = 0;
Personal_record temp;
//while loop increments i and retrieves a record until input_rec.last_name is not smaller than temp.last_name
do {
record_list.retrieve(i, temp);
i++;
} while (input_rec.last_name < temp.last_name && i <= record_list.size());
//if last_names are the same, check first names
if (input_rec.last_name == temp.last_name) {
while (input_rec.first_name < temp.first_name) record_list.retrieve(++i, temp);
//if last names are the same, only insert if there is no matching first name
if (input_rec.first_name != temp.first_name) record_list.insert(i, input_rec);
}
//if last name is not the same, insert
else record_list.insert(i, input_rec);
}
}
} else
cout << "Invalid file name." << endl;
Only the code after the comment "implementation of requirement 1" is mine, the rest is professor code that cannot be altered.
I am not getting any compiler errors, but the program seems to freeze somewhere in the process. After inserting the records from the file it should return control back to the user to enter a command, but this never happens. I am trying to use the Visual C++ debugger, but I am unfamiliar with it and it isn't giving me much insight. Any help is greatly appreciated!
You are accessing both element 0 and element size(). Unless size() in your program actually means size - 1, that's a problem.