C++ class vector issues - c++

Ok, I'm working on this inventory program, in which what is supposed to happen is the user inputs various bits of information about a particular product, then it gets passed to the inventory, while giving the user the opportunity to change stuff (as you should see in the code). Since I'm doing this for a school project, I have to have the various classes that are there (hence why I haven't gotten rid of them.
Now my issue is with the vectors in class Inventory.
Error 'std::vector> AddProduceToInventory(std::vector<_Ty,std::allocator<_Ty>>)': cannot convert argument 1 from 'std::vector>' to 'std::vector>'
This issue applies to each of those vectors in the class. I only copied one of the identical errors.
I can't figure out what else I'm supposed to do. Here is my code (sorry for the length!)
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
class Item {
public:
void SetPrice(int prcInDllrs) {
priceInDollars = prcInDllrs; // Somehow I need to keep adding each of these totals to make a grand total price.
}
void SetItemPrice(int whatever) {
itemsPrice = whatever;
}
void SetName(string nm)
{
name = nm;
};
void SetQuantity(int qnty)
{
quantity = qnty;
};
virtual void Print() //Here is my print problem
{
};
virtual ~Item()
{
return;
};
protected:
string name;
int quantity = 0;
int priceInDollars = 0;
int itemsPrice = 0;
};
class Produce : public Item { // Derived from Item class
public:
void SetExpiration(string expir)
{
expiration = expir;
};
void Print()
{
cout << name << " x" << quantity
<< " (Expires: " << expiration << ")" << " for $" << itemsPrice //FILL THIS IN!!!
<< endl;
};
private:
string expiration;
};
class Book : public Item {
public:
void SetAuthor(string athr) {
author = athr;
}
void Print()
{
cout << name << " x" << quantity
<< " for $" << itemsPrice << " (Author: " << author << ")" << endl;
}
private:
string author;
};
class Inventory {
public:
void PrintInventory()
{
if (inventory.size() == 0) {
cout << "No items to print." << endl;
}
else {
for (unsigned int i = 0; i < inventory.size(); ++i) {
cout << i << " - ";
inventory.at(i)->Print();
}
}
cout << "Total inventory value: $" << totalInvPriceInDollars << endl;
}
//I am leaving these out of the equation until I get the PrintInventory working
void AddItemToInventory()
{
vector<Inventory*> AddProduceToInventory(vector<Inventory*> Invntry);
AddProduceToInventory(vector<Inventory*> inventory)
{
Produce* prdc;
string usrInptName = "";
string usrInptQntyStr = "";
istringstream inSS;
int usrInptQnty = 0;
string usrInptExpr = "";
string usrInptPrcStr = "";
int usrInptPrc = 0;
int itemsTotalPrice = 0;
istringstream inDD;
string runningTotal = "";
int sum = 0;
cout << "Enter name of new produce: ";
getline(cin, usrInptName);
cout << "Enter quantity: ";
getline(cin, usrInptQntyStr);
inSS.str(usrInptQntyStr);
inSS >> usrInptQnty;
inSS.clear();
cout << "Enter expiration date: ";
getline(cin, usrInptExpr);
cout << "Enter the price per item: $";
getline(cin, usrInptPrcStr);
inDD.str(usrInptPrcStr);
inDD >> usrInptPrc;
inDD.clear();
itemsTotalPrice = usrInptPrc * usrInptQnty;
prdc = new Produce;
prdc->SetName(usrInptName);
prdc->SetQuantity(usrInptQnty);
prdc->SetExpiration(usrInptExpr);
prdc->SetPrice(usrInptPrc);
prdc->SetItemPrice(usrInptPrc);
inventory.push_back(prdc);
Inventory set;
set.SetInventory(inventory);
return inventory;
}
}
void AddBookToInventory()
{
vector<Inventory*> AddBookToInventory(vector<Inventory*> inventory) {
Book* prdct;
string usrInptName = "";
string usrInptQntyStr = "";
istringstream inSS;
int usrInptQnty = 0;
string usrInptAthr = "";
string usrInptPrcStr = "";
int usrInptPrc = 0;
int itemsTotalPrice = 0;
istringstream inDD;
string runningTotal = "";
int sum = 0;
cout << "Enter name of new book: ";
getline(cin, usrInptName);
cout << "Enter quantity: ";
getline(cin, usrInptQntyStr);
inSS.str(usrInptQntyStr);
inSS >> usrInptQnty;
inSS.clear();
cout << "Enter author: ";
getline(cin, usrInptAthr);
cout << "Enter the price per item: $";
getline(cin, usrInptPrcStr);
inDD.str(usrInptPrcStr);
inDD >> usrInptPrc;
inDD.clear();
prdct = new Book;
prdct->SetName(usrInptName);
prdct->SetQuantity(usrInptQnty);
prdct->SetPrice(usrInptPrc);
prdct->SetAuthor(usrInptAthr);
prdct->SetItemPrice(usrInptPrc);
inventory.push_back(prdct);
Inventory set;
set.SetInventory(inventory);
return inventory;
}
}
void UpdateItemQtyInventory()
{
//This is the update function in which we can change how many items a certain purchase has
vector<Item*> UpdateItemQtyInInventory(vector<Item*> inventory) {
string usrIndexChoiceStr = "";
unsigned int usrIndexChoice = 0;
istringstream inSS;
string usrInpuQntyStr = "";
int usrInptQnty = 0;
if (inventory.size() == 0) {
cout << "No items to update." << endl;
}
else {
PrintInventory(inventory);
do {
cout << "Update which item #: ";
getline(cin, usrIndexChoiceStr);
inSS.str(usrIndexChoiceStr);
inSS >> usrIndexChoice;
inSS.clear();
} while (!(usrIndexChoice < inventory.size()));
cout << "Enter new quantity: ";
std::getline(cin, usrInptQntyStr);
inSS.str(usrInptQntyStr);
inSS >> usrInptQnty;
inSS.clear();
inventory.at(usrIndexChoice)->SetQuantity(usrInptQnty);
}
return inventory;
}
}
void RemoveItemFromInventory()
{
//Here we will be removing an entire item from the inventory
vector<Item*> RemoveItemFromInventory(vector<Item*> inventory) {
istringstream inSS;
string usrIndexChoiceStr = "";
unsigned int usrIndexChoice = 0;
string usrInptQntyStr = "";
if (inventory.size() == 0) {
cout << "No items to remove." << endl;
}
else {
PrintInventory(inventory);
do {
cout << "Remove which item #: ";
getline(cin, usrIndexChoiceStr);
inSS.str(usrIndexChoiceStr);
inSS >> usrIndexChoice;
inSS.clear();
} while (!(usrIndexChoice < inventory.size()));
inventory.erase(inventory.begin() + usrIndexChoice);
}
return inventory;
}
}
void GetTotalValueAsPrice()
{
}
void SetInventory(vector<Item*> invntry) {
inventory = invntry;
}
private:
int totalInvPriceInDollars = 0;
vector<Inventory*> inventory;
};
// Print all items in the inventory
void PrintInventory(vector<Item*> inventory);
// Dialogue to create a new item, then add that item to the inventory
vector<Item*> AddItemToInventory(vector<Item*> inventory);
// Dialogue to create a new book, then add that book to the inventory
vector<Item*> AddBookToInventory(vector<Item*> inventory);
// Dialogue to update the quantity of an item, then update that item in the inventory
vector<Item*> UpdateItemQtyInInventory(vector<Item*> inventory);
// Dialogue to remove a specific item, then remove that specific item from the inventory
vector<Item*> RemoveItemFromInventory(vector<Item*> inventory);
int main() {
vector<Inventory*> inventory1;
string usrInptOptn = "default";
string usrInptOptn2 = "default";
Inventory update;
update.UpdateItemQtyInventory();
while (true) {
// Get user choice
cout << "\nEnter (p)rint, (a)dd, (u)pdate, (r)emove, or (q)uit: ";
getline(cin, usrInptOptn);
// Process user choice
if (usrInptOptn.size() == 0) {
continue;
}
else if (usrInptOptn.at(0) == 'p') {
Inventory printer;
printer.PrintInventory();
update.SetInventory(inventory1);
}
else if (usrInptOptn.at(0) == 'a') {
cout << "\nEnter (b)ook or (p)roduce: ";
getline(cin, usrInptOptn2);
if (usrInptOptn2.at(0) == 'b') {
inventory1 = AddBookToInventory(inventory1);
inventoryUpdate.SetInventory(inventory1);
}
else if (usrInptOptn2.at(0) == 'p') {
inventory1 = AddItemToInventory(inventory1);
inventoryUpdate.SetInventory(inventory1);
}
else
{
continue;
}
}
else if (usrInptOptn.at(0) == 'u') {
inventory1 = UpdateItemQtyInInventory(inventory1);
}
else if (usrInptOptn.at(0) == 'r') {
inventory1 = RemoveItemFromInventory(inventory1);
}
else if (usrInptOptn.at(0) == 'q') {
cout << "\nGood bye." << endl;
break;
}
}
return 0;
}
I'm also getting additional errors, but I think they are coming from this main issue. What do I do to fix this?
Thanks!
Also, I'm using Visual Studio, but have checked with Code::Blocks to make sure it isn't a weird compiler issue.

Most of your functions look somehow similar to this:
void foo() {
std::vector<T> foo(std::vector<T> bar){
/*...*/
}
}
It looks like you try to declare a function inside the function (with the same name but different parameters and return type and sometimes with missing return type). Just dont do that, but just this:
std::vector<T> foo(std::vector<T> bar){
/*...*/
}

Related

MultiMap not Printing List

I am having 2 issues with my code.
The 1st issue is that my multimap is not printing, and I don't know why.
The 2nd issue is that I don't know how to create a function to search and find a specific item in my multimap.
You can change as much of the code as you want, but I need to keep the class or change it to a struct.
#include<iostream>
#include<string>
#include<iterator>
#include<map>
#include<algorithm>
#include<iomanip>
using namespace std;
class SongNode {
public:
string title;
string artist;
float rating;
};
//Constants
#define INFINITE_LOOP 1
#define LEFT_JUSTIFIED 30
//Prototypes
void sortByArtist(multimap<string, SongNode>& newSongNode);
void sortByRating(multimap<string, SongNode>& newSongNode);
//FUNCTION : void sortByArtist
//PARAMETER : multimap<string, SongNode>&newSongNode
//RETURN : void
//DESCRIPTION : This function will sort the multimap by the artist of the song
void sortByArtist(multimap<string, SongNode>&newSongNode) {
multimap<string, SongNode>temp;
for (auto i = newSongNode.begin(); i != newSongNode.end(); i++)
temp.insert(pair<string, SongNode>(i->second.artist, i->second));
newSongNode.clear();
for (auto i = temp.begin(); i != temp.end(); i++)
newSongNode.insert(pair<string, SongNode>(i->second.artist, i->second));
temp.clear();
}
//FUNCTION : void sortByRating
//PARAMETER : (multimap<string, SongNode>& newSongNode
//RETURN : void
//DESCRIPTION : This function will sort the multimap by the rating.
void sortByRating(multimap<string, SongNode>& newSongNode) {
multimap<float, SongNode, greater<int>> temp;
for (auto i = newSongNode.begin(); i != newSongNode.end(); i++)
temp.insert(pair<int, SongNode>(i->second.rating, i->second));
newSongNode.clear();
for (auto i = temp.begin(); i != temp.end(); i++)
newSongNode.insert(pair<string, SongNode>(" ", i->second));
temp.clear();
}
int main() {
multimap<string, SongNode> songList;
multimap<string, SongNode>::iterator itr;
string title;
string artist;
int rating;
SongNode* newSongNode = new SongNode;
cout << "Please enter a title artist and rating\n";
while (INFINITE_LOOP) {
cout << "Title: ";
cin >> title;
if (title == ".") {
break;
}
cout << "Artist: ";
cin >> artist;
cout << "Rating: ";
cin >> rating;
//Error check for rating
while (INFINITE_LOOP) {
if (rating < 1) {
cout << "The rating you have entered is less then 1\n";
cout << "Rating: ";
cin >> rating;
break;
}
else if (rating > 5) {
cout << "The rating you have to enterd is greater then 5\n";
cout << "Rating: ";
cin >> rating;
break;
}
else
break;
}
SongNode* newNode = new SongNode;
newNode->title = title;
newNode->artist = artist;
newNode->rating = rating;
songList.insert(pair<string, SongNode>(title, *newSongNode));
}
//display the two lists here.
cout << "Artist Sorted List\n";
sortByArtist(songList);
for (itr = songList.begin(); itr != songList.end(); ++itr) {
cout << "Title" << left << setw(LEFT_JUSTIFIED) << itr->second.title;
cout << "Artist" << left << setw(LEFT_JUSTIFIED) << itr->second.artist;
cout << "Rating" << left << setw(LEFT_JUSTIFIED) << itr->second.rating<<endl;
}
cout << "\n";
cout << "Rating Sorted List\n";
sortByRating(songList);
delete newSongNode;
return 0;
}
First of all, you have two variables with similar names, and you definitely misuse them:
SongNode* newSongNode = new SongNode;
// ...
SongNode* newNode = new SongNode;
newNode->title = title;
newNode->artist = artist;
newNode->rating = rating;
songList.insert(pair<string, SongNode>(title, *newSongNode));
You are initializing the newNode but inserting the newSongNode. The values are initialized with empty strings, so that may explain no printing.
As for "searching in a multimap" be more specific in what your problem is.
You are not populating the songList with the SongNode objects that you fill with data. You have an extra SongNode that has no data in it, which is the only object you are putting into the songList. So there is nothing to print.
Try this instead:
#include <iostream>
#include <string>
#include <iterator>
#include <map>
#include <algorithm>
#include <iomanip>
#include <limits>
using namespace std;
struct SongNode {
string title;
string artist;
float rating;
};
//Constants
#define INFINITE_LOOP 1
#define LEFT_JUSTIFIED 30
//Prototypes
void sortByArtist(multimap<string, SongNode>& newSongNode);
void sortByRating(multimap<string, SongNode>& newSongNode);
//FUNCTION : void sortByArtist
//PARAMETER : multimap<string, SongNode>&newSongNode
//RETURN : void
//DESCRIPTION : This function will sort the multimap by the artist of the song
void sortByArtist(multimap<string, SongNode> &newSongNode) {
multimap<string, SongNode> temp;
for (auto &elem : newSongNode)
temp.insert(make_pair(elem.second.artist, elem.second));
newSongNode.clear();
for (auto &elem : temp)
newSongNode.insert(make_pair(elem.second.artist, elem.second));
}
//FUNCTION : void sortByRating
//PARAMETER : (multimap<string, SongNode>& newSongNode
//RETURN : void
//DESCRIPTION : This function will sort the multimap by the rating.
void sortByRating(multimap<string, SongNode>& newSongNode) {
multimap<float, SongNode, greater<int>> temp;
for (auto &elem : newSongNode)
temp.insert(make_pair(elem.second.rating, elem.second));
newSongNode.clear();
for (auto &elem : temp)
newSongNode.insert(make_pair(" ", elem.second));
}
int main() {
multimap<string, SongNode> songList;
string title, artist;
float rating;
cout << "Please enter a title artist and rating\n";
while (INFINITE_LOOP) {
cout << "Title: ";
cin >> title;
if (title == ".") {
break;
}
cout << "Artist: ";
cin >> artist;
cout << "Rating: ";
cin >> rating;
//Error check for rating
while (INFINITE_LOOP) {
if (!cin) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "The rating you have entered is invalid\n";
}
else if (rating < 1.0f) {
cout << "The rating you have entered is less then 1\n";
}
else if (rating > 5.0f) {
cout << "The rating you have to entered is greater then 5\n";
}
else
break;
cout << "Rating: ";
cin >> rating;
}
SongNode newNode;
newNode.title = title;
newNode.artist = artist;
newNode.rating = rating;
songList.insert(make_pair(title, newNode));
}
//display the two lists here.
cout << "Artist Sorted List\n";
sortByArtist(songList);
for (auto &elem : songList) {
cout << "Title" << left << setw(LEFT_JUSTIFIED) << elem.second.title;
cout << "Artist" << left << setw(LEFT_JUSTIFIED) << elem.second.artist;
cout << "Rating" << left << setw(LEFT_JUSTIFIED) << elem.second.rating << endl;
}
cout << "\n";
cout << "Rating Sorted List\n";
sortByRating(songList);
for (auto &elem : songList) {
cout << "Title" << left << setw(LEFT_JUSTIFIED) << elem.second.title;
cout << "Artist" << left << setw(LEFT_JUSTIFIED) << elem.second.artist;
cout << "Rating" << left << setw(LEFT_JUSTIFIED) << elem.second.rating << endl;
}
cout << "\n";
return 0;
}

vector pointers and retrieving data

I'm a beginner at coding in C++ and every other language. The problem I'm having here is in main() with the first (else if) where (UserInput == sell). I would like the function to print the data stored in the object #listPos to retrieve the cost and input it into my incomplete Profit() function, but every time I dereference the pointer (Search) I get an error code. There's something I'm missing big time please help!!
Ive already tried (*search) but there's a huge error code.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class UnSold{
public:
UnSold(string NameOfShoe, int PurchasePrice ){
name = NameOfShoe;
cost = PurchasePrice;
return;
}
void SetName(string NameOfShoe){
name = NameOfShoe;
return;
}
void SetCost(int PurchasePrice){
cost = PurchasePrice;
return;
}
string GetName() const {
return name;
}
int GetCost() const{
return cost;
}
void Profit();
void PrintItem();
private:
string name;
int cost;
};
void UnSold::Profit(){
static int profit = 0;
//profit += (sold-cost);
}
void UnSold::PrintItem(){
cout << "Name: " << this->name << " Cost: " << this->cost << endl;
}
void PrintEverything(vector<UnSold*> AllItems) {
unsigned int i;
for (i=0; i<AllItems.size(); ++i) {
cout<< i+1 << " ";
(*AllItems.at(i)).PrintItem();
}
}
int main(){
vector<UnSold*> Inventory;
string Name;
int Cost;
string UserInput;
unsigned int listPos;
UnSold* newItem = nullptr;
UnSold* search = nullptr;
while ( UserInput != "quit") {
cout << "Do you want to add, sell, print or quit?" <<endl;
cin >> UserInput;
if ( UserInput == "add") {
cout << "Enter item name: "<<endl;
cin >> Name;
cout << "Enter item cost: " << endl;
cin >> Cost;
newItem = new UnSold(Name, Cost);
Inventory.push_back(newItem);
}
else if ( UserInput == "sell") {
cout << "List Positon: ";
cin >> listPos;
if ( listPos < Inventory.size()){
cout << " Item Sold and Removed from list position " << listPos <<endl;
search = Inventory.at(listPos-1);
//cout<< "contents of Search: "<< search << endl;
delete search;
Inventory.erase(Inventory.begin() + (listPos -1));
}
else{
cout << "Error"<<endl;
}
}
else if ( UserInput == "print") {
PrintEverything(Inventory);
}
else if ( UserInput != "quit"){
}
}
return 0;
}
This is a compile error.
Remove line 85: newItem.at(listPos - 1); and it runs just fine in visual studio.
The issue is that newItem is a pointer to an element. I assume you meant to use Inventory here instead. However, that logic was already done on the previous line.
On a side note, I stongly advise against storing owning pointers like this. There's no good reason in this case not to just use vector<UnSold> instead.
else if ( UserInput == "sell") {
cout << "List Positon: ";
cin >> listPos;
if ( listPos < Inventory.size()){
cout << " Item Sold and Removed from list position " << listPos <<endl;
search = Inventory.at(listPos-1);
//cout<< "contents of Search: "<< search << endl;
delete search;
Inventory.erase(Inventory.begin() + (listPos -1));
Here you mix the use of listPos and listPos - 1.
If you're allowing the user to input position 0 indexed, then
Inventory.at(listPos-1) should be Inventory.at(listPos) and
Inventory.erase(Inventory.begin() + (listPos -1)) should be Inventory.erase(Inventory.begin() + (listPos)).
If you're letting them input the position with the indexing starting at 1, then
if (listPos < Inventory.size()) should be
if(listPos <= Inventory.size() && listPos > 0)

c++ error: 'std::string' has no member

I am creating a directory program that prompts a user for a file name and reads the file into a string array. I'm have trouble in my SearchFirstName function. I get an error:'std::string' has no member named 'userRecord'. I'm not sure how to fix this because userRecord is declared.
Header
#include<string>
using namespace std;
enum Title {Mr, Mrs, Ms, Dr, NA};
struct NameType {
Title title;
string firstName;
string lastName;
};
struct AddressType {
string street;
string city;
string state;
string zip;
};
struct PhoneType {
int areaCode;
int prefix;
int number;
};
struct entryType {
NameType name;
AddressType address;
PhoneType phone;
};
const int MAX_RECORDS = 50;
Code
// string bookArray[MAX_RECORDS];
entryType bookArray[MAX_RECORDS]; //Solution
int bookCount = 0;
void OpenFile(string& filename, ifstream& inData)
{
do {
cout << "Enter file name to open: ";
cin >> filename;
inData.open(filename.c_str());
if (!inData)
cout << "File not found!" << endl;
} while (!inData);
if(inData.is_open())
{
for(int i=0; i<MAX_RECORDS;i++)
{
inData>> bookArray[bookCount];
++bookCount;
}
}
}
void SearchFirstName(ifstream& inData)
{
entryType userRecord; // Declaration of userRecord
string searchName;
string normalSearchName, normalFirstName;
char choice;
bool found = false;
cout << "Enter first name to search for: ";
cin >> searchName;
for(int i = 0; i < bookCount; ++i){
normalFirstName = NormalizeString(bookArray[i].userRecord.name.firstName);
// Convert retrieved string to all uppercase
if (normalFirstName == normalSearchName) { // Requested name matches
PrintRecord(bookArray[i].userRecord.name.firstName);
cout << "Is this the correct entry? (Y/N)";
cin >> choice;
choice = toupper(choice);
cout << endl;
if (choice == 'Y') {
found = true;
break;
}
}
}
// Matching name was found before the end of the file
if (inData && !found){
cout << "Record found: " << endl;
PrintRecord(userRecord);
cout << endl;
}
else if (!found) // End of file. Name not found.
{
cout << searchName << " not found!" << endl << endl;
}
// Clear file fail state and return to beginning
inData.clear();
inData.seekg(0);
}
string bookArray[MAX_RECORDS];
bookArray is of type string.It should be
entryType bookArray[MAX_RECORDS];
Also
normalFirstName = NormalizeString(bookArray[i].userRecord.name.firstName);
bookArray[i] cannot have userRecord as a member.userRecord is variable that you have declared.
It should be
normalFirstName = NormalizeString(bookArray[i].name.firstName);

convert function into member function?

I'm new here and I'm looking for help with a program written in c++.
I want to convert following functions that are not in a class nor in main() of my program
void PrintInventory(vector<Item*> inventory);
vector<Item*> AddItemToInventory(vector<Item*> inventory);
vector<Item*> UpdateItemQtyInInventory(vector<Item*> inventory);
vector<Item*> RemoveItemFromInventory(vector<Item*> inventory);
into public function members of a class Inventory that have no parameters and return nothing.
I've been working on that for 4 days now and just can't figure out how I'm supposed to change these functions to be void and have no parameter without destroying the whole program...
If I go exactly by what the instruction say which is to make a void/no parameters out of the four functions, I would get something like:
class Inventory
{
public:
void PrintInventory() {}
void AddItemToInventory() {}
void UpdateItemQtyInInventory() {}
void RemoveItemFromInventory() {}
private:
vector<Item*> inventory;
};
Please give me a hint. I feel like the solution must be simple but I've been completely stuck for days.
Thanks for your help.
EDIT:
I'm still getting a bunch of errors and think I need to say a bit more about my code:
I have a base class Item and two derived classes Produce and Book. Then I have four function calls:
// Print all items in the inventory
void PrintInventory(vector<Item*> inventory);
// Dialogue to create a new item, then add that item to the inventory
vector<Item*> AddItemToInventory(vector<Item*> inventory);
// Dialogue to update the quantity of an item, then update that item in the inventory
vector<Item*> UpdateItemQtyInInventory(vector<Item*> inventory);
// Dialogue to remove a specific item, then remove that specific item from the inventory
vector<Item*> RemoveItemFromInventory(vector<Item*> inventory);
Next comes the main and my class Inventory that now has four converted functions with no return and no parameters that were not originally inside the class Inventory and had parameters/return before.
Here is the whole code, I think it's better to understand this way:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <cstring>
using namespace std;
class Item {
public:
void SetName(string nm)
{
name = nm;
};
void SetQuantity(int qnty)
{
quantity = qnty;
};
void SetPrice(int prcInDllrs) //step1
{
priceInDollars = prcInDllrs; //step1
};
virtual void Print()
{
cout << name << " " << quantity << endl;
};
virtual ~Item()
{
return;
};
protected:
string name;
int quantity;
int priceInDollars; //step1
};
class Produce : public Item { // Derived from Item class
public:
void SetExpiration(string expir)
{
expiration = expir;
};
void Print()
{
cout << name << " x" << quantity
<< " for $" << priceInDollars //step1
<< " (Expires: " << expiration << ")"
<< endl;
};
private:
string expiration;
};
//step 2 add derived class Book
class Book : public Item { // Derived from Item class
public:
void SetAuthor(string authr) //create author function with parameter
{
author = authr;
};
void Print()
{
cout << name << " x" << quantity
<< " for $" << priceInDollars //step1
<< " (Author: " << author << ")"
<< endl;
};
private:
string author;
};
// Print all items in the inventory
void PrintInventory(vector<Item*> inventory);
// Dialogue to create a new item, then add that item to the inventory
vector<Item*> AddItemToInventory(vector<Item*> inventory);
// Dialogue to update the quantity of an item, then update that item in the inventory
vector<Item*> UpdateItemQtyInInventory(vector<Item*> inventory);
// Dialogue to remove a specific item, then remove that specific item from the inventory
vector<Item*> RemoveItemFromInventory(vector<Item*> inventory);
int main() {
vector<Item*> inventory;
string usrInptOptn = "default";
while (true) {
// Get user choice
cout << "\nEnter (p)rint, (a)dd, (u)pdate, (r)emove, or (q)uit: ";
getline(cin, usrInptOptn);
// Process user choice
if (usrInptOptn.size() == 0) {
continue;
}
else if (usrInptOptn.at(0) == 'p') {
PrintInventory(inventory);
}
else if (usrInptOptn.at(0) == 'a') {
inventory = AddItemToInventory(inventory);
}
else if (usrInptOptn.at(0) == 'u') {
inventory = UpdateItemQtyInInventory(inventory);
}
else if (usrInptOptn.at(0) == 'r') {
inventory = RemoveItemFromInventory(inventory);
}
else if (usrInptOptn.at(0) == 'q') {
cout << "\nGood bye." << endl;
break;
}
}
return 0;
}
class Inventory {
public:
void PrintInventory() {
unsigned int i = 0;
if (inventory.size() == 0) {
cout << "No items to print." << endl;
}
else {
for (i = 0; i<inventory.size(); ++i) {
cout << i << " - ";
inventory.at(i)->Print();
}
};
}
void AddItemToInventory() {
Produce* prdc;
Book* book; //create new pointer object of class book
string usrInptName = "";
string usrInptQntyStr = "";
istringstream inSS;
int usrInptQnty = 0;
string usrInptExpr = "";
int usrInptPrc = 0; //step1
string usrInptAuthr = ""; //declare variable
string usrInptBookName = "";
int usrInptQntyBook = 0;
string usrInptQntyBookStr = "";
string usrInptChoice = " ";
//loop user choice and ask again if choice is not valid
do {
cout << "Enter choice of adding (b)ook or (p)roduce: ";
getline(cin, usrInptChoice);
if (usrInptChoice != "b" && usrInptChoice != "p") {
cout << "Invalid Choice" << endl;
}
} while (usrInptChoice != "b" && usrInptChoice != "p");
//only ask for inventory type accoring to user input p or b
if (usrInptChoice == "p") {
cout << "Enter name of new produce: ";
getline(cin, usrInptName);
cout << "Enter quantity: ";
getline(cin, usrInptQntyStr);
inSS.str(usrInptQntyStr);
inSS >> usrInptQnty;
inSS.clear();
cout << "Enter expiration date: ";
getline(cin, usrInptExpr);
cout << "Enter the price per item : $"; //step1
cin >> usrInptPrc; //step1
prdc = new Produce;
prdc->SetName(usrInptName);
prdc->SetQuantity(usrInptQnty);
prdc->SetExpiration(usrInptExpr);
prdc->SetPrice(usrInptPrc);
inventory.push_back(prdc);
}
if (usrInptChoice == "b") {
cout << "Enter name of new book: ";
getline(cin, usrInptBookName);
cout << "Enter quantity: ";
getline(cin, usrInptQntyBookStr);
inSS.str(usrInptQntyBookStr);
inSS >> usrInptQntyBook;
inSS.clear();
cout << "Enter author: ";
getline(cin, usrInptAuthr);
cout << "Enter the price per item : $"; //step1
cin >> usrInptPrc; //step1
book = new Book;
book->SetName(usrInptBookName);
book->SetQuantity(usrInptQntyBook);
book->SetAuthor(usrInptAuthr);
book->SetPrice(usrInptPrc);
inventory.push_back(book);
};
}
void UpdateItemQtyInInventory() {
string usrIndexChoiceStr = "";
unsigned int usrIndexChoice = 0;
istringstream inSS;
string usrInptQntyStr = "";
int usrInptQnty = 0;
if (inventory.size() == 0) {
cout << "No items to update." << endl;
}
else {
PrintInventory();
do {
cout << "Update which item #: ";
getline(cin, usrIndexChoiceStr);
inSS.str(usrIndexChoiceStr);
inSS >> usrIndexChoice;
inSS.clear();
} while (!(usrIndexChoice < inventory.size()));
cout << "Enter new quantity: ";
getline(cin, usrInptQntyStr);
inSS.str(usrInptQntyStr);
inSS >> usrInptQnty;
inSS.clear();
inventory.at(usrIndexChoice)->SetQuantity(usrInptQnty);
};
}
void RemoveItemFromInventory() {
istringstream inSS;
string usrIndexChoiceStr = "";
unsigned int usrIndexChoice = 0;
string usrInptQntyStr = "";
if (inventory.size() == 0) {
cout << "No items to remove." << endl;
}
else {
PrintInventory();
do {
cout << "Remove which item #: ";
getline(cin, usrIndexChoiceStr);
inSS.str(usrIndexChoiceStr);
inSS >> usrIndexChoice;
inSS.clear();
} while (!(usrIndexChoice < inventory.size()));
inventory.erase(inventory.begin() + usrIndexChoice);
};
}
private:
vector<Item*> inventory;
};
I don't get any compilation errors in Visual Studio but when I try to build, there are 5 errors. Compiling the program in Geany gives me no errors either but when I build, it says:
undefined reference to `PrintInventory(std::vector<Item*, std::allocator<Item*> >)'
undefined reference to `AddItemToInventory(std::vector<Item*, std::allocator<Item*> >)'
undefined reference to `UpdateItemQtyInInventory(std::vector<Item*, std::allocator<Item*> >)'
undefined reference to `RemoveItemFromInventory(std::vector<Item*, std::allocator<Item*> >)'
collect2.exe: error: ld returned 1 exit status
Compilation failed.
I feel like I'm missing some basic, simple thing but I just can't figure it out. The instruction is confusing to me when it says I have to convert the functions PrintInventory, AddItemToInventory, UpdateItemQtyInInventory,
and RemoveItemFromInventory into void/no parameters but which functions does it refer to? The four definition lines? The actual functions? Both? And what about the main and the other classes? Wouldn't I need to change things there as well?
I believe your code conversion is correct. Since 'Inventory vector' is a a member variable it can be accessed by all the other member function and can also be manipulated. This removes the requirement for passing vector as argument.
Now for returning the vector I would suggest adding a new "GetInventory()" method which returns the vector or take a reference to pass the vector.
Hope it helps.
Thanks to WhozCraig, my problem has been solved:
"The class definition of Inventory has to come before main() somehow. Move it above main() and it should work."
Basic testing:
Note, there are no pointers in here
void test()
{
class T_item
{
public:
string name;
int quantity;
int priceInDollars;
};
vector<T_item> inventory;
T_item temp;
//add item:
temp.name = "name1";
temp.quantity = 1;
temp.priceInDollars = 1;
inventory.push_back(temp);
temp.name = "name2";
temp.quantity = 2;
temp.priceInDollars = 2;
inventory.push_back(temp);
cout << "print:\n";
for each(T_item item in inventory)
{
cout << item.name << endl;
cout << item.quantity << endl;
cout << item.priceInDollars << endl << endl;
}
//modify item at index 1:
inventory[1].name = "modified";
//delete item at index 0:
inventory.erase(inventory.begin() + 0);
cout << "print again:\n";
for each(T_item item in inventory)
{
cout << item.name << endl;
cout << item.quantity << endl;
cout << item.priceInDollars << endl << endl;
}
}
int main()
{
test();
return 0;
}

c++ trouble with either RTTI or binary file io

I think I am having trouble with binary file io. If I run my program, create some employee objects and then display them everything works fine. If I save the object data and reload the program I get an RTTI exception. It apears to me that my LoadEmployeeData() and Savelist(vector &e) functions work just fine. The exception occurs in my DisplayEmployeeData() function when I try to use typeid.
Just to reiterate, I am getting an RTTI error when using typeid on an object loaded from disk.
//****************header file***********
#include <string.h>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <typeinfo>
#include <ctime>
#include <cstdlib>
using namespace std;
class Employee
{
private:
int employeeID;
char name[80];
int SSN;
public:
Employee();
Employee(int, char*,int);
virtual ~Employee();
virtual void DisplayBaseData();
//getters
int GetID();
char* getName();
int GetSSN();
//setters
void SetID(int);
void SetName(char*);
void SetSSN(int);
};//end Employee class
class Salary : public Employee
{
private:
double salary;
public:
Salary();
Salary(int, char*, int, double); //id, name, ssn, salary
~Salary();
void DisplayEmployeeData();
//getters
double GetSalary();
//setters
void SetSalary(double);
};//end class Exempt
class Hourly : public Employee
{
private:
double rate;
double hoursWorked;
public:
Hourly();
Hourly(int, char*, int, double, double); //id, name, ssn, rate
~Hourly();
void DisplayEmployeeData();
//getters
double GetRate();
double GetHoursWorked();
//setters
void SetRate(double);
void SetHoursWorked(double);
};//end Hourly Class
const int HOURLYTYPE = 0;
const int SALARYTYPE = 1;
//*******body*******
#include "lab05.h";
Employee::Employee(){};
Employee::Employee(int ID, char* nme, int ssn) : employeeID(ID), SSN(ssn)
{
strcpy(name, nme);
}
int Employee::GetID()
{
return employeeID;
}
char* Employee::getName()
{
return name;
}
int Employee::GetSSN()
{
return SSN;
}
void Employee::SetID(int i)
{
employeeID = i;
}
void Employee::SetName(char* n)
{
strcpy(name, n);
}
void Employee::SetSSN(int i)
{
SSN = i;
}
void Employee::DisplayBaseData()
{
cout << "ID: \t" << employeeID << endl;
cout << "Name: \t " << name << endl;
cout << "SSN: \t" << SSN << endl;
}
Employee::~Employee(){}
Salary::Salary(){}
Salary::Salary(int id, char* nme, int ssn, double slry) : Employee(id, nme, ssn), salary(slry){}
void Salary::DisplayEmployeeData()
{
DisplayBaseData();
cout << "Salary: \t " << salary << endl;
}
double Salary::GetSalary()
{
return salary;
}
void Salary::SetSalary(double d)
{
salary = d;
}
Salary::~Salary(){}
Hourly::Hourly(){}
Hourly::Hourly(int id, char* nme, int ssn, double rte, double worked) : Employee(id, nme, ssn), rate(rte), hoursWorked(worked){}
void Hourly::DisplayEmployeeData()
{
DisplayBaseData();
cout << "Rate: \t" << rate << endl;
cout << "Worked: \t " << hoursWorked << endl;
}
double Hourly::GetRate()
{
return rate;
}
double Hourly::GetHoursWorked()
{
return hoursWorked;
}
void Hourly::SetRate(double d)
{
rate = d;
}
void Hourly::SetHoursWorked(double d)
{
hoursWorked = d;
}
Hourly::~Hourly(){}
vector<Employee*> LoadEmployeeData()
{
vector<Employee*> employeeList;
string fileName = "";
cout << "\nEnter filename for employee data: ";
cin >> fileName;
fstream file;
file.open(fileName, ios::in, ios::binary);
char buffer[4096] = {0};
int numEntries;
file.read((char*)&numEntries, sizeof(int));
cout << numEntries << " number of entries found." << endl;
if (numEntries != 0)
{
int identifier;
for (int i = 0; i < numEntries; i++)
{
file.read((char*)&identifier, sizeof(int));
if (identifier == SALARYTYPE)
{
Employee* temp = new Salary();
file.read((char*)temp, sizeof(Salary));
employeeList.push_back(temp);
}
else if (identifier == HOURLYTYPE)
{
Employee* temp = new Hourly();
file.read((char*)temp, sizeof(Hourly));
employeeList.push_back(temp);
}
}
}
else cout << "No Entries found." << endl;
file.close();
return employeeList;
}//end LoadEmployeeData function
void ListEmployees(vector<Employee*> &e)
{
if (e.size() != 0)
{
for (int i = 0; i < e.size(); i++)
{
if (typeid(*(e[i])) == typeid(Hourly))
{
cout << "\n(" << i << ")" << endl;
dynamic_cast<Hourly*>(e[i])->DisplayEmployeeData();
}
else if (typeid(*(e[i])) == typeid(Salary))
{
cout << "\n(" << i << ")" << endl;
dynamic_cast<Salary*>(e[i])->DisplayEmployeeData();
}
}
}
else cout << "No items in list" << endl;
}// end ListEmployees function
void ModifyEmployee(vector<Employee*> &e)
{
cout << "Enter employee selection." << endl;
}
void CreateEmployee(vector<Employee*> &e)
{
bool continueLoop = true;
srand(time(0)); //seed random number generator
cout << "\n Enter new employee information." << endl;
cout << "Name: ";
char newName[80] = {0};
cin >> newName;
cout << "\n SSN: ";
int newSSN;
cin >> newSSN;
char newType = '-1';
do
{
cout << "\n Is new employee paid a (s)alary or (h)ourly rate? ";
cin >> newType;
if (newType == 's' || newType == 'h') continueLoop = false;
else cout << "incorrect input" << endl;
}while (continueLoop == true);
if (newType == 's')
{
cout << "Enter salary amount: ";
double amount;
cin >> amount;
e.push_back(new Salary(rand() % 1000 + 1, newName, newSSN, amount));
}
else if (newType == 'h')
{
cout << "Enter hourly amount: ";
double amount;
cin >> amount;
cout << "Enter hours worked: ";
double hoursWorked;
cin >> hoursWorked;
e.push_back(new Hourly(rand() % 1000 + 1, newName, newSSN, amount, hoursWorked));
}
}
void Savelist(vector<Employee*> &e)
{
if (e.size() == 0)
cout << "No employees in list. Nothing done." << endl;
else
{
cout << "Enter save filename: ";
char fileName[80] = {'\0'};
cin >> fileName;
fstream* file = new fstream();
file->open(fileName, ios::out, ios::binary);
char buffer[80] = {'\0'};
int numEntries = e.size();
file->write((char*)&numEntries, sizeof(int)); //writes number of entries
for (int i = 0; i < e.size(); i++)
{
if (typeid(*e[i]) == typeid(Salary))
{
int classType = SALARYTYPE;
file->write((char*)&classType, sizeof(int));
file->write((char*)dynamic_cast<Salary*>(e[i]), sizeof(Salary));
}
else if (typeid(*e[i]) == typeid(Hourly))
{
int classType = HOURLYTYPE;
file->write((char*)&classType, sizeof(int));
file->write((char*)dynamic_cast<Hourly*>(e[i]), sizeof(Salary));
}
}
file->close();
}
}
void DeleteEmployee(vector<Employee*> &e)
{
cout << "Input index number of employee to delete: ";
int idx = 0;
cin >> idx;
if (idx > e.size() -1)
cout << "invalid index number\n" << endl;
else
{
delete e[idx];
e.erase(e.begin() + idx); //removes from list
}
}
int main()
{
const int ZERO = 0;
const int ONE = 1;
const int TWO = 2;
const int THREE = 3;
const int FOUR = 4;
const int FIVE = 5;
const int SIX = 6;
int exitMainLoop = false; //for flow control
int mainMenuChoice = -1;
vector<Employee*> employeeList;
do
{
cout << "Select from the following options." << endl;
cout << "(1) Load employee data file." << endl;
cout << "(2) View Employees." << endl;
cout << "(3) Modify Employee data. " << endl;
cout << "(4) Create new employee." << endl;
cout << "(5) Save list to file." << endl;
cout << "(6) Delete employee data. " << endl;
cout << "(0) Exit program." << endl;
//add more options
cout << "Enter selection: ";
cin >> mainMenuChoice;
if (cin.fail())
{
cout << "\nInvalid selection. Try again" << endl;
cin.clear();
string garbage = "";
cin >> garbage;
}
else if (mainMenuChoice == ONE)
employeeList = LoadEmployeeData();
else if (mainMenuChoice == TWO)
ListEmployees(employeeList);
else if (mainMenuChoice == THREE)
ModifyEmployee(employeeList);
else if (mainMenuChoice == FOUR)
CreateEmployee(employeeList);
else if (mainMenuChoice == FIVE)
Savelist(employeeList);
else if (mainMenuChoice == SIX)
DeleteEmployee(employeeList);
else if (mainMenuChoice == ZERO)
exitMainLoop = true;
}while(exitMainLoop == false);
system("PAUSE");
}
You can't read/write raw C++ objects from/to disk if they have virtual methods (or use RTTI, which requires virtual methods) because there's no guarantee that the vtable address from the first execution will be written to disk, and there's no guarantee that the vtable will be in the same place the next time the program is run -- hence, the address that was written to disk will point somewhere incorrect when it is read back.
file->write((char*)dynamic_cast<Hourly*>(e[i]), sizeof(Salary));
looks suspicious. did you mean sizeof(Hourly)?