Displaying array of a Structure/Class Errors C++ - c++

So, I have a hero structure that contains name, health, and attack. I'm allowing the user to enter how many heroes they want to create and create an array of that many heroes (I also had problems allowing the user to determine the array size, so the problem could be there). When trying to set the attributes using a loop of the array, I get an error: IntelliSense: no operator "[]" matches these operands. operand types are: Hero [ int ]
My question is, how do I loop through an array of a structures to set their attributes and if so, would displaying the hero's information be similar with a display function?
struct Hero
{
private:
string hName;
int hHealth;
int hAttack;
public:
void displayHeroData();
void setName(string);
void setHealth(int);
void setAttack(int);
};
void Hero::displayHeroData()
{
cout << "\n\n\n\nHERO INFO:\n" << endl;
cout << "Name: " << hName << endl;
cout << "Health: " << hHealth << endl;
cout << "Attack: " << hAttack << endl;
};
void Hero::setName(string name)
{
hName = name;
}
void Hero::setHealth(int health)
{
if(health > 0)
hHealth = health;
else
hHealth = 100;
}
void Hero::setAttack(int attack)
{
if(attack > 0)
hAttack = attack;
else
hAttack = 100;
}
int main()
{
string name;
int health;
int attack;
int num;
Hero *heroList; //declaring array
//getting size of array
cout << "How many hero's do you want to create? (greater than 0)" <<endl;
cin >> num;
heroList = new Hero[num]; //this is the array of Heroes
//looping through the array
for(int x = 0; x < num; ++x){
//creating a new hero, I think???
Hero heroList[x];
//setting hero's name
cout << "What is hero" << x <<"'s name?" << endl;
cin >> name;
heroList[x].setName(name);
//display the character after attributes have been set
heroList[x].displayCharacterData();
}//end of for loop
return 0;
}

Hero heroList[x];
Remove this line for good. no need for it.

The only problem that you will encounter after removing the line proposed (Hero heroList[x]) is that all the hero objects created aren't initialized (when you called new Hero[num] you only allocated the array and created the default implicit constructor for each one).
In order to init all of them, you must either use all your 'setters', or write a non-default constructor and then only allocate an array of Hero* ptrs, and when looping through it init each ptr to a new Hero(.....) with the parameters you wish.
Hope that helps clarify things.

In the loop just do the following
//looping through the array
for(int x = 0; x < num; ++x)
{
cout << "What is hero" << x <<"'s name?" << endl;
cin >> name;
heroList[x].setName(name);
}
for(int x = 0; x < num; ++x)
{
heroList[x].displayHeroData();
}

Related

What needs to be in the constructor and what needs to be in the setter functions?

The objective is to output the same data as the first program.
The first program requires manual input of the room number and room cost. The second (problematic) program requires it to auto populate with the room number and room cost being hard coded in to an array within the main.
A default constructor of the class "room" is needed to populate the array and add setter functions to set the values of the room number and cost.
The objective of the whole program is to create the array, populate with test data and then list the data about the rooms.
Program 1 (manual in put) - this works fine;
#include<iostream>
using namespace std;
class room
{
int roomNo;
float roomCost;
public:
void GetData ();
void PutData ();
};
void room::GetData ()
{
cout << "\n\tEnter room number : ";
cin >> roomNo;
cout << "\n\tEnter room cost : ";
cin >> roomCost;
}
void room::PutData ()
{
cout << "\n\t\t\t" << roomNo << " \t|\t " << roomCost;
}
int main ()
{
int roomNo;
room roomList[10];
for (roomNo = 0; roomNo < 10; roomNo++)
{
cout << "\nEnter details of " << roomNo + 1 << " room" << endl;
roomList[roomNo].GetData ();
}
cout <<"\n*******************************************************************************";
cout << "\n\t\t\t Room Details";
cout <<"\n*******************************************************************************";
cout << "\n\t\t Room Number \t| Cost per Night";
cout << "\n\t\t--------------------------------------";
for (roomNo = 0; roomNo < 2; roomNo++)
roomList[roomNo].PutData();
getchar ();
getchar ();
}
Second (problematic) program;
#include<iostream>
using namespace std;
class room
{
int roomNo;
float roomCost;
public:
room();
void PutData ();
};
room::room()
{
cout<<"\n\t\t\t"<<roomNo<<" \t|\t "<<roomCost;
}
void room::PutData ()
{
cout << "\n\t\t\t" << roomNo << " \t|\t " << roomCost;
}
int main ()
{
int roomNo[10] = {1,2,3,4,5,6,7,8,9,10};
float roomCost[10] = {100.00, 90.00, 85.50, 80.00, 80.00, 50.00, 50.00, 45.50, 45.50, 40.00};
room roomList[10]; //Statement 3 : Creating Array of 3 Employees
cout <<"\n*******************************************************************************";
cout << "\n\t\t\t Room Details";
cout <<"\n*******************************************************************************";
cout << "\n\t\t Room Number \t| Cost per Night";
cout << "\n\t\t--------------------------------------";
for (int roomNo = 0; roomNo < 10; roomNo++)
roomList[roomNo].PutData();
getchar ();
getchar ();
}
The problem is that roomNo and roomCost never actually get set to anything for each room instance. The class won't automatically pull from the arrays you define in main.
Additionally,
roomList[roomNo].PutData();
Accesses uninitialized data:
void room::PutData ()
{
cout << "\n\t\t\t" << roomNo << " \t|\t " << roomCost;
}
(The constructor has the same problem)
The solution is to initialize each room with the correct data. I recommend using the constructor:
room(int _roomNum, float _roomCost) : roomNo(_roomNum), roomCost(_roomCost)
{}
Then use a vector to initialize (instead of room roomsList[10])
std::vector<room> rooms;
rooms.reserve(10);
for(size_t i = 0; i < 10; ++i)
rooms.emplace_back(roomNo[i], roomCost[i]);
Live Demo
You should have two setters, one for each member, and then write your loop like
for (int n = 0; n < 10; n++)
{
roomList[n].setNumber(roomNo[n]);
roomList[n].setCost(roomCost[n]);
}
(On a side note, you should do the same with the first program and handle user input in main.)

How to allow user input in objects and classes?

Consider the following code:
#include <iostream>
using namespace std;
class inventory
{
public:
~inventory()
{
cout << "This Object is being destroyed" << endl;
}
inventory()
{
itemNumber = 0;
quantity= 0;
cost= 0;
}
inventory(int itemNumber1, int quantity1, double cost1)
{
setItemNumber(itemNumber1);
setQuantity(quantity1);
setCost(cost1);
}
void setItemNumber(int itemNumber2)
{
itemNumber=itemNumber2;
}
bool setQuantity(int quantity2)
{
bool userTrue = true;
bool userFalse = false;
if (quantity2 < 0)
{
quantity = 0;
return userFalse;
}
else
{
quantity= quantity2;
return userTrue;
}
}
bool setCost(double cost2)
{
bool userTrue = true;
bool userFalse = false;
if (cost2 < 0.0)
{
cost = 0.0;
return userFalse;
}
else
{
cost= cost2;
return userTrue;
}
}
double getTotalCost(int quantity, double cost)
{
int total;
total = (quantity * cost);
return total;
}
private:
int itemNumber;
int quantity;
double cost;
};
int main()
{
int itemNumberInput;
int quantityInput;
double costInput;
cout << "Enter the Item Number: " << endl;
cin >> itemNumberInput;
cout << "Enter the Quantity : " << endl;
cin >> quantityInput;
cout << "Enter the Cost : " << endl;
cin >> costInput;
inventory *pointerA, *pointerB;
pointerA = new inventory;
pointerB = new inventory(inventory(itemNumberInput , quantityInput , costInput));
inventory firstObject(itemNumberInput,quantityInput,costInput);
int itemNumberInput1;
int quantityInput1;
double costInput1;
cout << "Enter the Item Number: " << endl;
cin >> itemNumberInput1;
cout << "Enter the Quantity : " << endl;
cin >> quantityInput1;
cout << "Enter the Cost : " << endl;
cin >> costInput1;
inventory secondObject(itemNumberInput1,quantityInput1,costInput1); // not sure if thats correct
cout << secondObject.setItemNumber(); // not working
cout << secondObject.setQuantity(); // not working
cout << secondObject.setCost(); // not working
return 0;
}
The code above is supposed to take three user inputs, and send them to the classes, and the classes will do their job.
I'm currently stuck at the end where its giving me an error.
In the second object where the values are asked from the user, it should send these values to the classes.
Instead, I'm getting the error.
How can I resolve this problem?
Here is the fixed code:-
#include <iostream>
using namespace std;
class inventory
{
public:
~inventory()
{
cout << "This Object is being destroyed" << endl;
}
inventory()
{
itemNumber = 0;
quantity= 0;
cost= 0;
}
inventory(int itemNumber, int quantity, double cost)
{
this->itemNumber = itemNumber;
this->quantity = quantity;
this->cost = cost;
}
void setItemNumber(int itemNumber)
{
this->itemNumber=itemNumber;
}
bool setQuantity(int quantity)
{
bool userTrue = true;
bool userFalse = false;
if (quantity < 0)
{
this->quantity = 0;
return userFalse;
}
else
{
this->quantity= quantity;
return userTrue;
}
}
bool setCost(double cost)
{
bool userTrue = true;
bool userFalse = false;
if (cost < 0.0)
{
this->cost = 0.0;
return userFalse;
}
else
{
this->cost= cost;
return userTrue;
}
}
double getTotalCost(int quantity, double cost)
{
return quantity * cost;
}
private:
int itemNumber;
int quantity;
double cost;
};
int main()
{
int itemNumberInput;
int quantityInput;
double costInput;
cout << "Enter the Item Number: " << endl;
cin >> itemNumberInput;
cout << "Enter the Quantity : " << endl;
cin >> quantityInput;
cout << "Enter the Cost : " << endl;
cin >> costInput;
inventory *pointerA, *pointerB;
pointerA = new inventory;
pointerB = new inventory(inventory(itemNumberInput , quantityInput , costInput));
inventory firstObject(itemNumberInput,quantityInput,costInput);
int itemNumberInput1;
int quantityInput1;
double costInput1;
cout << "Enter the Item Number: " << endl;
cin >> itemNumberInput1;
cout << "Enter the Quantity : " << endl;
cin >> quantityInput1;
cout << "Enter the Cost : " << endl;
cin >> costInput1;
// The below line is correct
// inventory secondObject(itemNumberInput1,quantityInput1,costInput1);
//Alternatively
inventory secondObject;
secondObject.setItemNumber(itemNumberInput1);
secondObject.setQuantity(quantityInput1);
secondObject.setCost(costInput1);
delete pointerA; // delete dynamically allocated memory to avoid memory leak
delete pointerB;
return 0;
}
Well you've constructed 'secondObject' object using the 3-arg constructor, using the user-entered values as parameters. Therefore, the member variables of this object are being set via the constructor and using the 'set' methods aren't really necessary. In your case, the set methods would be useful if you wanted to change the values later on. For example, lets pretend the user enters 10, 10, and 2.5 for the values. You're then using the constructor to construct the object with those values. The only difference is you're placing those values into variables first. But it works the same way. If you wanted to change the value of quantity later on, you could do secondObject.setQuantity(2); And the quantity for that object is now set to 2. The reason why your calls to .set aren't working is because you need to pass in parameters to these methods i.e. the value you want to set it to.
In regard to the destructor method being printed, objects are destroyed when they go out of scope so that the memory is released. Normally, nothing would happen in terms of output- the object would just go out of scope and the compiler would free up the memory and go about its' business. However, you've coded a custom destructor that prints out 'The Object is being destroyed', which it is at the end of the main. It's likely your constructor is working fine, I'm just not sure what you expect to be happening. I'd also suggest you read up on memory leaks in C++, especially in regard to the 'new' keyword.

Issues with retrieving information from a class module for output within a switch statement

I know this may be something obvious to some with experience but I am in the middle of my first real class for C++ programming. I have come across something in my code that I have been trying to resolve without any success. I am trying to extract the sum of the total value of "m_cost" stored within a array that is inside of these class modules. I want to output the total value inside of a switch statement for print out. Just seeing if someone can point me in the right direction or if I have completely gone off-track with the logic.
Project Code section in question:
void materialsMenu()
{
Inventory record[MAX_REC];
int i, n;
cout << "\n=====Inventory Management=====\n";
cout << "\nHow many Materials are there to be used? : ";
cin >> n;
cout << "Enter " << n << " Materials\n";
for (i = 0; i < n; i++)
record[i].getdata();
cout << "\n\n---Material Information---\n";
cout << "\n" << setw(8) << "Item Name "
<< setw(10) << " Price per foot "
<< setw(19) << " Cost " << endl;
cout << endl << "-------------------------------------------" << endl;
for (i = 0; i < n; i++)
record[i].showdata();
}
void Inventory::getdata() {
cout << endl;
cout << "\nEnter Material Name : ";
cin >> itemName;
cout << "Enter Price Per Foot : ";
cin >> ppf;
cout << "Enter Total Length Needed in Feet (ft) : ";
cin >> length;
cout << endl;
m_cost = ppf*length;
m_costT=???????? **this is the issue**
}
Materials.H file contents:
#ifndef MATERIALS_H
using namespace std;
class Materials {
private:
char itemName[15];
float ppf;
float length;
double m_cost;
float m_costT;
public:
Materials()
{
ppf = 0;
length = 0;
m_cost = 0;
m_costT = 0;
}
Materials(int itemName, float ppf, float length, double m_cost, float
m_costT)
{
length = getLength();
ppf = getPpf();
m_cost = getCost();
m_costT = getTotal();
}
float getLength()
{
return length;
}
float getPpf()
{
return ppf;
}
double getCost()
{
return m_cost;
}
float getTotal()
{
return m_costT;
}
void getdata();
void showdata();
};
#endif // !MATERIALS_H
Consider something like this to hold your records. It's very simple, but it demonstrates the idea of one class holding another and shows information hiding and all sorts of other tidbits. You are struggling to get that total because the Record class shouldn't care about this. The total is a concept outside of the scope of a Record. And as such, it is very difficult to calculate this from where you wanted to do it. (Though it is possible, it breaks all sorts of C++ rules and should be avoided)
Example:
class Record;
class RecordHolder
{
public:
int GetTotal()
{
int retVal = 0;
for(int i=0; i<10; i++) // Magic number 10 for demo purposes only...
{
retVal += records[i].m_cost; // Or use a public get function.
}
return retVal;
}
private:
Record records[10]; // Magic number 10 for demo purposes only...
};
The RecordHolder could also do printing, add/removing records, etc. It controls the records array. The Records are just Records and don't care about such management.

printing name in multiple for loops and arrays

I've come across a little problem, how do I print the winning candidate's name? See the instructions here are, input five names, their number of votes and percentage of votes, whoever has the highest wins. I don't know if I did my code right, but it works.. well except for the name part. I've tried everything from a lot of for loops to transfer the array or what.
I'm almost done with the code.
Here's the code
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
char candidates[50];
int votes[5]={0};
float percent[5]={0};
int a,b,c,d,e,i;
int maxx;
int champ=0;
char winner[50];
cout << "Enter the candidates' last names: ";
cout << endl;
for(a=1;a<=5;a++)
{
cout << a << ". ";
cin >> candidates;
}
cout << endl;
cout << "Enter their number of votes: " << endl;
for(b=1;b<=5;b++)
{
cout << b << ". ";
cin >> votes[b];
}
cout << endl;
cout << "percentage of votes: " << endl;
for(c=1;c<=5;c++)
{
cout << c << ". ";
percent[c]=votes[c]*0.2;
printf("%.2f\n", percent[c]);
}
cout <<"Candidates\t\tVotes\t\t% of Votes" << endl;
for(int k=1;k<=5;k++)
{
cout << candidates[k] << "\t\t\t" << votes[k] << "\t\t\t";
printf("%.2f\n", percent[k]);
}
maxx=percent[0];
for(d=1;d<=5;d++)
{
if(maxx<percent[d]);
{
//what happens here?
}
}
return 0;
}
You should keep a 2d array of characters or array of string for storing candidate names instead of a 1-d array.
char candidates[5][10]; //
for(int i = 0; i < 5; i++)
{
cin >> candidates[i];
}
Then keep a variable to store index for winning candidate
int winIndex = 0;
int winPercent = 0;
for(int i = 0; i < 5; i++)
{
if(percent[i] > winPercent)
{
winPercent = percent;
winIndex = i;
}
}
Finally print name of winning candidate;
cout << candidates[winIndex];
In object oriented approach, you may create a class with following information
class Candidate
{
string name;
int votes;
float percent;
};
Use string candidates[50]; instead of char candidates[50];
then cin >> candidates[a];

C++ Class Variable Scope

I have a question about variable scope in a C++ class. The problem I'm working on says to create a class that holds an array of structures, with each structure holding the name, cost, and amount for a particular type of drink.
The class should have public member functions to buy a drink and display the menu, and private functions to get and validate money input (called by buy_drink) and to display an end of day report (called by the destructor).
I have a problem with the scope in the private function input_money. I get an error saying that the array has not been defined yet. I tested the display_data function (for printing the menu), and it worked fine on its own, but now I can't figure out why input_money would have a scope error and display_data wouldn't. Here is the header file:
/* need to create a class that holds an array of
5 structures, each structure holding string drink name,
double cost, and int number in machine
class needs public functions to display data and
buy drink
private functions input money -- called by buy_drink to accept,
validate, and return to buy drink the amount of money input
daily report -- destructor that reports how much money
was made daily and how many pops are left in machine */
#ifndef DRINKS_H
#define DRINKS_H
#include <string>
class Drinks
{
private:
struct Menu
{
std::string name;
double cost;
int number;
};
Menu list[5]; // array of 5 menu structures
double money_made; // track money made during the day
double input_money(int); // return validated money to buy_drink()
void daily_report(); // called by deconstructor
public:
Drinks();
~Drinks();
void display_data();
void buy_drink(int);
};
#endif
And here is the implementation file:
/* implementation file for Drinks class */
#include <iostream>
#include <string>
#include "drinks.h"
using namespace std;
const int SIZE = 5;
const int START_SIZE = 100;
Drinks::Drinks()
{
list[0].name = "Coke";
list[1].name = "Root Beer";
list[2].name = "Orange Soda";
list[3].name = "Grape Soda";
list[4].name = "Bottled Water";
for (int count = 0; count < (SIZE-1); count++)
list[count].cost = .75;
list[4].cost = 1;
for (int count = 0; count < SIZE; count++)
list[count].number = 20;
money_made = 0;
}
void Drinks::display_data()
{
for (int count = 0; count < SIZE; count++) {
if (count == 0)
cout << count+1 << list[count].name << "\t\t$ ";
else
cout << count+1 << list[count].name << "\t$ ";
cout << list[count].cost << "\t"
<< list[count].number << endl;
}
}
double input_money(int c)
{
double input;
cin >> input;
while (input != list[c].cost) {
if (input < list[c].cost) {
cout << "Not enough money.\n"
<< "Enter " << list[c].cost - input
<< " more cents to buy\n\n> ";
cin >> input;
}
else if (input > list[c].cost) {
cout << "Too much money.\n"
<< "I only need $" << list[c].cost << endl
<< "Enter " << input - list[c].cost
<< " less money: ";
cin >> input;
}
}
return input;
}
void Drinks::buy_drink(int c) // this receives an int choice (to access corresponding structure in the list array)
{
double input;
cout << "Enter " <<list[c].cost
<< " to purchase " << list[c].name
<< "\n\n> ";
input = input_money(c); // input money returns a validated and accurate price for the drink and is passed the choice to access array
list[c].number -= 1;
money_made += list[c].cost; // add cost of drink to money made
}
void Drinks::daily_report()
{
int end_size = 0;
for (int count = 0; count < SIZE; count++)
end_size += list[count].number;
cout << "Today, you made $" << money_made << endl;
cout << "There are " << START_SIZE - end_size
<< " drinks left in the machine" << endl;
}
Drinks::~Drinks()
{
daily_report();
cout << "goodbye mr anderson\n";
}
Any help would be much appreciated! I can't seem to figure out why the input_money function does not have access to the structures in the array.
Thank you!
EDIT: Total noob mistake/carelessness. Forgot to add the name of the class in the input_money function definition and use the scope resolution operator (i.e. should be Drinks::input_money(int c)). Thanks to those who answered.
double Drinks::input_money(int c)
// ^^^^^^^^ forgot this
You forgot the class name while providing the implementation.
Notice the difference between your definition of
void Drinks::display_data
and
double input_money(int c)
In the second case you have defined a free function that is not a member of the class and has no information about the class members. It should be
double Drinks::input_money(int c)