How to access array in function outside of main? - c++

I am trying to create a program that prints out a store inventory. I print out the variables from my objects in the getInventory function. However, when I try and print out the entire inventory in the getStore function it returns nothing. I feel like it is an issue with my pointer properly pointing to my array but I am not sure.
#include <iostream>
#include <string>
class Weapon
{
private:
std::string nameWeapon, messageUsed;
bool ownedWeapon;
double weaponCost;
int numberUses;
public:
//Default constructor
Weapon()
{
nameWeapon = "weapon name";
messageUsed = "weapon sound";
weaponCost = 0;
ownedWeapon = false;
numberUses = 1;
}
//Non-Default Constructor
Weapon(std::string nW, std::string mU,double wC,bool oW, int nU )
{
nameWeapon = nW;
messageUsed = mU;
weaponCost = wC;
ownedWeapon = oW;
numberUses = nU;
}
void getInventory()
{
std::cout << nameWeapon << "\t" << messageUsed << "\t" << weaponCost << "\t" << ownedWeapon << "\t" << numberUses << "\n";
}
void getStore(Weapon* weaponArray)
{
std::cout << "Name" << "\t" << "Sound" << "\t" << "Price" << "\t" << "Owned";
for (int i = 0; i < 9; i++)
{
weaponArray[i].getInventory();
}
}
};
int main()
{
Weapon weaponArray[9]{};
weaponArray[0] = Weapon("Broad Sword","Clang!",50,false,3);
weaponArray[1] = Weapon("Champions Sword","Swoosh!",99.99,false,5);
weaponArray[2] = Weapon("Dagger","Ding!",12.25,false,1);
weaponArray[3] = Weapon("Poisin Dagger","Shh",18.50,false,1);
weaponArray[4] = Weapon("Sturdy Dagger","Gronk!",14.75,false,3);
weaponArray[5] = Weapon("Short Bow","T'wang!",35.75,false,3);
weaponArray[6] = Weapon("Champions Bow","Swoop!",90.15,false,5);
weaponArray[7] = Weapon("Champions Axe","Bash!",110.11,false,6);
weaponArray[8] = Weapon("Throwing Axe","Bonk!",25.75,false,2);
void getStore();
system("pause");
return 0;
}

void getStore();
This is a function stub. It declares a function getStore that takes no arguments and returns nothing to be implemented later. This is almost definitely a typo.
Further, because void getStore(Weapon* weaponArray) is in the Weapon class, you have to call it on a weapon, which doesn't look right. You probably mean to do this:
class Weapon {
// ...
};
void getStore(Weapon* weaponArray, unsigned sz)
{
std::cout << "Name" << "\t" << "Sound" << "\t" << "Price" << "\t" << "Owned";
for (unsigned i = 0; i < sz; i++)
{
weaponArray[i].getInventory();
}
}
int main()
{
Weapon weaponArray[9]{};
weaponArray[0] = Weapon("Broad Sword","Clang!",50,false,3);
//...
getStore(weaponArray, 9);
}

Related

C++ linker undefined reference to function cannot find my error

It is a homework problem. It compiles fine, but linker gives undefined reference to my function getSalesData - line 20 just after my first for loop. Here is the code. I cannot find where I have done anything incorrectly; I have my prototype defined and it matches my function header, and I am simply calling the function.
// chips and salsa
#include <iostream>
#include <iomanip>
#include <string>
int getJarsSold(std::string type);
void getSalesData(int jarsSold[],int size,int &totalJars,int &highSeller,int &lowSeller);
int main() {
const int SIZE = 5;
const std::string salsaTypes[] {"Mild","Medium","Sweet","Hot","Zesty"};
int jarsSold[SIZE] = {};
int highIndex,lowIndex,totalJarsSold;
for (int i = 0; i < SIZE; i++) {
jarsSold[i] = getJarsSold(salsaTypes[i]);
}
getSalesData(jarsSold,SIZE,totalJarsSold,highIndex,lowIndex);
std::cout << " Type Jars Sold\n";
std::cout << "---------------------\n";
for (int i = 0; i < SIZE; i++) {
std::cout << std::setw(8) << salsaTypes[i] << std::setw(15) << jarsSold[i] << std::endl;
}
std::cout << "*********************\n";
std::cout << "Total Sales = " << totalJarsSold << std::endl;
std::cout << "Highest Seller = " << salsaTypes[highIndex] << std::endl;
std::cout << "Lowest Seller = " << salsaTypes[lowIndex] << std::endl;
}
int getJarsSold(std::string type) {
bool validData = false;
int numJars;
while (!validData) {
std::cout << "Enter jars sold this month for " << type << " salsa type: ";
std::cin >> numJars;
if (numJars < 0) {
std::cout << "Number of jars sold must be 0 or positive number.\n";
}
else {
validData = true;
}
}
validData = false;
return numJars;
}
void getSalesData(int jarsSold[],int size,int totalJars,int highIndex,int lowIndex) {
bool firstRun = true;
int highVal,lowVal;
totalJars = 0;
for (int i = 0; i < size; i++) {
if (firstRun) {
highIndex = i;
highVal = jarsSold[highIndex];
lowIndex = i;
lowVal = jarsSold[lowIndex];
totalJars += jarsSold[i];
firstRun = false;
}
else {
totalJars += jarsSold[i];
if (jarsSold[i] > highVal) {
highVal = jarsSold[i];
highIndex = i;
}
if (jarsSold[i] < lowVal) {
lowVal = jarsSold[i];
lowIndex = i;
}
}
}
}
Any help is appreciated. I am just using -c for compiling and -o for linking, nothing fancy as I know no better.

C++ Using array and for loop to output from multiple classes

I am asked to do this code and i need to use array or something similar to print out different classes. The only way i know is individually doing every single class is there a faster way of doing this. Following is the way i am using at the moment.
Ground_Transport Gobj;
Air_Transport Aobj;
Sea_Transport Sobj;
Car Cobj;
Train Tobj;
Bus Bobj;
Gobj.estimate_time();
Gobj.estimate_cost();
cout << Gobj.getName() << endl;
Bobj.estimate_time();
Bobj.estimate_cost();
cout << Bobj.getName() << endl;
Sobj.estimate_time();
Sobj.estimate_cost();
cout<<Sobj.getName()<<endl;
Aobj.estimate_time();
Aobj.estimate_cost();
cout << Aobj.getName() << endl;
Cobj.estimate_time();
Cobj.estimate_cost();
cout << Cobj.getName() << endl;
Tobj.estimate_time();
Tobj.estimate_cost();
cout << Tobj.getName() << endl;
Transport_KL_Penang Kobj;
cout << Kobj.getName() << endl;
This is the header file Transport_KL_Penang
#include <iostream>
#include <string>
using namespace std;
class Transport_KL_Penang
{
public:
Transport_KL_Penang() {}
virtual string getName() {
return Name;
}
int Time_in_hours1 ;
int Time_in_hours2 ;
int Cost_in_RM1 ;
int Cost_in_RM2 ;
void estimate_time() ;
void estimate_cost() ;
private:
static string Name;
};
void Transport_KL_Penang::estimate_time()
{
cout << "It takes " << Time_in_hours1 << "-" << Time_in_hours2 <<
" hours if you use " << Name << endl;
}
void Transport_KL_Penang::estimate_cost()
{
cout << "It will cost around " << Cost_in_RM1 << "-" << Cost_in_RM2 <<
"RM if you use " << Name << endl;
}
If you don't need a specific object name, you can write something as a code below, creating a multiples generics objects:
#include <iostream>
#include <cstdlib>
#include <time.h>
class Myclass {
private:
int randTime;
float cost;
public:
void estimate_time(){
randTime = rand()%100;
}
void estimate_cost(){
cost = randTime * 0.2;
}
float getEstimateCost(){
return cost;
}
};
int main(){
srand(time(NULL));
int numberOfObjects = 7;
Myclass obj[numberOfObjects];
//input
for(int i = 0; i < numberOfObjects; i++){
obj[i].estimate_time();
obj[i].estimate_cost();
}
// printing
for(int i = 0; i < numberOfObjects; i++){
std::cout << obj[i].getEstimateCost() << std::endl;
}
return 0;
}

delete array pointers heap corruption

I get an exception on this line in Visual Studio 2015. It builds with no errors.
_free_dbg(block, _UNKNOWN_BLOCK);
This is how I declare the new array of pointers:
CAirship * pAirShip[10];
This is how I delete the array of pAirShip pointers:
for (int i = 0; i < 10; i++) {
if (pAirShip[i]) {
cout << "pAirShip[" << i << "] is " << pAirShip[i] << endl;
delete pAirShip[i];// Delete appropriate object
}
} // end for loop
I get an error on attempting to delete pAirShip[0],
Here is a debug window that does print the pointer addresses:
Here is the full code:
struct AirShipFile {
int Type; // Airplane or Balloon
string name; // Name of the airship
int passCount; // passenger count
int weightCargo; // cargo weight
int EngOrGas; // engine or gas type
int distance; // range or altitude
};
enum EngineType { Jet, Propeller }; // for airplanes only
std::ostream& operator<<(std::ostream& out, const EngineType value) {
static std::map<EngineType, std::string> strings;
if (strings.size() == 0) {
#define INSERT_ELEMENT(p) strings[p] = #p
INSERT_ELEMENT(Jet);
INSERT_ELEMENT(Propeller);
#undef INSERT_ELEMENT
}
return out << strings[value];
}
enum GasType {Helium, Hydrogen }; // for proprellers only
std::ostream& operator<<(std::ostream& out, const GasType value) {
static std::map<GasType, std::string> strings;
if (strings.size() == 0) {
#define INSERT_ELEMENT(p) strings[p] = #p
INSERT_ELEMENT(Helium);
INSERT_ELEMENT(Hydrogen);
#undef INSERT_ELEMENT
}
return out << strings[value];
}
enum AirShipType { AIRPLANE, BALLOON };
class CAirship {
public:
CAirship() { }
virtual void SetData(AirShipFile &data) = 0;
virtual void GetData() = 0;
AirShipType GetAirShipType() { return m_AirShipType; }
protected:
AirShipType m_AirShipType;
};
class CAIRPLANE : public virtual CAirship {
public:
CAIRPLANE() : CAirship() {}
void SetData(AirShipFile &data);
void GetData();
private:
EngineType m_EngineType;
int m_MaxPassengerCount;
string m_Name;
int m_MaxCargoWeight;
int m_MaxAltitude;
};
// Function: SetData
void CAIRPLANE::SetData(AirShipFile &data)
{
// cast integer to enum
m_EngineType = EngineType(data.EngOrGas);
// airplane name
m_Name = data.name;
// passenger count
m_MaxPassengerCount = data.passCount;
//max cargo weight
m_MaxCargoWeight = data.weightCargo;
// cast integer to enum
m_AirShipType = AirShipType(data.Type);
// maximum altitude
m_MaxAltitude = data.distance;
}
void CAIRPLANE::GetData()
{
cout << setw(20) << m_Name << "\t" << setw(20) << m_EngineType << setw(20);
cout << left << setw(20) << m_MaxAltitude << "\n";
}
class CBALLOON : public virtual CAirship {
public:
CBALLOON() : CAirship() {}
void SetData(AirShipFile &data);
void GetData();
private:
GasType m_GasType;
EngineType m_EngineType;
int m_MaxPassengerCount;
string m_Name ;
int m_MaxCargoWeight;
int m_MaxAltitude;
};
void CBALLOON::SetData(AirShipFile &data)
{
// cast integer to enum
m_GasType = GasType(data.EngOrGas);
// airplane name
m_Name = data.name;
// passenger count
m_MaxPassengerCount = data.passCount;
//max cargo weight
m_MaxCargoWeight = data.weightCargo;
// cast integer to enum
m_AirShipType = AirShipType(data.Type);
// maximum altitude
m_MaxAltitude = data.distance;
}
void CBALLOON::GetData()
{
cout << setw(20) << m_Name << "\t" << setw(20)<< m_GasType << setw(20);
cout << left << setw(20) << m_MaxAltitude << "\n";
}
// AIRPLANE = 0
// BALLOON = 1
int main(int argc, char *argv[])
{
if (argc != 2) {
cout << "Usage: PR <filename>\n";
return 1;
}
ifstream Infile(argv[1]);
if (!Infile) {
cout << "Cannot open file\n";
return 1;
}
char LineBuf[100];
char d[] = ",";
CAirship * pAirShip[10];
int i = 0;
while (Infile.getline(LineBuf, 100)) {
struct AirShipFile data;
// read the first field Airship type
// airplane or balloon
data.Type = atoi(strtok(LineBuf, d));
switch (data.Type) {
case AIRPLANE:
// Create AIRPLANE Object
pAirShip[i] = new CAIRPLANE();
data.name = strtok(NULL, d);
data.passCount = atoi(strtok(NULL, d));
data.weightCargo = atoi(strtok(NULL, d));
data.EngOrGas = atoi(strtok(NULL, d));
data.distance = atoi(strtok(NULL, d));
break;
case BALLOON:
// Create BALLOON Object
pAirShip[i] = new CBALLOON();
data.name = strtok(NULL, d);
data.passCount = atoi(strtok(NULL, d));
data.weightCargo = atoi(strtok(NULL, d));
data.EngOrGas = atoi(strtok(NULL, d));
data.distance = atoi(strtok(NULL, d));
break;
default:
break;
} // end switch
// call appropriate function
pAirShip[i++]->SetData(data);
memset(LineBuf, '\0', 100);
}
Infile.close();
cout << "Listing of all Airplanes \n";
cout << left << setw(20) << "\nName" << left<< setw(20)<<"\tEngine Type";
cout << left<<setw(20)<<"\Maximum Range" << "\n\n";
for (int i = 0; i < 10; i++) {
if (pAirShip[i]->GetAirShipType() == AIRPLANE)
pAirShip[i]->GetData();
}
cout << "\n\nListing of all Balloons \n";
cout <<left << setw(20) << "\nName" << left << setw(20) << "\tGas Type" ;
cout << left << setw(20) << "\Maximum Altitude" << "\n\n";
for (int i = 0; i < 10; i++) {
if (pAirShip[i]->GetAirShipType() == BALLOON)
pAirShip[i]->GetData();
}
for (int i = 0; i < 10; i++) {
if (pAirShip[i]) {
delete pAirShip[i];// Delete appropriate object
}
} // end for loop
return 0;
}
The problem is that when allocating an array of any kind, C++ does not initialize the elements, but leaves them with "random" values. So, when you create an array of pointers, the pointers are not created with NULL, nullptr or 0 value, so this is not a good indicator if they are really unused on its own. Trying to free the space that isn't allocated is what generates the error. You should first initialize them (by yourself in a for loop) with nullptr right after you create the array, then you can use your code for deleting the array of pointers.

Using classes and constructors and create a object name with an array size of 3

I am trying to create an object in the main with an array of three. When i run it, it displays the desired output, but it gives an error and any code after that doesn't run. "Unhandled exception at 0x775FC41F in Grocery.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0036E590."
class GroceryItem {
public:
GroceryItem();//default constructor
GroceryItem(string, double, int, int); // four argument constructor
void set_item_name(string); // Assigns a value to the data memeber item_name
void set_item_price(double); //Assigns a value to the data member item_price
void set_qty_on_hand(int);// Assigns a value to the data member quantity_on_hand.
void set_qty_purchased(int); // Sets qty_purchased to zero before a customer begins shopping.
string get_item_name(); // Returns the value of the data memebr item_name.
double get_item_price(); // Returns the value of the data member item_price
int get_qty_on_hand(); // Returns the value of the data member quantity_on_hand.
int get_qty_purchased(); // Retruns the value of the data memebr qty_purchased.
private:
string item_name;
double item_price;
int quantity_on_hand;
int quantity_purchased;
};
GroceryItem::GroceryItem(string name, double price, int hand, int purchased){
set_item_name(name);
set_item_price(price);
set_qty_on_hand(hand);
set_qty_purchased(purchased);
}
void GroceryItem::set_item_name(string name){
item_name = name;
}
string GroceryItem::get_item_name(){
return item_name;
}
void GroceryItem::set_item_price(double price){
item_price = price;
}
double GroceryItem::get_item_price(){
return item_price;
}
void GroceryItem::set_qty_on_hand(int hand){
quantity_on_hand = hand;
}
int GroceryItem::get_qty_on_hand(){
return quantity_on_hand;
}
void GroceryItem::set_qty_purchased(int purchased){
if (purchased > 0)
quantity_purchased = purchased;
if (purchased <= 0)
{
quantity_purchased = 0;
cout <<"\n cart cannot be negative, it will be set to 0. \n";
}
}
int GroceryItem::get_qty_purchased(){
return quantity_purchased;
}
int main(){
int input;
cout <<"Welcome to KMART\n" << "\nHappy Shopping" << endl;
GroceryItem Kmart("Hello", 1234, 1234, 1);
GroceryItem Kmart2("My", 1234, 1234, 1);
GroceryItem Kmart3[SIZE] = {
{ "John", 1234, 1234, 0 },
{ "Mary", 1234, 1234, 0 },
{ "Kevin", 1234, 1234, 0 }
};
//Kmart("jjj", 12, 123, 1);
for (int i = 0; i < 10; i++){
cout << Kmart3[i].get_item_name() << "\t" << Kmart3[i].get_item_price() << "\t" << Kmart3[i].get_qty_on_hand() << "\t" << Kmart3[i].get_qty_purchased() << endl;
}
cout << "This is fromt eh four argument constructor" << endl;
cout<<Kmart.get_item_name()<<"\t"<<Kmart.get_item_price()<<"\t"<<Kmart.get_qty_on_hand()<<"\t"<<Kmart.get_qty_purchased()<<endl;
cout << Kmart2.get_item_name() << "\t" << Kmart2.get_item_price() << "\t" << Kmart2.get_qty_on_hand() << "\t" << Kmart2.get_qty_purchased() << endl;
}
You have not shared with us the value for SIZE; however, I'm guessing that you probably have it less than 10. If that were the case, then it would crash later when you're looping through Kmart3.
Making this change should stop the crashing (at least it does in my testing):
for (int i = 0; i < SIZE; i++)
{
if (Kmart3[i].get_item_name().length() > 0)
cout << Kmart3[i].get_item_name().c_str() << "\t" << Kmart3[i].get_item_price() << "\t" << Kmart3[i].get_qty_on_hand() << "\t" << Kmart3[i].get_qty_purchased() << endl;
}
Of course, there are a few other issues you'll need to address before the code works as I think you mean for it to work; however, that should stop the crashing.

c++ Sharing list between main an exterior function

I am making a rabbit population simulator for a challenge I am doing. I have a map of class objects. I also have a list which contains the keys for the map. Each round of the simulator I want to add more objects to the class, and update my map and list. To do this I wrote a separate "creation" function which will randomly generate new class objects and add them to a map and add the keys to a list.
The problem is when I call the creation function, then iterate through the map using the list it shows the map or list is empty (not sure which). If I iterate through the map before leaving the function it only shows the newest objects. If I move the code for the function into the main function, it works correctly (calling it twice gives me the new objects created in the first iteration of the code, and also the objects created by the second iteration).
I am guessing that a new list or map is being created each time the function is called and is overwriting the old list or map. How can I get the list and map to pass between the main function and the creation function?
Here is my code:
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include <string>
#include <sstream>
#include <array>
#include <time.h>
#include <conio.h>
#include <map>
#include <list>
class Bunny
{
public:
char fname;
int sex, age, color, status;
Bunny(int, int, int, int);
Bunny();
int s() { return (sex); }
int a() { return (age); }
int c() { return(color);}
int st() { return (status);}
int aging(int age) { return (age + 1); }
};
Bunny::Bunny(int s, int a, int c, int st)
{
sex = s;
age = a;
color = c;
status = st;
}
Bunny::Bunny(){}
void creation(std::map<std::string, Bunny> bunnies, std::list<std::string>names, int births);
std::string firstname(int s, int num)
{
std::string name;
if (s == 0)
{
switch (num)
{
case (0) :
name = "Tim";
break;
case (1) :
name = "Tom";
break;
case (2) :
name = "Mark";
break;
case (3) :
name = "Bob";
break;
case (4) :
name = "Rob";
break;
}
}
if (s == 1)
{
switch (num)
{
case (0) :
name = "Suzy";
break;
case (1) :
name = "Linda";
break;
case (2) :
name = "Mary";
break;
case (3) :
name = "Jan";
break;
case (4) :
name = "Julie";
break;
}
}
return (name);
}
void main()
{
int num = rand() % 5;
int n, births = 10;
std::list<std::string>names;
std::map<std::string, Bunny> bunnies;
srand(time(0));
creation(bunnies, names, births);
std::cout << "Number" << "\t" << "Name" << "\t" << "age" << "\t" << "Sex" << "\t" << "Color" << "\t" << "Vampire?" "\n";
n = 0;
for (std::list<std::string>::iterator it = names.begin(); it != names.end(); it++)
{
n++;
std::cout << n << "\t";
std::cout << " " << *it;
std::cout << "\t" << bunnies[*it].a() << "\t" << bunnies[*it].s() << "\t" << bunnies[*it].c() << "\t" << bunnies[*it].st() << "\n";
}
creation(bunnies, names, births);
_getch();
}
/*void year()
{
for (std::list<std::string>::iterator it = names.begin(); it != names.end(); it++)
{
bunnies[*it].aging(bunnies[*it].a())
}
}*/
void creation(std::map<std::string, Bunny> bunnies,std::list<std::string> names,int births)
{
int n;
for (n = 0; n < births; n++)
{
int num = std::rand() % 5;
char id = (std::rand() % 100) + 20;
int s = std::rand() % 2;
std::string f = firstname(s, num) + '_' + id;
int a = 0;
int c = std::rand() % 5;
int st;
if (rand() % 50 == 43) st = 1; else st = 0;
bunnies[f] = Bunny(s, a, c, st);
names.push_front(f);
//std::cout << f << " " << bunnies[f].a() << " " << bunnies[f].c() << "\n";
}
std::cout << "Number" << "\t" << "Name" << "\t" << "age" << "\t" << "Sex" << "\t" << "Color" << "\t" << "Vampire?" "\n";
n = 0;
for (std::list<std::string>::iterator it = names.begin(); it != names.end(); it++)
{
n++;
std::cout << n << "\t";
std::cout << *it;
std::cout << "\t" << bunnies[*it].a() << "\t" << bunnies[*it].s() << "\t" << bunnies[*it].c() << "\t" << bunnies[*it].st() << "\n";
}
}
Your problem is that your main function is passing your map and list by value instead of passing by reference. This means that your creation function is receiving a copy of the existing map/list, rather than a reference to the original one you created. Since it is then only making edits to that copy, any changes it makes will not be reflected in the main function.
Change your creation function from:
void creation(std::map<std::string, Bunny> bunnies, std::list<std::string>names, int births)
to
void creation(std::map<std::string, Bunny>& bunnies, std::list<std::string>& names, int births)