Hopefully this will be my last question for a while.
I'm a little confused as to why my function isn't working. Here is my code (I'll explain a little bit more afterwards):
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
class Inventory {
public:
void SetSumInv(int prcInDllrs, int individualquantity) {
priceInDollars = priceInDollars + (prcInDllrs * individualquantity);
totalInvPriceInDollars = totalInvPriceInDollars + priceInDollars;
}
void SetItemPrice(int whatever) {
itemsPrice = whatever;
}
void SetName(string nm)
{
name = nm;
};
void SetQuantity(int qnty)
{
quantity = qnty;
};
void SetAuthor(string athr) {
author = athr;
}
void SetExpiration(string expir)
{
expiration = expir;
};
virtual void Print(){
cout << name << " x" << quantity << " for: $" << itemsPrice; //" (Expires: " << expiration << ")";
if (expiration.size() != 0) {
cout << " (Expires: " << expiration << ")" << endl;
}
else {
cout << " (Author: " << author << ")" << endl;
}
}
void PrintInventory(vector<Inventory*> inventory) {
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();
}
cout << "Total inventory value: " << priceInDollars;
}
return;
}
void AddItemToInventory()
{
}
vector<Inventory*> AddProduceToInventory(vector<Inventory*> inventory)
{
Inventory* prdc;
string usrInptName = "";
string usrInptQntyStr = "";
istringstream inSS;
istringstream inDD;
int usrInptQnty = 0;
string usrInptExpr = "";
string usrInptPrcStr = "";
int usrInptPrc = 0;
int ItemCost = 0;
cout << "Enter name of new produce: ";
getline(cin, usrInptName);
SetName(usrInptName);
cout << "Enter quantity: ";
getline(cin, usrInptQntyStr);
inSS.str(usrInptQntyStr);
inSS >> usrInptQnty;
inSS.clear();
SetQuantity(usrInptQnty);
cout << "Enter expiration date: ";
getline(cin, usrInptExpr);
SetExpiration(usrInptExpr);
cout << "Enter the price per item: $";
getline(cin, usrInptPrcStr);
inDD.str(usrInptPrcStr);
inDD >> usrInptPrc;
inDD.clear();
SetItemPrice(usrInptPrc);
ItemCost = (usrInptPrc * usrInptQnty);
prdc = new Inventory;
prdc->SetName(usrInptName);
prdc->SetQuantity(usrInptQnty);
prdc->SetExpiration(usrInptExpr);
prdc->SetSumInv(usrInptPrc, usrInptQnty);
prdc->SetItemPrice(usrInptPrc);
inventory.push_back(prdc);
return inventory;
}
void AddBookToInventory()
{
}
vector<Inventory*> AddBookToInventory(vector<Inventory*> inventory) {
Inventory* prdct;
string usrInptName = "";
string usrInptQntyStr = "";
istringstream inSS;
int usrInptQnty = 0;
string usrInptAthr = "";
string usrInptPrcStr = "";
int usrInptPrc = 0;
istringstream inDD;
int sum = 0;
int ItemCost = 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();
ItemCost = (usrInptPrc * usrInptQnty);
prdct = new Inventory;
prdct->SetName(usrInptName);
prdct->SetQuantity(usrInptQnty);
prdct->SetSumInv(usrInptPrc, usrInptQnty);
prdct->SetAuthor(usrInptAthr);
prdct->SetItemPrice(usrInptPrc);
inventory.push_back(prdct);
return inventory;
}
void UpdateItemQtyInventory()
{}
//This is the update function in which we can change how many items a certain purchase has
vector<Inventory*> UpdateItemQtyInInventory(vector<Inventory*> inventory) {
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(inventory);
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);
}
return inventory;
}
void RemoveItemFromInventory()
{}
//Here we will be removing an entire item from the inventory
vector<Inventory*> RemoveItemFromInventory(vector<Inventory*> 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()
{
}
protected:
string name;
int quantity = 0;
int priceInDollars = 0;
int totalCost = 0;
int itemsPrice = 0;
string expiration;
string author;
private:
int totalInvPriceInDollars = 0;
};
int main() {
vector<Inventory*> INVENTORY;
string usrInptOptn = "default";
string usrInptOptn2 = "default";
Inventory update;
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') {
update.PrintInventory(INVENTORY); //Different!
}
else if (usrInptOptn.at(0) == 'a') {///I don't know what the difference is between the three slashes and the two, but they are different!
cout << "\nEnter (b)ook or (p)roduce: ";
getline(cin, usrInptOptn2);
if (usrInptOptn2.at(0) == 'b') {
INVENTORY = update.AddBookToInventory(INVENTORY); //Supposed to look like: INV = AddItem...(INV);
}
else if (usrInptOptn2.at(0) == 'p') {
INVENTORY = update.AddProduceToInventory(INVENTORY);
}
else
{
continue;
}
}
else if (usrInptOptn.at(0) == 'u') {
INVENTORY = update.UpdateItemQtyInInventory(INVENTORY);
}
else if (usrInptOptn.at(0) == 'r') {
INVENTORY = update.RemoveItemFromInventory(INVENTORY);
}
else if (usrInptOptn.at(0) == 'q') {
cout << "\nGood bye." << endl;
break;
}
}
return 0;
}
So now. In my class Inventory, public: void SetSumInv, what this program does is it gets the user input, and tallies everything up, so when it prints, it is supposed to print the inventory and afterwards it is supposed to print the sum of the inventory value (in dollars). I've tried running this, and it won't print the sum of the inventory value. What is wrong here? I can't figure this out.
Thanks!
After dissecting your code; it took me considerable amount of time to clean some of it up. I did not have time to search for your bug, but what I was able to do was clean up your class a little bit so that it is friendlier to read. I made a couple of modifications to some of your class's function calls which are explained in the comments. I also removed all of the empty functions you had declared within your class. I also changed the look or feel of the classes naming conventions (this is user preference only)
Inventory.h
#ifndef INVENTORY_H
#define INVENTORY_H
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
class Inventory {
protected:
std::string m_strName;
std::string m_strExpiration;
std::string m_strAuthor;
int m_quantity;
int m_priceInDollars;
int m_totalCost;
int m_itemsPrice;
private:
int m_totalInvPriceInDollars;
public:
Inventory(); // Default Constructor
void setName( const std::string& nm );
void setAuthor( const std::string& athr );
void setExpiration( const std::string& expir );
void setSumInv( int prcInDllrs, int individualquantity );
void setItemPrice( int whatever );
void setQuantity( int qnty );
virtual void print();
void printInventory( std::vector<Inventory*>& inventory );
// I changed these methods to pass by reference opposed to returning from function call
void addProduceToInventory( std::vector<Inventory*>& inventory );
void addBookToInventory( std::vector<Inventory*>& inventory );
void updateItemQtyInInventory( std::vector<Inventory*>& inventory );
void removeItemFromInventory( std::vector<Inventory*>& inventory );
}; // Invenotory
#endif // INVENTORY_H
Inventory.cpp
#include "Inventory.h"
// ----------------------------------------------------------------------------
// Inventory()
Inventory::Inventory() :
m_quantity( 0 ),
m_itemsPrice( 0 ),
m_priceInDollars( 0 ),
m_totalCost( 0 ),
m_totalInvPriceInDollars( 0 ) {
} // Inventory
// ----------------------------------------------------------------------------
// setSumInv()
void Inventory::setSumInv( int prcInDllrs, int individualquantity ) {
m_priceInDollars = m_priceInDollars + (prcInDllrs * individualquantity);
m_totalInvPriceInDollars = m_totalInvPriceInDollars + m_priceInDollars;
} // setSumInv
// ----------------------------------------------------------------------------
// setItemPrice()
void Inventory::setItemPrice( int whatever ) {
m_itemsPrice = whatever;
} // setItemPrice
// ----------------------------------------------------------------------------
// setQuantity()
void Inventory::setQuantity( int qnty ) {
m_quantity = qnty;
} // setQuantity
// ----------------------------------------------------------------------------
// setName()
void Inventory::setName( const std::string& strName ) {
m_strName = strName;
} // setName
// ----------------------------------------------------------------------------
// setAuthor()
void Inventory::setAuthor( const std::string& strAuthor ) {
m_strAuthor = strAuthor;
} // setAuthor
// ----------------------------------------------------------------------------
// setExpiration()
void Inventory::setExpiration( const std::string& strExpir ) {
m_strExpiration = strExpir;
} // setExpiration
// ----------------------------------------------------------------------------
// print()
void Inventory::print() {
std::cout << m_strName << " x" << m_quantity << " for: $" << m_itemsPrice; //" (Expires: " << expiration << ")";
if ( m_strExpiration.size() != 0 ) {
std::cout << " (Expires: " << m_strExpiration << ")" << std::endl;
} else {
std::cout << " (Author: " << m_strAuthor << ")" << std::endl;
}
} // print
// ----------------------------------------------------------------------------
// printInventory()
void Inventory::printInventory( std::vector<Inventory*>& vInventory ) {
unsigned int i = 0;
if ( vInventory.size() == 0) {
std::cout << "No items to print." << std::endl;
} else {
for ( i = 0; i < vInventory.size(); ++i ) {
std::cout << i << " - ";
vInventory.at(i)->print();
}
std::cout << "Total inventory value: " << m_priceInDollars;
}
} // printInventory
// ----------------------------------------------------------------------------
// addProduceToInventory()
void Inventory::addProduceToInventory( std::vector<Inventory*>& vInventory ) {
std::string usrInptName = "";
std::string usrInptQntyStr = "";
std::istringstream inSS;
std::istringstream inDD;
int usrInptQnty = 0;
std::string usrInptExpr = "";
std::string usrInptPrcStr = "";
int usrInptPrc = 0;
int itemCost = 0;
std::cout << "Enter name of new produce: ";
getline( std::cin, usrInptName );
setName( usrInptName );
std::cout << "Enter quantity: ";
std::getline( std::cin, usrInptQntyStr );
inSS.str( usrInptQntyStr );
inSS >> usrInptQnty;
inSS.clear();
setQuantity( usrInptQnty );
std::cout << "Enter expiration date: ";
getline( std::cin, usrInptExpr );
setExpiration( usrInptExpr );
std::cout << "Enter the price per item: $";
getline( std::cin, usrInptPrcStr );
inDD.str( usrInptPrcStr );
inDD >> usrInptPrc;
inDD.clear();
setItemPrice( usrInptPrc );
itemCost = usrInptPrc * usrInptQnty;
Inventory* pInv = nullptr; // Initialize Pointers to nullptr
pInv = new Inventory; // Using New Memory (Dyanamic) - Where Is This Being Deleted?
pInv->setName( usrInptName );
pInv->setQuantity( usrInptQnty );
pInv->setExpiration( usrInptExpr );
pInv->setSumInv( usrInptPrc, usrInptQnty );
pInv->setItemPrice(usrInptPrc);
vInventory.push_back( pInv );
} // addProduceToInventory
// ----------------------------------------------------------------------------
// addBookToInventory()
void Inventory::addBookToInventory( std::vector<Inventory*>& inventory) {
std::string usrInptName = "";
std::string usrInptQntyStr = "";
std::istringstream inSS;
int usrInptQnty = 0;
std::string usrInptAthr = "";
std::string usrInptPrcStr = "";
int usrInptPrc = 0;
std::istringstream inDD;
int sum = 0;
int itemCost = 0;
std::cout << "Enter name of new book: ";
getline( std::cin, usrInptName );
std::cout << "Enter quantity: ";
getline( std::cin, usrInptQntyStr );
inSS.str( usrInptQntyStr );
inSS >> usrInptQnty;
inSS.clear();
std::cout << "Enter author: ";
getline( std::cin, usrInptAthr );
std::cout << "Enter the price per item: $";
getline( std::cin, usrInptPrcStr );
inDD.str( usrInptPrcStr );
inDD >> usrInptPrc;
inDD.clear();
itemCost = usrInptPrc * usrInptQnty;
Inventory* pInv = nullptr; // Initialize pointers to nullptr;
pInv = new Inventory; // Using New Memory (Dyanamic) - Where Is This Being Deleted?
pInv->setName( usrInptName );
pInv->setQuantity( usrInptQnty );
pInv->setSumInv( usrInptPrc, usrInptQnty );
pInv->setAuthor( usrInptAthr );
pInv->setItemPrice( usrInptPrc );
inventory.push_back( pInv );
} // addBookToInventory
// ----------------------------------------------------------------------------
// updateItemQtyInInventory()
// This is the update function in which we can change how many items a certain purchase has
void Inventory::updateItemQtyInInventory( std::vector<Inventory*>& vInventory ) {
std::string usrIndexChoiceStr = "";
unsigned int usrIndexChoice = 0;
std::istringstream inSS;
std::string usrInptQntyStr = "";
int usrInptQnty = 0;
if ( vInventory.size() == 0 ) {
std::cout << "No items to update." << std::endl;
} else {
printInventory( vInventory );
do {
std::cout << "Update which item #: ";
getline( std::cin, usrIndexChoiceStr );
inSS.str( usrIndexChoiceStr );
inSS >> usrIndexChoice;
inSS.clear();
} while ( !(usrIndexChoice < vInventory.size()) );
std::cout << "Enter new quantity: ";
getline( std::cin, usrInptQntyStr );
inSS.str( usrInptQntyStr );
inSS >> usrInptQnty;
inSS.clear();
vInventory.at(usrIndexChoice)->setQuantity(usrInptQnty);
}
} // updateItemQtyInInventory
// ----------------------------------------------------------------------------
// removeItemFromInventory()
// Here we will be removing an entire item from the inventory
void Inventory::removeItemFromInventory( std::vector<Inventory*>& vInventory) {
std::istringstream inSS;
std::string usrIndexChoiceStr = "";
unsigned int usrIndexChoice = 0;
std::string usrInptQntyStr = "";
if ( vInventory.size() == 0 ) {
std::cout << "No items to remove." << std::endl;
} else {
printInventory( vInventory );
do {
std::cout << "Remove which item #: ";
getline( std::cin, usrIndexChoiceStr );
inSS.str( usrIndexChoiceStr );
inSS >> usrIndexChoice;
inSS.clear();
} while ( !(usrIndexChoice < vInventory.size()) );
vInventory.erase( vInventory.begin() + usrIndexChoice );
}
} // removeItemFromInventory
main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
//using namespace std; // Bad Practice To Use This In A Global Scope!
#include "Inventory.h"
// ----------------------------------------------------------------------------
// main()
int main() {
std::vector<Inventory*> vInventory;
std::string strUsrInptOptn = "default";
std::string strUsrInptOptn2 = "default";
Inventory update;
while (true) {
// Get user choice
std::cout << "\nEnter (p)rint, (a)dd, (u)pdate, (r)emove, or (q)uit: ";
getline( std::cin, strUsrInptOptn);
// Process user choice
if ( strUsrInptOptn.size() == 0 ) {
continue;
} else if ( strUsrInptOptn.at(0) == 'p' ) {
update.printInventory( vInventory ); //Different!
} else if ( strUsrInptOptn.at(0) == 'a' ) { ///I don't know what the difference is between the three slashes and the two, but they are different!
std::cout << "\nEnter (b)ook or (p)roduce: ";
getline( std::cin, strUsrInptOptn2 );
if ( strUsrInptOptn2.at(0) == 'b' ) {
update.addBookToInventory( vInventory ); //Supposed to look like: INV = AddItem...(INV);
} else if ( strUsrInptOptn2.at(0) == 'p' ) {
update.addProduceToInventory( vInventory );
} else {
continue;
}
} else if ( strUsrInptOptn.at(0) == 'u' ) {
update.updateItemQtyInInventory( vInventory );
} else if ( strUsrInptOptn.at(0) == 'r' ) {
update.removeItemFromInventory( vInventory );
} else if ( strUsrInptOptn.at(0) == 'q') {
std::cout << "\nGood bye." << std::endl;
break;
}
} // while
return 0;
} // main
With this the code is much cleaner looking with an elegant feel. The main.cpp isn't cluttered with tons of lines of code; it is always good practice to keep main.cpp short and simple since this is where the main executable starts. I created a class of your inventory and put it in its own module in a *.h and *.cpp file. I also separated its declaration from its definition or its implementation. This way if someone else is looking at your source code to use it; they do not have to know exactly how the function works, only what it is supposed to do. The interface or *.h file should tell you everything you need to know about the class object and how it is used. Also this allows for cleaner and quicker build times since you only have to compile this class's *.cpp file only when you changed something within instead of rebuilding the entire solution.
Now there are some instances where you might want to have the implementation in the header file and some cases where you don't have a choice and it has to be. The cases where you might want the implementation to be in the header file is if your methods are declared as inline or you are creating a header only library. The case where you may not have a choice but to have it in the header file is if you are creating class templates or function templates however when you have these two types either inline member functions, class template member functions or function templates these will usually be found in an inline file or an *.inl and you would include this file using the #include directive outside of your class's declaration and before the #endif header guard; if you are using #pragma once instead of the #ifndef #define #endif then you would just have this after the class's declaration.
Once you start to have a constant structure of your code that you prefer; it will become easier to debug and find errors.
Out side of your question I think I have noticed another bug that you have introduced that you may or may not be aware of; I think you may have a memory leak in your program!
I hope this serves as a guide to help you. If I get the chance within the next couple of days; I may go ahead and either try to debug your code or try to rewrite your program in a slightly more elegant way. If I do get around to it I'll post it as another answer.
I have written a version of the program that the user had requested. It took me a little bit of time to work out the bugs and to make sure that it is working as expected. This doesn't meant that it is completely bug free. If anyone happens to find any bugs please feel free to comment and list any bugs so that I can fix them and make the appropriate edits.
This program is written in C++ using Win32 Console Application compiled and built with VS 2015.
What I have done here is created a small class hierarchy. The StoreItem class is an abstract base class meaning you can not create an object of this type directly since its constructors are protected. Any class object that inherits from this base class can be constructed publicly. I did this since different product types may have different information about them.
I took what was common about all Product Types and stored that information into the base class using protected members and public access functions. The only private member in the base class is the Type the inherited class is upon construction. These are just objects that contain data and methods. The Inventory class is what does a majority of the work to store and remove items, to calculate totals and to print its list.
I designed it this way so that the StoreItem and its inherited classes do not have any dependences with the iostream objects. The Inventory class only uses the std::cout objects within its printing method.
The only section of code that works with the input or the std::cin object is within the main function in the working while loop.
Having a structure such as this, allows these classes to be modular, or reusable. This also makes it easy to add another type or store item. You would have to create another class that is derived from StoreItem, Add in the Enumerated type, then repeat the process of adding in the appropriate functions within the Inventory and within the user choice branching.
This could be simplified a little more but I tried to keep this as close to the user's original program. I did not elect to use generic template types which is also a very useful and an efficient way of implementing it to reduce the amount of code redundancy. One needs to master these basic concepts before they can begin to move onto more advanced topics.
stdafx.h
#ifndef STDAFX_H
#define STDAFX_H
#include <stdio.h>
#include <tchar.h>
#include <conio.h>
#include <string>
#include <iostream>
#include <memory>
//#include <sstream> // Not Using stringstring, istringstream, or ostringstream
#include <vector>
#endif // STDAFX_H
stdafx.cpp
#include "stdafx.h"
StoreItem.h
#ifndef STORE_ITEM_H
#define STORE_ITEM_H
class StoreItem {
public:
enum ItemType {
ITEM_BOOK = 0,
ITEM_PRODUCE,
}; // ItemType
protected:
std::string m_strItemName;
float m_priceInDollars;
private:
ItemType m_type;
public:
std::string getItemName() const;
float getItemPrice() const;
void setItemName( const std::string& strItemName );
void setItemPrice( float price );
ItemType getItemType() const;
protected:
explicit StoreItem( ItemType type );
StoreItem( ItemType type, const std::string& strItemName, float priceInDollars );
}; // StoreItem
#endif // STORE_ITEM_H
StoreItem.cpp
#include "stdafx.h"
#include "StoreItem.h"
// ----------------------------------------------------------------------------
// StoreItem()
StoreItem::StoreItem( ItemType type ) :
m_type( type ) {
} // StoreItem
// ----------------------------------------------------------------------------
// StoreItem()
StoreItem::StoreItem( ItemType type, const std::string& strItemName, float priceInDollars ) :
m_type( type ),
m_strItemName( strItemName ),
m_priceInDollars( priceInDollars ){
} // StoreItem
// ----------------------------------------------------------------------------
// getItemType()
StoreItem::ItemType StoreItem::getItemType() const {
return m_type;
} // getItemType
// ----------------------------------------------------------------------------
// setItemName()
void StoreItem::setItemName( const std::string& strItemName ) {
m_strItemName = strItemName;
} // setItemName
// ----------------------------------------------------------------------------
// getItemName()
std::string StoreItem::getItemName() const {
return m_strItemName;
} // getItemName
// ----------------------------------------------------------------------------
// setItemPrice()
void StoreItem::setItemPrice( float priceInDollars ) {
m_priceInDollars = priceInDollars;
} // setItemPrice
// ----------------------------------------------------------------------------
// getItemPrice()
float StoreItem::getItemPrice() const {
return m_priceInDollars;
} // getItemPrice
Book.h
#ifndef BOOK_H
#define BOOK_H
#include "StoreItem.h"
class Book sealed : public StoreItem {
private:
std::string m_strAuthorName;
public:
Book();
Book( const std::string& strItemName, float priceInDollars, const std::string& strAuthor );
void setAuthorName( const std::string& strAuthor );
std::string getAuthorName() const;
}; // Book
#endif // BOOK_H
Book.cpp
#include "stdafx.h"
#include "Book.h"
// ----------------------------------------------------------------------------
// Book()
Book::Book() :
StoreItem( ITEM_BOOK ) {
} // Book
// ----------------------------------------------------------------------------
// Book()
Book::Book( const std::string& strItemName, float priceInDollars, const std::string& strAuthorName ) :
StoreItem( ITEM_BOOK, strItemName, priceInDollars ),
m_strAuthorName( strAuthorName ) {
} // Book
// ----------------------------------------------------------------------------
// setAuthorName()
void Book::setAuthorName( const std::string& strAuthorName ) {
m_strAuthorName = strAuthorName;
} // setAuthorName
// ----------------------------------------------------------------------------
// getAuthorName()
std::string Book::getAuthorName() const {
return m_strAuthorName;
} // getAuthorName
Produce.h
#ifndef PRODUCE_H
#define PRODUCE_H
#include "StoreItem.h"
class Produce sealed : public StoreItem {
private:
std::string m_strExpirationDate;
public:
Produce();
Produce( const std::string& strItemName, float priceInDollars, const std::string& strExpirationDate );
void setExpirationDate( const std::string& strExpirationDate );
std::string getExpirationDate() const;
}; // Produce
#endif // PRODUCE_H
Produce.cpp
#include "stdafx.h"
#include "Produce.h"
// ----------------------------------------------------------------------------
// Produce()
Produce::Produce() :
StoreItem( ITEM_PRODUCE ) {
} // Produce
// ----------------------------------------------------------------------------
// Produce()
Produce::Produce( const std::string& strItemName, float priceInDollars, const std::string& strExpirationDate ) :
StoreItem( ITEM_PRODUCE, strItemName, priceInDollars ),
m_strExpirationDate( strExpirationDate ) {
} // Produce
// ----------------------------------------------------------------------------
// setExpirationDate()
void Produce::setExpirationDate( const std::string& strExpirationDate ) {
m_strExpirationDate = strExpirationDate;
} // setExpirationDate
// ----------------------------------------------------------------------------
// getExpirationDate()
std::string Produce::getExpirationDate() const {
return m_strExpirationDate;
} // getExpirationDate
Inventory.h
#ifndef INVENTORY_H
#define INVENTORY_H
#include "StoreItem.h" // Needed For StoreItem::ItemType
class Book;
class Produce;
class Inventory {
private:
typedef std::vector<std::shared_ptr<Book>> PtrBooks;
typedef std::vector<std::shared_ptr<Produce>> PtrProduce;
PtrBooks m_vBooks;
PtrProduce m_vProduce;
public:
void addBook( const std::string& strName, const std::string& strAuthor, float price );
void addProduce( const std::string& strName, const std::string& strExpiration, float price );
void removeItemFromIventory( StoreItem::ItemType type, const std::string& strItemName, unsigned idx );
void showInventory() const;
bool isBookListEmpty() const;
bool isProduceListEmpty() const;
}; // Inventory
Inventory.cpp
#include "stdafx.h"
#include "Inventory.h"
#include "Book.h"
#include "Produce.h"
// ----------------------------------------------------------------------------
// addBook()
void Inventory::addBook( const std::string& strName, const std::string& strAuthor, float price ) {
m_vBooks.push_back( std::shared_ptr<Book>( new Book( strName, price, strAuthor ) ) );
} // addItemTo
// addProduce()
void Inventory::addProduce( const std::string& strName, const std::string& strExpiration, float price ) {
m_vProduce.push_back( std::shared_ptr<Produce>( new Produce( strName, price, strExpiration ) ) );
} // addProduce
// ----------------------------------------------------------------------------
// removeItemFromInventory()
void Inventory::removeItemFromIventory( StoreItem::ItemType type, const std::string& strItemName, unsigned idx ) {
if ( strItemName.empty() ) {
// throw Exeption Here
return;
}
unsigned counter = 1; // User Based, Not Vector or Array Based
if ( type == StoreItem::ITEM_BOOK ) {
PtrBooks::iterator it = m_vBooks.begin();
for ( ; it != m_vBooks.end(); ++it ) {
if ( it->get()->getItemName() == strItemName && counter == idx ) {
// Found It
it->reset();
m_vBooks.erase( it );
return;
}
counter++;
}
}
// Reset Counter
counter = 1;
if ( type == StoreItem::ITEM_PRODUCE ) {
PtrProduce::iterator it = m_vProduce.begin();
for ( ; it != m_vProduce.end(); ++it ) {
if ( it->get()->getItemName() == strItemName && counter == idx ) {
// Found It
it->reset();
m_vProduce.erase( it );
return;
}
counter++;
}
}
} // removeItemFromInventory()
// ----------------------------------------------------------------------------
// showInventory()
void Inventory::showInventory() const {
float totalCostBooks = 0;
float totalCostProduce = 0;
std::flush( std::cout );
std::cout << "\n-------------" << std::endl
<< "Sales Invoice" << std::endl
<< "-------------" << std::endl << std::endl;
std::cout << "Book Information: " << std::endl;
for ( unsigned u = 0; u < m_vBooks.size(); ++u ) {
std::cout << u + 1 << ": "
<< m_vBooks.at( u ).get()->getItemName() << " "
<< m_vBooks.at( u ).get()->getAuthorName() << " "
<< "$" << m_vBooks.at( u ).get()->getItemPrice() << std::endl;
totalCostBooks += m_vBooks.at( u ).get()->getItemPrice();
}
std::cout << "Total Cost Of Books: $" << totalCostBooks << std::endl << std::endl;
std::cout << "Produce Information: " << std::endl;
for ( unsigned u = 0; u < m_vProduce.size(); ++u ) {
std::cout << u + 1 << ": "
<< m_vProduce.at( u ).get()->getItemName() << " "
<< m_vProduce.at( u ).get()->getExpirationDate() << " "
<< "$" << m_vProduce.at( u ).get()->getItemPrice() << std::endl;
totalCostProduce += m_vProduce.at( u ).get()->getItemPrice();
}
std::cout << "Total Cost Of Produce: $" << totalCostProduce << std::endl << std::endl;
std::cout << "------------------" << std::endl
<< "Grand Total: $" << totalCostBooks + totalCostProduce << std::endl;
} // showInventory
// ----------------------------------------------------------------------------
// isBookListEmpty()
bool Inventory::isBookListEmpty() const {
return m_vBooks.empty();
} // isBookListEmpty
// ----------------------------------------------------------------------------
// isProduceListEmpty()
bool Inventory::isProduceListEmpty() const {
return m_vProduce.empty();
} // isProduceListEmpty
main.cpp
// StoreInventory.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "Inventory.h"
int main() {
Inventory inventory;
std::string userInput;
bool quit = false;
while ( !quit ) {
std::cout << "\nEnter (a)dd, (r)emove, (s)how inventory, (q)uit: ";
std::cin >> userInput;
if ( userInput[0] == 'a' || userInput[0] == 'A' ) {
std::cout << "\nEnter (b)ook or (p)roduce: ";
std::cin >> userInput;
if ( userInput[0] == 'b' || userInput[0] == 'B' ) {
std::string strName;
std::string strAuthor;
float price = 0;
std::cout << "\nEnter the name of the book. ";
std::getline( std::cin, strName ); // For Some Reason I have To Add This Twice
std::getline( std::cin, strName );
std::cout << "\nEnter the book's author. ";
std::getline( std::cin, strAuthor );
std::cout << "\nEnter the price in US Dollars. ";
std::cin >> price;
inventory.addBook( strName, strAuthor, price );
} else if ( userInput[0] == 'p' || userInput[0] == 'P' ) {
std::string strName;
std::string strExpiration;
float price = 0;
std::cout << "\nEnter the type of produce. ";
std::getline( std::cin, strName ); // For Some Reason I have To Add This Twice
std::getline( std::cin, strName );
std::cout << "\nEnter the expiration date. ";
std::getline( std::cin, strExpiration );
std::cout << "\nEnter the price in US Dollars. ";
std::cin >> price;
inventory.addProduce( strName, strExpiration, price );
} else {
std::cout << "\nInvalid Entry\n";
}
system( "cls" ); // If on windows and using win32 console
continue;
} else if ( userInput[0] == 'r' || userInput[0] == 'R' ) {
// Clear The Screen, Show The Inventory Then Ask User Which Item To Remove
system( "cls" ); // If on windows and using win32 console
inventory.showInventory();
std::cout << "\nWhich item would you like to remove (b)ook or (p)roduce? ";
std::cin >> userInput;
StoreItem::ItemType type;
if ( userInput[0] == 'b' || userInput[0] == 'B' ) {
if ( inventory.isBookListEmpty() ) {
std::cout << "\nThere are no entries availabe to remove. ";
continue;
} else {
type = StoreItem::ITEM_BOOK;
}
} else if ( userInput[0] == 'p' || userInput[0] == 'P' ) {
if ( inventory.isProduceListEmpty() ) {
std::cout << "\nThere are no entries available to remove. ";
continue;
} else {
type = StoreItem::ITEM_PRODUCE;
}
} else {
std::cout << "\nInvalid Type\n";
}
std::string strName;
unsigned idx;
std::cout << "\nEnter name of product you wish to remove. ";
std::getline( std::cin, strName ); // For Some Reason I have To Add This Twice
std::getline( std::cin, strName );
std::cout << "\nEnter item number of this type you wish to remove. ";
std::cin >> idx;
inventory.removeItemFromIventory( type, strName, idx );
continue;
} else if ( userInput[0] == 's' || userInput[0] == 'S' ) {
system( "cls" ); // If on windows and using win32 console
inventory.showInventory();
continue;
} else if ( userInput[0] == 'q' || userInput[0] == 'Q' ) {
quit = true;
break;
} else {
std::cout << "\nInvalid Entry\n";
continue;
}
} // while
std::cout << "\nPress any key to quit" << std::endl;
_getch();
return 0;
} // main
Few issues:
1.) priceInDollars was not being initialized properly
2.) totalInvPriceInDollars needs to be static
below code fixes the issues:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int totalInvPriceInDollars = 0 ;
class Inventory {
public:
Inventory(): priceInDollars(0) {};
void SetSumInv(int prcInDllrs, int individualquantity) {
priceInDollars = priceInDollars + (prcInDllrs * individualquantity);
totalInvPriceInDollars = totalInvPriceInDollars + priceInDollars;
}
void SetItemPrice(int whatever) {
itemsPrice = whatever;
}
void SetName(string nm)
{
name = nm;
};
void SetQuantity(int qnty)
{
quantity = qnty;
};
void SetAuthor(string athr) {
author = athr;
}
void SetExpiration(string expir)
{
expiration = expir;
};
virtual void Print(){
cout << name << " x" << quantity << " for: $" << itemsPrice; //" (Expires: " << expiration << ")";
if (expiration.size() != 0) {
cout << " (Expires: " << expiration << ")" << endl;
}
else {
cout << " (Author: " << author << ")" << endl;
}
}
void PrintInventory(vector<Inventory*> inventory) {
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();
}
cout << "Total inventory value: " << totalInvPriceInDollars;
}
return;
}
void AddItemToInventory()
{
}
vector<Inventory*> AddProduceToInventory(vector<Inventory*> inventory)
{
Inventory* prdc;
string usrInptName = "";
string usrInptQntyStr = "";
istringstream inSS;
istringstream inDD;
int usrInptQnty = 0;
string usrInptExpr = "";
string usrInptPrcStr = "";
int usrInptPrc = 0;
int ItemCost = 0;
cout << "Enter name of new produce: ";
getline(cin, usrInptName);
SetName(usrInptName);
cout << "Enter quantity: ";
getline(cin, usrInptQntyStr);
inSS.str(usrInptQntyStr);
inSS >> usrInptQnty;
inSS.clear();
SetQuantity(usrInptQnty);
cout << "Enter expiration date: ";
getline(cin, usrInptExpr);
SetExpiration(usrInptExpr);
cout << "Enter the price per item: $";
getline(cin, usrInptPrcStr);
inDD.str(usrInptPrcStr);
inDD >> usrInptPrc;
inDD.clear();
SetItemPrice(usrInptPrc);
ItemCost = (usrInptPrc * usrInptQnty);
prdc = new Inventory;
prdc->SetName(usrInptName);
prdc->SetQuantity(usrInptQnty);
prdc->SetExpiration(usrInptExpr);
prdc->SetSumInv(usrInptPrc, usrInptQnty);
prdc->SetItemPrice(usrInptPrc);
inventory.push_back(prdc);
return inventory;
}
void AddBookToInventory()
{
}
vector<Inventory*> AddBookToInventory(vector<Inventory*> inventory) {
Inventory* prdct;
string usrInptName = "";
string usrInptQntyStr = "";
istringstream inSS;
int usrInptQnty = 0;
string usrInptAthr = "";
string usrInptPrcStr = "";
int usrInptPrc = 0;
istringstream inDD;
int sum = 0;
int ItemCost = 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();
ItemCost = (usrInptPrc * usrInptQnty);
prdct = new Inventory;
prdct->SetName(usrInptName);
prdct->SetQuantity(usrInptQnty);
prdct->SetSumInv(usrInptPrc, usrInptQnty);
prdct->SetAuthor(usrInptAthr);
prdct->SetItemPrice(usrInptPrc);
inventory.push_back(prdct);
return inventory;
}
void UpdateItemQtyInventory()
{}
//This is the update function in which we can change how many items a certain purchase has
vector<Inventory*> UpdateItemQtyInInventory(vector<Inventory*> inventory) {
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(inventory);
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);
}
return inventory;
}
void RemoveItemFromInventory()
{}
//Here we will be removing an entire item from the inventory
vector<Inventory*> RemoveItemFromInventory(vector<Inventory*> 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()
{
}
protected:
string name;
int quantity;
int priceInDollars ;
int totalCost;
int itemsPrice;
string expiration;
string author;
};
int main() {
vector<Inventory*> INVENTORY;
string usrInptOptn = "default";
string usrInptOptn2 = "default";
Inventory update;
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') {
update.PrintInventory(INVENTORY); //Different!
}
else if (usrInptOptn.at(0) == 'a') {///I don't know what the difference is between the three slashes and the two, but they are different!
cout << "\nEnter (b)ook or (p)roduce: ";
getline(cin, usrInptOptn2);
if (usrInptOptn2.at(0) == 'b') {
INVENTORY = update.AddBookToInventory(INVENTORY); //Supposed to look like: INV = AddItem...(INV);
}
else if (usrInptOptn2.at(0) == 'p') {
INVENTORY = update.AddProduceToInventory(INVENTORY);
}
else
{
continue;
}
}
else if (usrInptOptn.at(0) == 'u') {
INVENTORY = update.UpdateItemQtyInInventory(INVENTORY);
}
else if (usrInptOptn.at(0) == 'r') {
INVENTORY = update.RemoveItemFromInventory(INVENTORY);
}
else if (usrInptOptn.at(0) == 'q') {
cout << "\nGood bye." << endl;
break;
}
}
return 0;
}
Related
I am new to c++ and trying to make an atm. It consits of one file reading user data from files and a main file. Everytime I try to read the output of the returned pointer to the array of structs, where the data is stored, I get strange data. I think there is a problem when assigning strings to the first struct, because when I tried with test values (third file) it worked.
Edit:
I can read out integeres from the strcut, but I have problems with strings.
Here is the code
users.cpp (Creates the struct, included in main.cpp)
#include <fstream>
#include <string>
#include <iostream>
#define STRING_ERROR 4294967295
#define MAX_USERS 100000
using namespace std;
struct user
{
int id;
string firstname;
string name;
int age;
int pin;
};
struct user_container{
int size;
user users [MAX_USERS];
};
typedef struct user User;
typedef struct user_container container;
void print_user_vars(User *user){
cout << "Id: " << user->id << "\nFirstname: " << user->firstname << "\nName: " << user->name << "\nAge: " << user->age << "\nPIN: " << user->pin << endl;
}
int get_usercount(string path){
int usercount = 0;
ifstream file;
string line;
file.open(path, ios::binary | ios::in);
while(true){
getline(file , line);
if(file.fail())
break;
if(line.find("}") != STRING_ERROR){
usercount++;
}
}
file.close();
return usercount;
}
container * get_users(string path){
const int usercount = get_usercount(path);
ifstream file;
string line;
User users[usercount];
const char *values[5] = {"id", "firstname", "name", "age", "pin"};
file.open(path, ios::binary | ios::in);
User proto_user;
int user_num = 0;
while(true){
getline(file , line);
if(file.fail())
break;
if(line.find(":") != STRING_ERROR){
for(int i = 0; i < 5; i++){
if(line.find(values[i]) != STRING_ERROR){
string value;
for(int v = 0; v < line.length(); v++){
if(v > line.find_first_of(":")){
value += line[v];
}
}
if(values[i] == "id"){
proto_user.id = stoi(value);
}
else if(values[i] == "firstname"){
proto_user.firstname = value;
}
else if(values[i] == "name"){
proto_user.name = value;
}
else if(values[i] == "age"){
proto_user.age = stoi(value);
}
else if(values[i] == "pin"){
proto_user.pin = stoi(value);
}
break;
}
}
}
else if(line.find("}") != STRING_ERROR){
//print_user_vars(&proto_user);
users[user_num++] = proto_user;
//cout << "Added user at " << user_num << endl;
}
//cout << line << endl;
}
for(int i = 0; i < user_num; i++){
//cout << "\nUSER: " << i + 1 << endl;
//print_user_vars(&users[i]);
}
static container con;
con.size = usercount;
for(int i = 0; i < usercount; i++){
if(i <= MAX_USERS){
// con.users[i] = users[i] didnt work, but this does
con.users[i].firstname = users[i].firstname;
con.users[i].age = users[i].age;
con.users[i].name = users[i].name;
con.users[i].pin = users[i].pin;
con.users[i].id = users[i].id;
}
}
print_user_vars(&con.users[0]);
return &con;
}
main.cpp (Calls the function)
#include <iostream>
#include "includes/users.h"
using namespace std;
int main(void){
string wasd = "w";
int id;
int pin;
cout << "\n Welcome\n\n ID\n>>> ";
cin >> id;
cout << " PIN\n>>> ";
cin >> pin;
container *con = get_users("users");
int size = con->size;
cout << "Age: " << con->users[0].age << ", PIN: " << con->users[0].pin << ", Firstname: " << con->users[0].firstname << ", Name: "
<< con->users[0].name << ", ID: " << con->users[0].id << endl;
//Functionality
return 0;
}
Simpler.cpp (Just like users.cpp, but with test values, included in main.cpp)
#include <fstream>
#include <string>
#include <iostream>
#define STRING_ERROR 4294967295
#define MAX_USERS 100000
using namespace std;
struct user
{
int id;
string firstname;
string name;
int age;
int pin;
};
struct user_container{
int size;
user users [MAX_USERS];
};
typedef struct user User;
typedef struct user_container container;
container * get_users(string path){
const int usercount = 2;
User users[usercount];
users[0].age = 59;
users[0].firstname = "Peter";
users[0].name = "Bremer";
users[0].id = 456878;
users[0].pin = 1234;
users[1].age = 8;
users[1].firstname = "a";
users[1].name = "b";
users[1].id = 456;
users[1].pin = 1111;
static container con;
con.size = usercount;
for(int i = 0; i < usercount; i++){
if(i <= MAX_USERS){
// con.users[i] = users[i] didnt work, but this does
con.users[i].firstname = users[i].firstname;
con.users[i].age = users[i].age;
con.users[i].name = users[i].name;
con.users[i].pin = users[i].pin;
con.users[i].id = users[i].id;
}
}
cout << "Usercount " << usercount << endl;
return &con;
}
int main(void){
container *con = get_users("users");
int size = con->size;
cout << "Age: " << con->users[0].age << ", PIN: " << con->users[0].pin << ", Firstname: " << con->users[0].firstname << ", Name: "
<< con->users[0].name << ", ID: " << con->users[0].id << endl;
return 0;
}
Not really the answer you are looking for:
Avoid using typedef when you don't need it. Just name your struct User, it will be available under that name without writing struct User.
And for your container, just use one of the STL containers. std::vector<User> would be a good start. This also removes the need for MAX_USERS.
struct User
{
int id;
std::string firstname;
std::string name;
int age;
int pin;
};
typedef std::vector<User> container;
With the three interfaces in user.cpp you can now just use
void print_user_vars(const User& user);
int get_usercount(const std::string& path);
container get_users(const std::string& path);
and thus get rid of the static container con; in get_users.
With a std::vector I no longer see a need for the get_usercount function.
And instead of macros go for constants (and remove magic numbers):
auto const STRING_ERROR = std::string::npos;
(Though I don't agree with the name STRING_ERROR. It's more a STRING_NOT_FOUND.)
Cleanup of print_user_vars after signature change:
void print_user_vars(const User& user)
{
std::cout << "Id: " << user.id << "\nFirstname: " << user.firstname
<< "\nName: " << user.name << "\nAge: " << user.age
<< "\nPIN: " << user.pin << std::endl;
}
And getting some inspiration from get_usercount (a method I don't believe you need):
int get_usercount(const std::string& path)
{
int usercount = 0;
std::ifstream file(path, std::ios_base::binary);
std::string line;
while(std::getline(file, line))
{
if(line.find("}") != STRING_ERROR)
{
usercount++;
}
}
return usercount;
}
This line in get_users is NOT C++. (It's part of the C99 standard):
User users[usercount];
And as #bruno points out:
else if(values[i] == "name"){
does not work. Consider
else if(std::strcmp(values[i], "name") == 0){
#include <iostream>
#include <string>
#include <vector>
class Contact;
class Controller;
class View;
class Contact {
private:
std::string name;
std::string phone;
public:
std::string get_name() {
return name;
}
std::string get_phone() {
return phone;
}
void set_name(std::string name) {
this->name = name;
}
void set_phone(std::string phone) {
this->phone = phone;
}
};
class Controller {
public:
void delete_contact(std::vector<Contact> &data) {
std::cout << "Choose a number from 1 to 3.\n";
std::cout << "1. Delete by id\n";
std::cout << "2. Delete by name\n";
std::cout << "3. Delte by phone\n";
int choice;
std::cin >> choice;
enum { ID = 1, NAME = 2, PHONE = 3 };
if (choice == ID) {
int id;
std::cout << "Enter id: \n";
std::cin >> id;
delete_by_id(data, id);
}
else if (choice == NAME) {
std::string name;
std::cout << "Enter name: \n";
std::cin >> name;
delete_by_name(data, name);
}
else if (choice == PHONE) {
std::string phone;
std::cout << "Enter phone: \n";
std::cin >> phone;
delete_by_phone(data, phone);
}
else {
std::cerr << "Wrong choice.\n";
}
}
void delete_by_id(std::vector<Contact> &data, const int id) {
// valid ids are in range [1 .. data.size()]
if (id < data.size() || id > data.size()) {
std::cerr << "id not found\n";
return;
}
std::cout << "Contact " << id << " deleted successfully\n";
}
void delete_by_name(std::vector<Contact> &data, const std::string name) {
int id = -1;
// assuming unique names
for (int i = 0; i < data.size(); i++) {
if (data[i].get_name() == name) {
id = i;
break;
}
}
if (id == -1) {
std::cerr << "Contact with " << name << " is not found\n";
return;
}
data.erase(data.begin() + id);
}
void delete_by_phone(std::vector<Contact> &data, const std::string phone) {
int id = -1;
for (int i = 0; i < data.size(); i++) {
if (data[i].get_name() == phone) {
id = i;
break;
}
}
if (id == -1) {
std::cerr << "Contact with " << phone << " is not found\n";
return;
}
data.erase(data.begin() + id);
}
void add_contact(Contact new_contact, std::vector<Contact> &data) {
data.push_back(new_contact);
}
void search_contact(std::vector<Contact> &data) {
std::cout << "1. Search by id.\n";
std::cout << "2. Search by name.\n";
std::cout << "3. Search by phone.\n";
enum { ID = 1, NAME = 2, PHONE = 3 };
int choice;
std::cin >> choice;
if (choice == ID) {
int id;
std::cout << "Enter id: \n";
std::cin >> id;
search_by_id(data, id);
}
else if (choice == NAME) {
std::string name;
std::cout << "Enter name: \n";
std::cin >> name;
search_by_name(data, name);
}
else if (choice == PHONE) {
std::string phone;
std::cout << "Enter phone: \n";
std::cin >> phone;
search_by_phone(data, phone);
}
else {
std::cerr << "Wrong choice.\n";
}
}
void search_by_id(std::vector<Contact> &data, int id) {
if (id < data.size() || id > data.size()) {
std::cerr << "Contact not found\n";
return;
}
View v;
v.print_contact_data(data[id]);
}
void search_by_name(std::vector<Contact> &data, const std::string name) {
int id = -1;
for (int i = 0; i < data.size(); i++) {
if (data[i].get_name() == name) {
id = i;
break;
}
}
if (id == -1) {
std::cerr << "Contact not found\n";
return;
}
View v;
v.print_contact_data(data[id]);
}
void search_by_phone(std::vector<Contact> &data, const std::string phone) {
int id = -1;
for (int i = 0; i < data.size(); i++) {
if (data[i].get_phone() == phone) {
id = i;
break;
}
}
if (id == -1) {
std::cerr << "Contact not found\n";
return;
}
View v;
v.print_contact_data(data[id]);
}
void edit_contact(std::vector<Contact> &data) {
std::cout << "Enter contact id\n";
int id;
std::cin >> id;
if (id < data.size() || id > data.size()) {
std::cerr << "Sorry, wrong id\n";
}
std::cout << "Do you want to edit this contact? [Y, N]\n";
View v;
v.print_contact_data(data[id]);
std::string choice;
std::cin >> choice;
if (choice.front() == 'Y') {
std::cout << "Enter new name:\n";
std::string name;
std::cin >> name;
data[id].set_name(name);
std::cout << "Enter new phone:\n";
std::string phone;
std::cin >> phone;
data[id].set_phone(phone);
std::cout << "Done\n";
}
else {
std::cerr << "Wrong choice.\n";
}
}
};
class View {
public:
std::vector<Contact> data;
void print_contact_data(Contact data) {
std::cout << data.get_name() << ' ' << data.get_phone() << '\n';
}
void print_all_contacts() {
int curr = 1;
for (auto x : data)
std::cout << curr++ << ". " << x.get_name()
<< ' ' << x.get_phone() << '\n';
}
Contact get_contact_data() {
Contact data;
std::cout << "Enter contact name:\n";
std::string name;
std::cin >> name;
std::cout << "Enter contact phone:\n";
std::string phone;
std::cin >> phone;
data.set_name(name);
data.set_phone(phone);
return data;
}
void main_menu() {
enum { ADD = 1, DELETE = 2, EDIT = 3,
SEARCH = 4, PRINT = 5, EXIT = 6 };
std::cout << "1. Add contact\n";
std::cout << "2. Delete contact\n";
std::cout << "3. Edit contact\n";
std::cout << "4. Search contact\n";
std::cout << "5. Print all contacts\n";
std::cout << "6. Exit\n";
int choice;
std::cin >> choice;
Controller temp;
if (choice == ADD) {
temp.add_contact(get_contact_data(), data);
} else if (choice == DELETE) {
temp.delete_contact(data);
} else if (choice == EDIT) {
temp.edit_contact(data);
} else if (choice == SEARCH) {
temp.search_contact(data);
} else if (choice == PRINT) {
print_all_contacts();
} else if (choice == EXIT) {
exit(0);
} else {
std::cout << "Wrong choice\n";
}
}
};
int main() {
View v;
v.main_menu();
return 0;
}
I've tried to implement MVC design pattern. Basically, this is a basic contact management system. One can add, delete, edit, search contacts. View class is responsible for user manipulation and interacts with the user. The contact class is just the model. I'm getting this error message "'View v' has incomplete type and cannot be defined". I've searched for some solutions but couldn't find what my error is.
You have the following code structure:
class Contact;
class Controller;
class View;
class Controller {
public:
// ...
void search_by_id(std::vector<Contact> &data, int id) {
// ...
View v;
// ...
}
// ...
};
class View {
public:
// ...
void main_menu() {
// ...
Controller temp;
// ...
}
// ...
};
This gives an error because View v; requires View to be defined. Moving the definition of View to before Controller won't solve the issue because Controller temp; would have the same issue.
The simple fix is to move all the function definitions outside the class, and after the other classes have been defined:
class Controller {
public:
// ...
void search_by_id(std::vector<Contact> &data, int id);
// ...
};
class View {
public:
// ...
void main_menu();
// ...
};
void View::main_menu() {
// ...
Controller temp;
// ...
}
void Controller::search_by_id(std::vector<Contact> &data, int id) {
// ...
View v;
// ...
}
I am unsure about why I am getting this error message when I hover over purchaseArray in my string Customer::save() method in the customer.cpp file:
identifier is undefined
And this error message when I hover over getline in the void Customer::parse(string line) method in the customer.cpp file:
no instance of overloaded function "getline" matches the argument list argument types are: (std::stringstream, int, char)
Code in the Customer.cpp file:
#include "Customer.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include<utility>
using namespace std;
//default constructor
Customer::Customer() {
}
//Full constructor
Customer::Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type)
{
this->customerID = customerID;
this->title = title;
this->name = name;
this->numOfPurchases = numOfPurchases;
purchases = new int[3];
purchases[0] = purchase1;
purchases[1] = purchase2;
purchases[2] = purchase3;
this->type = type;
}
Customer::Customer(const Customer& source) //copy constructor
{
cout << "copy constructor called" << endl;
this->customerID = source.customerID;
this->title = source.title;
this->name = source.name;
this->numOfPurchases = source.numOfPurchases;
this->purchases = new int[3];
purchases[0] = source.purchases[0];
purchases[1] = source.purchases[1];
purchases[2] = source.purchases[2];
this->type = source.type;
}
//overloaded assignment operator=
Customer& Customer::operator= (Customer& otherCustomer)
{
cout << "Overloaded assignment operator= called" << endl;
//self-assignment guard
if (this == &otherCustomer)
return *this; //refernce to the same object
// copy data from the source (rhs) to this object (the destination)
name = otherCustomer.name;
//must make a new scores object to store a copy of the other student
if (purchases != nullptr)
delete[] purchases;
purchases = new int[3];
for (int i = 0; i < 3; i++) {
purchases[i] = otherCustomer.purchases[i];
}
//return this existing object so we can chain this operator
return *this;
}
string Customer::save()
{
stringstream out;
out << this->customerID << ";";
out << this->title << ";";
out << this->name << ";";
out << this->numOfPurchases << ";";
int* purchases = 0;
purchases = purchases | (purchaseArray[0] << 24);
purchases = purchases | (purchaseArray[1] << 16);
purchases = purchases | (purchaseArray[2] << 8);
out << this->type << ";";
out.flush();
return out.str();
}
void Customer::parse(string line)
{
stringstream in(line);
string customerIDLine;
getline(in, customerIDLine, ';');
customerID = stoi(customerIDLine);
getline(in, title, ';');
getline(in, name, ';');
int numOfPurchases;
getline(in, numOfPurchases, ';');
int s = stoi(numOfPurchases);
purchasesArray[0] = (s & (255 << 16)) >> 16;
purchasesArray[1] = (s & (255 << 8)) >> 8;
purchasesArray[2] = s & 255;
getline(in, type, ';');
}
Customer::~Customer() {
cout << "Destructor ~Customer called" << endl;
delete[] purchases;
}
// Overloaded insertion operator (Outputs Character object data as an output stream)
// Defined in header file as a "friend" function, as it is not a member function
//
ostream& operator<<(ostream& out, Customer& customer)
{
cout << "Customer details ( output by insertion operator<< )" << endl;
cout << "Customer ID: " << customer.customerID << endl;
cout << "Title: " << customer.title << endl;
cout << "Name: " << customer.name << endl;
cout << "Number of purchases: " << customer.numOfPurchases << endl;
cout << "Purchases: ";
for (int i = 0; i < 3; i++)
{
if (i > 0) cout << ",";
cout << customer.purchases[i];
}
cout << "Type: " << customer.type << endl;
return out;
}
istream& operator>> (istream& in, Customer& customer)
{
cout << "Enter Customer details ( using the extraction operator>> )" << endl;
cout << "Enter Customer ID: " << endl;
cin >> customer.customerID;
cout << "Enter Title: " << endl;
getline(cin, customer.title);
cout << "Enter Name: " << endl;
getline(cin, customer.name);
cout << "Enter Number of Purchases: ";
cin >> customer.numOfPurchases;
cout << "Enter Purchases: ";
cin >> customer.purchases[0];
cin >> customer.purchases[1];
cin >> customer.purchases[2];
cout << "Enter Type";
getline(cin, customer.type);
cout << endl;
return in;
}
int Customer::getCustomerID()
{
return customerID;
}
string Customer::getTitle()
{
return title;
}
string Customer::getName()
{
return name;
}
int Customer::getNumOfPurchases()
{
return numOfPurchases;
}
int* Customer::getPurchases()
{
return purchases;
}
string Customer::getType()
{
return type;
}
void Customer::setCustomerID(int customerID)
{
if (customerID < 1) {
cout << "Customer ID has to be equal to 1 or more" << endl; //Changed all the "throw invalid_argument" messages to cout as they were causing an issue with my main.cpp file and an abort message kept appearing every time I ran my main.cpp file.
}
this->customerID = customerID;
}
void Customer::setTitle(string title)
{
if (title.length() < 2) {
cout << "Title has to be more than or equal to 2 characters" << endl;
}
this->title = title;
}
void Customer::setName(string name)
{
if (name.length() < 4) {
cout << "Length of name should be more than or equal to 4 characters" << endl;
}
this->name = name;
}
//Got help ith this on stack overflow as I was using "&&" instead of using "||" for the if statement
void Customer::setNumOfPurchases(int numOfPurchases)
{
if(numOfPurchases <0 || numOfPurchases > 10000){
cout << "Number of purchases should be between 0 to 10000" << endl;
}
this->numOfPurchases = numOfPurchases;
}
void Customer::setPurchases(int purchase1, int purchase2, int purchase3)
{
if (purchase1 < 0 || purchase2 < 0 || purchase3 < 0) {
cout << "Purchases must be more than or equal to zero" << endl;
}
}
//Got help from stack overflow on comparing strings as I originally didnt use "type.compare"
void Customer::setType(string type) {
if (type.compare("New") !=0 || type.compare("Either") !=0) {
cout << "Type of purchase has to be New or Either" << endl;
}
}
Code in the Customer.h file:
#pragma once
#include<iostream>
using namespace std;
#include<string>
class Customer
{
private:
int customerID;
string title;
string name;
int numOfPurchases;
int* purchases;
string type;
public:
Customer(); // default constructor
Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type);
//copy overload assignment
Customer& operator=(Customer& otherCustomer);
Customer(const Customer& source);
string save();
void parse(string line);
~Customer(); //destructor
//Getters and Setters
void setCustomerID(int customerID);
void setTitle(string title);
void setName(string name);
void setNumOfPurchases(int numOfPurchases);
void setPurchases(int purchase1, int purchase2, int purchase3);
void setType(string type);
int getCustomerID();
string getTitle();
string getName();
int getNumOfPurchases();
int* getPurchases();
string getType();
void printCustomer() {
cout << customerID << "," << title << "," << name << "," << numOfPurchases << "," << purchases << "," << type << endl;
}
friend std::ostream& operator<<(std::ostream& out, Customer& customer); // overloaded operator<<
friend istream& operator>> (istream& in, Customer& customer); // overloaded operator >>
};
Code from the Main.cpp file:
// Repeat_Assessment_C++_AislingSmith.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include "Customer.h"
using namespace std;
void OutputFileStream();
void parseLine(const string& str);
void InputFileStream();
void save(vector<Customer> customers);
void load(vector<Customer>& customers);
void addCustomer(vector<Customer>& vect);
//void printActions();
void OutputFileStream()
{
cout << "Creating and writing to file: Customer.txt" << endl;
ofstream outStream("customers.txt"); // write mode (overwrites existing data)
if (outStream.good())
{
int customerID = 150033;
outStream << "This is a line of text.\n";
outStream << "This is another line of text.\n";
outStream << "This is a line of text.\n";
int numOfPurchases = 4;
int purchases = 0;
outStream << customerID << "Mr" << "Jack" << "New" << numOfPurchases << purchases << endl;
outStream.close(); // close file
cout << "File written.\n" << endl;
}
else
cout << "Unable to open file";
}
void parseLine(const string& str) {
stringstream strStream(str); //create string stream from the string
// int customerID;
string title;
string name;
string type;
//int numOfPurchases;
//int purchases;
string s;
int customerID = 150033;
getline(strStream, s, ';');
customerID = stoi(s);
getline(strStream, title, ';');
getline(strStream, name, ';');
getline(strStream, type, ';');
int numOfPurchases = 4;
getline(strStream, s, ';');
numOfPurchases = stoi(s);
int purchases = 0;
getline(strStream, s, ';');
purchases = stoi(s);
int* purchasesArray = new int[3];
purchasesArray[0] = (purchases & (255 << 16)) >> 16;
purchasesArray[1] = (purchases & (255 << 8)) >> 8;
purchasesArray[2] = purchases & 255;
for (int i = 0; i < 3; i++)
{
int purchasesArray[3];
}
cout << " CustomerID: " << customerID << "Title:" << title << " Name: " << name << " Type:" << type << " Number of Purchases: " << numOfPurchases << "Purchases: " << purchases << endl;
}
void InputFileStream() {
cout << "Reading from a semi-colon delimited txt file" << endl;
string line;
ifstream inStream("customers.txt"); //opens file as an input file stream
if (inStream.good()) //if the file is opened successfully and not empty
{
while (getline(inStream, line)) //reads line until false return
{
parseLine(line);
}
inStream.close();
}
else
cout << "unable to open file or the file is empty!";
}
void save(vector<Customer> customers)
{
ofstream out("customers.txt");
if(out)
{
for (Customer& c : customers)
{
out << c.save();
}
out.flush();
out.close();
}
else
{
cout << "Error Writing to File" << endl;
}
}
void load(vector<Customer>& customers)
{
ifstream in("customers.txt");
if (in) {
string line;
while (!in.eof())
{
getline(in, line);
if (line != "")
{
Customer c;
c.parse(line);
customers.push_back(c);
}
}
}
}
void addCustomer(vector<Customer>& customers) {
Customer customer;
cin >> customer;
customers.push_back(customer);
}
int main()
{
InputFileStream();
vector<Customer> customers;
Customer c;
Customer cust1;
cust1.setCustomerID(150032);
cust1.setTitle("Mr");
cust1.setName("Joey");
cust1.setNumOfPurchases(3);
cust1.setPurchases(366, 352, 334);
cust1.setType("New");
cout << cust1.getCustomerID() << endl;
cout << cust1.getTitle() << endl;
cout << cust1.getName() << endl;
cout << cust1.getNumOfPurchases() << endl;
cout << cust1.getPurchases() << endl;
cout << cust1.getType() << endl;
return 0;
}
First Problem
The first error is pretty clear, purchaseArray is nowhere defined (at least not in the code you show here) and you probably meant just purchases or this->purchases? Allthough I got no clue what you tried to achieve with the int *purchases there.
Second Problem
The second one occurs, because the way you try to read an integer from a stream is flawed.
It's about this piece of code from Customer::parse
int numOfPurchases; // declare int
getline(in, numOfPurchases, ';'); // error, second parameter must be std::string!
int s = stoi(numOfPurchases); // numOfPurchases is already an int
You probably wanted this:
std::string numOfPurchasesBuf; // temporary buffer
getline(in, numOfPurchasesBuf, ';'); // read data to string
int s = stoi(numOfPurchasesBuf); // convert to int
and since all of those lines read some member variable you probably want to set this one as well:
this->numOfPurchases = s;
I've spent pretty much all day trying to do this, I understand pointers and what a linked list does, but I don't know how to actually code it and all I've found are Java and C examples which don't help because I'm using C++.
Thanks in advance for taking a look at my code and helping me, I really appreciate it considering how many days I've spent stressed out and confused about this. I'm not going to lie so far most of my deleteNode function is probably trash. But like I've said I'm just lost I don't even know where to start or how to progress because I only understand the concepts.
This is my data file.
John Doe 80
Jane Smith 70
Bill Jones 50
Pat Hughes 90
Sam Sosa 40
This is my Header file
#include<string>
using namespace std;
class student {
public:
student(); // constructor method
void st_fn(string fn);
string st_fn();
void st_ln(string ln);
string st_ln();
void st_score(float s);
float st_score();
string st_pass_or_fail();
// need a pointer to the next object
student *nxt_ptr;
protected: // protected can be inherited
float m_score;
string m_ln;
string m_fn;
string m_pf_msg;
};
student::student() //constructor
{
nxt_ptr = NULL;
m_score = 0;
}
void student::st_fn(string fn)
{
m_fn = fn;
}
string student::st_fn()
{
return m_fn;
}
void student::st_ln(string ln)
{
m_ln = ln;
}
string student::st_ln()
{
return m_ln;
}
void student::st_score(float s)
{
m_score = s;
}
float student::st_score()
{
return m_score;
}
string student::st_pass_or_fail()
{
if (m_score >= 60)
m_pf_msg = "PASSED";
else
m_pf_msg = "FAILED";
return m_pf_msg;
}
This is my .cpp file.
#include<iostream>
#include<string>
#include<fstream>
#include "Header.h"
using namespace std;
int display_menu()
{
int option;
cout << endl << endl;
cout << "1. Display List" << endl;
cout << "2. Add a student" << endl;
cout << "3. Delete first student" << endl;
cout << "4. Search by Last Name" << endl;
cout << "5. Exit" << endl;
cin >> option;
return option;
}
student * search_last_name(student *h)
{
student *f = NULL;
student *t = NULL;
string s_ln;
// prompt for last name to search for
cout << "Enter Last Name of the Student";
cin >> s_ln;
if (h != NULL)
{
t = h;
while (t != NULL)
{
if (t->st_ln() == s_ln)
f = t; // found the last name so save t
t = t->nxt_ptr;
}
}
else
cout << "List is empty" << endl;
return f;
}
void add_student(student *&head) // h is the head of the list
{
student *new_st, *r;
string fn, ln;
float s;
cout << "Enter new students first name, last name and score";
cin >> fn >> ln >> s;
// instantiate a new node, use new_st
new_st = new student;
new_st->st_fn(fn);
new_st->st_ln(ln);
new_st->st_score(s);
if (head == NULL)
head = new_st;
else
{
// find the last node, use r for this
// write code
r = head;
while (r->nxt_ptr != nullptr)
r = r->nxt_ptr;
// add to the back of the list
// write code
r->nxt_ptr = new_st;
} // end of else
} // end of add student
student * delete_front(student * head)
{
student *t;
// delete front node
// check for empty list
if (head != NULL)
{
// delete first node
t = head;
head = head->nxt_ptr;
delete(t);
}
else
cout << "List is empty - nothing to delete" << endl;
return head;
}
void deleteNode(struct Node *head, struct Node *n)
{
// When node to be deleted is head node
if (head == n)
{
n = head->next;
//Remove the link of next node
head->next = head->next->next;
return;
}
//When not first node, folow the normal deletion process
//Find the previous node
struct Node *prev = head;
while (prev->next != NULL && prev->next != n)
prev = prev->next;
// Check if node really exists in Linked List
if (prev->next == NULL)
{
cout << endl << "Given node is not present in Linked List";
return;
}
//Remove node from linked list should it exist
prev->next = prev->next->next;
return;
}
void display_list(student *t)
{
if (t == NULL)
cout << "List is Empty!";
else
{
while (t != NULL)
{
cout << "******Student******" << endl;
cout << t->st_ln() << endl;
cout << t->st_fn() << endl;
cout << t->st_score() << endl << endl;
t = t->nxt_ptr;
}
}
}
int main()
{
string ln, fn;
float s;
int n;
ifstream infile;
student *head = NULL; //pointer to a student object
student *cp = NULL; // pointer to end of the list
student *new_st = NULL; // pointer to a new student object
student *f = NULL; // pointer to found node
int option; // the numbe of menu item the user selects
infile.open("lab8d.txt");
while (!infile.eof())
{
infile >> fn >> ln >> s;
//instantiate a student object
new_st = new student;
//load the object with data
new_st->st_fn(fn);
new_st->st_ln(ln);
new_st->st_score(s);
// check for empty list - its a special case
if (head == NULL)
{
head = new_st;
cp = new_st;
}
else // list is not empty
{
cp->nxt_ptr = new_st;
cp = new_st;
}
} // end of loop
// loop to give the user some options
option = display_menu();
while (option != 5)
{
if (option == 1)
display_list(head);
else if (option == 2)
add_student(head);
else if (option == 3)
head = delete_front(head);
else if (option == 4)
{
f = search_last_name(head);
if (f != NULL)
{
cout << f->st_fn() << endl;
cout << f->st_ln() << endl;
cout << f->st_score() << endl;
cout << f->st_pass_or_fail() << endl;
}
else
cout << "Name not in the list" << endl;
}
else if (option == 6)
{
cout << "Enter the number of the node you would like to delete: " << endl;
cin >> n;
}
option = display_menu();
}
system("pause");
return 0;
}
The simpler and self-contained your functions are, the easier they are to test and debug, and the less like they are to fail.
Try something more like this:
Student.h:
#include <string>
class student_list;
class student
{
public:
student();
student(const std::string &fn, const std::string &ln, float s, student *nxt = NULL);
void next(student *s);
student* next() const;
void firstName(const std::string &fn);
std::string firstName() const;
void lastName(const std::string &ln);
std::string lastName() const;
void score(float s);
float score() const;
std::string pass_or_fail() const;
void display(bool showPassOrFail = false) const;
friend class student_list;
protected: // protected can be inherited
student *m_next;
std::string m_fn;
std::string m_ln;
float m_score;
};
Student.cpp:
#include "Student.h"
#include <iostream>
student::student()
: m_next(NULL), m_score(0)
{
}
student::student(const std::string &fn, const std::string &ln, float s, student *nxt)
: m_next(nxt), m_fn(fn), m_ln(ln), m_score(s)
{
}
void student::next(student *s)
{
m_next = s;
}
student* student::next() const
{
return m_next;
}
void student::firstName(const std::string &fn)
{
m_fn = fn;
}
std::string student::firstName() const
{
return m_fn;
}
void student::lastName(const std::string &ln)
{
m_ln = ln;
}
std::string student::lastName() const
{
return m_ln;
}
void student::score(float s)
{
m_score = s;
}
float student::score() const
{
return m_score;
}
std::string student::pass_or_fail() const
{
if (m_score >= 60)
return "PASSED";
else
return "FAILED";
}
void student::display(bool showPassOrFail) const
{
std::cout << lastName() << std::endl;
std::cout << firstName() << std::endl;
std::cout << score() << std::endl;
if (showPassOrFail)
std::cout << pass_or_fail() << std::endl;
}
StudentList.h:
#include <string>
class student;
class student_list
{
public:
student_list();
~student_list();
student* search_last_name(const std::string &ln);
student* insert(const std::string &fn, const std::string &ln, float s, student* after = NULL);
bool remove(int idx);
void display() const;
private:
student *m_head;
};
StudentList.cpp:
student_list::student_list()
: m_head(NULL)
{
}
student_list::~student_list()
{
while (m_head)
remove(0);
}
student* student_list::search_last_name(const std::string &ln)
{
student *t = m_head;
while (t)
{
if (t->lastName() == ln)
break; // found the last name
t = t->next();
}
return t;
}
student* student_list::insert(const std::string &fn, const std::string &ln, float s, student* after)
{
student **r;
if (after)
{
// add to list after the specified node
// get pointer to next node
r = &(after->m_next);
}
else
{
// add to the back of the list
// find pointer to last node
r = &m_head;
while (*r)
r = &((*r)->m_next);
}
// instantiate a new node
student *new_st = new student(fn, ln, s);
if (after)
new_st->next(*r);
// add to list
*r = new_st;
return new_st;
}
bool student_list::remove(int idx)
{
// delete a node at index
// find pointer to node
student **r = &m_head;
while ((*r) && (idx-- > 0))
r = &((*r)->m_next);
if (*r)
{
// delete node
student *t = *r;
*r = t->next();
delete t;
return true;
}
return false;
}
void student_list::display() const
{
student *t = m_head;
if (!t)
std::cout << "List is Empty!" << std::endl;
else
{
do
{
std::cout << "******Student******" << std::endl;
t->display();
t = t->next();
}
while (t);
}
}
Main.cpp:
#include "Student.h"
#include "StudentList.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <limits>
#include <cstdlib>
int read_number()
{
int value;
while (!(std::cin >> value))
{
std::cout << "Must be a number, try again: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return value;
}
int display_menu()
{
int option;
std::cout << std::endl << std::endl;
std::cout << "1. Display List" << std::endl;
std::cout << "2. Add a student" << std::endl;
std::cout << "3. Delete first student" << std::endl;
std::cout << "4. Search by Last Name" << std::endl;
std::cout << "5. Delete student by index" << std::endl;
std::cout << "6. Exit" << std::endl << std::endl;
std::cout << "Choice: ";
do
{
option = read_number();
if ((option >= 1) && (option <= 6))
break;
std::cout << "Must be 1..6, try again: ";
}
while (true);
return (option != 6) ? option : -1;
}
int main()
{
student_list students;
std::ifstream infile("lab8d.txt");
if (infile.is_open())
{
student *cp = NULL;
std::string ln, fn;
float s;
while (infile >> fn >> ln >> s)
cp = students.insert(fn, ln, s, cp);
infile.close();
}
// loop to give the user some options
int option; // the number of menu item the user selects
while ((option = display_menu()) != -1)
{
switch (option)
{
case 1:
{
students.display();
break;
}
case 2:
{
// prompt for student info
std::string info;
std::cout << "Enter new student's first name, last name, and score: ";
std::string ln, fn;
float s;
if (std::cin >> fn >> ln >> s)
students.insert(fn, ln, s);
break;
}
case 3:
{
if (!students.remove(0))
std::cout << "List is empty" << std::endl;
break;
}
case 4:
{
// prompt for last name to search for
std::string ln;
std::cout << "Enter Last Name of the Student: ";
if (std::cin >> ln)
{
student *f = students.search_last_name(ln);
if (f)
f->display(true);
else
std::cout << "Name not found in List" << std::endl;
}
break;
}
case 5:
{
std::cout << "Enter the index of the Student to Delete: " << std::endl;
int idx = read_number();
if (!students.remove(idx))
std::cout << "Index not found in List" << std::endl;
break;
}
}
}
std::system("pause");
return 0;
}
That being said, you really should be using the std::list container instead, eg:
Student.h:
#include <string>
class student_list;
class student
{
public:
student();
student(const std::string &fn, const std::string &ln, float s);
void firstName(const std::string &fn);
std::string firstName() const;
void lastName(const std::string &ln);
std::string lastName() const;
void score(float s);
float score() const;
std::string pass_or_fail() const;
void display(bool showPassOrFail = false) const;
friend class student_list;
protected: // protected can be inherited
std::string m_fn;
std::string m_ln;
float m_score;
};
Student.cpp:
#include "Student.h"
#include <iostream>
student::student()
: m_score(0)
{
}
student::student(const std::string &fn, const std::string &ln, float s)
: m_fn(fn), m_ln(ln), m_score(s)
{
}
void student::firstName(const std::string &fn)
{
m_fn = fn;
}
std::string student::firstName() const
{
return m_fn;
}
void student::lastName(const std::string &ln)
{
m_ln = ln;
}
std::string student::lastName() const
{
return m_ln;
}
void student::score(float s)
{
m_score = s;
}
float student::score() const
{
return m_score;
}
std::string student::pass_or_fail() const
{
if (m_score >= 60)
return "PASSED";
else
return "FAILED";
}
void student::display(bool showPassOrFail) const
{
std::cout << lastName() << std::endl;
std::cout << firstName() << std::endl;
std::cout << score() << std::endl;
if (showPassOrFail)
std::cout << pass_or_fail() << std::endl;
}
Main.cpp:
#include "Student.h"
#include <list>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <limits>
#include <algorithm>
#include <cstdlib>
int read_number()
{
int value;
while (!(std::cin >> value))
{
std::cout << "Must be a number, try again: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return value;
}
int display_menu()
{
int option;
std::cout << std::endl << std::endl;
std::cout << "1. Display List" << std::endl;
std::cout << "2. Add a student" << std::endl;
std::cout << "3. Delete first student" << std::endl;
std::cout << "4. Search by Last Name" << std::endl;
std::cout << "5. Delete student by index" << std::endl;
std::cout << "6. Exit" << std::endl << std::endl;
std::cout << "Choice: ";
do
{
option = read_number();
if ((option >= 1) && (option <= 6))
break;
std::cout << "Must be 1..6, try again: ";
}
while (true);
return (option != 6) ? option : -1;
}
int main()
{
std::list<student> students;
std::ifstream infile("lab8d.txt");
if (infile.is_open())
{
std::string ln, fn;
float s;
while (infile >> fn >> ln >> s)
students.push_back(student(fn, ln, s));
infile.close();
}
// loop to give the user some options
int option; // the number of menu item the user selects
while ((option = display_menu()) != -1)
{
switch (option)
{
case 1:
{
if (students.empty())
std::cout << "List is Empty!" << std::endl;
else
{
for(const auto &s : students)
{
std::cout << "******Student******" << std::endl;
s.display();
}
}
break;
}
case 2:
{
// prompt for student info
std::string info;
std::cout << "Enter new student's first name, last name, and score: ";
std::string ln, fn;
float s;
if (std::cin >> fn >> ln >> s)
students.push_back(student(fn, ln, s));
break;
}
case 3:
{
if (students.empty())
std::cout << "List is empty" << std::endl;
else
students.erase(students.begin());
break;
}
case 4:
{
// prompt for last name to search for
std::string ln;
std::cout << "Enter Last Name of the Student: ";
if (std::cin >> ln)
{
auto f = std::find(students.begin(), students.end(),
[&](const student &s){ return (s.lastName() == ln); }
);
if (f != students.end())
f->display(true);
else
std::cout << "Name not found in List" << std::endl;
}
break;
}
case 5:
{
std::cout << "Enter the index of the Student to Delete: " << std::endl;
int idx = read_number();
if ((idx < 0) || (idx >= students.size()))
std::cout << "Index not found in List" << std::endl;
else
students.erase(std::next(students.begin(), idx));
break;
}
}
}
std::system("pause");
return 0;
}
I currently have a main.cc and a database.cc file that work perfectly, but my main.cc file does not match the one that it is going to be tested with. I've tried to convert it but it keeps throwing errors and I don't have the time to break my whole code and start again.
This is my database.cc file:
#include<list>
#include<algorithm>
#include<iostream>
#include<string>
#include<fstream>
#ifndef passenger_h
#define passenger_h
using std::string;
using std::cin;
using std::cout;
using std::list;
using std::endl;
class Passenger {
public:
Passenger() {}
Passenger(string, string, string);
bool operator==(const Passenger&) const;
bool operator<(const Passenger&) const;
void print(std::ostream& os);
private:
string fname, lname, destination;
};
class Flightlist {
public:
int menu();
void read_from_file(string);
void insert(Passenger p);
void remove(Passenger p);
bool check_reservation(Passenger p);
void display_list();
void save_to_file(string);
private:
list<Passenger> flist;
};
#endif
Passenger::Passenger(string first, string last, string dest)
{
fname = first;
lname = last;
destination = dest;
}
bool Passenger::operator==(const Passenger& p) const
{
return fname == p.fname && lname == p.lname;
}
bool Passenger::operator<(const Passenger& p) const
{
return fname < p.fname || (fname == p.fname && lname < p.lname);
}
void Passenger::print(std::ostream& os)
{
os << fname << ' ' << lname << ' ' << destination << '\n';
}
int Flightlist::menu()
{
int option;
cout << endl;
cout << "Enter one of the following options:" << endl;
cout << "1. load reservations from file:" << endl;
cout << "2. reserve a ticket" << endl;
cout << "3. cancel a reservation" << endl;
cout << "4. check reservation" << endl;
cout << "5. display passenger list" << endl;
cout << "6. save passenger list" << endl;
cout << "7. exit" << endl << endl;
cin >> option;
cin.get();
return option;
}
void Flightlist::read_from_file(string filename)
{
string fname, lname, destination;
std::ifstream input(filename.c_str());
while (input >> fname >> lname >> destination)
{
flist.push_back(Passenger(fname, lname, destination));
}
input.close();
}
void Flightlist::insert(Passenger p)
{
flist.push_back(p);
}
void Flightlist::remove(Passenger p)
{
flist.remove(p);
}
bool Flightlist::check_reservation(Passenger p)
{
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
return flist.end() != find(flist.begin(), flist.end(), p);
}
void Flightlist::display_list()
{
flist.sort();
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
for ( ; i1 != i2; ++i1) {
i1->print(cout);
}
}
void Flightlist::save_to_file(string filename)
{
flist.sort();
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
std::ofstream output(filename.c_str());
for ( ; i1 != i2; ++i1) {
i1->print(output);
}
output.close();
}
This is my current main.cc file, which works perfectly with the above program:
#include "database.cc"
int main()
{
Flightlist flight_list;
string fname, lname, destination;
while (true)
{
switch (flight_list.menu())
{
case 1:
{
flight_list.read_from_file("ticket_reservations.dat");
break;
}
case 2:
{
cout << "first name of passenger:" << endl;
cin >> fname;
cout << "last name of passenger" << endl;
cin >> lname;
cout << "destination of passenger" << endl;
cin >> destination;
flight_list.insert(Passenger(fname, lname, destination));
break;
}
case 3:
{
cout << "first name of passenger:" << endl;
cin >> fname;
cout << "last name of passenger" << endl;
cin >> lname;
cout << "destination of passenger" << endl;
cin >> destination;
flight_list.remove(Passenger(fname, lname, destination));
break;
}
case 4:
{
cout << "first name of passenger:" << endl;
cin >> fname;
cout << "last name of passenger" << endl;
cin >> lname;
cout << "destination of passenger" << endl;
cin >> destination;
if (flight_list.check_reservation(Passenger(fname, lname, destination)))
cout << "this passenger has a ticket reservation" << endl;
else
cout << "this passenger does not have a ticket reservation" << endl;
break;
}
case 5:
{
flight_list.display_list();
break;
}
case 6:
{
flight_list.save_to_file("ticket_reservations.dat");
}
break;
case 7:
return 0;
}
}
return 0;
}
This is the main.cc file that my program will be tested with, and therefore what I need to convert my code to be compatible with:
#include "database.cc"
int main()
{
list<Passenger> flight_list;
string first_name, last_name, destination;
while (true)
{
switch (menu())
{
case 1:
{
read_from_file(flight_list, "ticket_reservations.dat");
break;
}
case 2:
{
cout << "name of passenger:" << endl;
cin >> first_name >> last_name;
cout << "destination:" << endl;
cin.ignore();
getline(cin, destination);
insert(flight_list, first_name, last_name, destination);
break;
}
case 3:
{
cout << "name of passenger:" << endl;
cin >> first_name >> last_name;
remove(flight_list, first_name, last_name);
break;
}
case 4:
{
cout << "name of passenger:" << endl;
cin >> first_name >> last_name;
if (check_reservation(flight_list, first_name, last_name))
cout << "this passenger has a ticket reservation" << endl;
else
cout << "this passenger does not have a ticket reservation" << endl;
break;
}
case 5:
{
display_list(flight_list);
break;
}
case 6:
{
save_to_file(flight_list, "ticket_reservations.dat");
}
break;
case 7:
return 0;
}
}
return 0;
}
I strongly apologise for the large amount of code, but I desperately need help with this. Thank you!
Your functions are not working because you have never defined them as general functions; they are class function members.
You need to iterate through your list and call the class member - I'm not going to rewrite all your code, but here's an illustration:
list<MyClass> MyList;
// ... your list is populated here ..
for(auto iter=MyList.begin(); iter!=MyList.end(); ++iter) {
// ... decide what to do here ...
*iter->MyMethod(argument1,argument2)
// ... etc ...
}
Note I'm calling MyMethod as a class member, not as a function (iter,first. You'll need to adjust your code to call your methods this way too, meaning you need to go through your list outside of the class instance.
The important bit to grasp is that you use . (or -> if you're accessing it through a pointer) to access your function member; you can't call it directly as a function.
The only other option you have is to add wrapper functions to your database.cc, defining the functions you're trying to call in your new main.cc.
Here is a new Database.cc that seems to compile.
It seems that the test main.cc calls free functions so I created new objects in every function stub.
And I added a constructor to Flightlist for list.
// #include "stdafx.h" // uncomment for MS version
#include<list>
#include<algorithm>
#include<iostream>
#include<string>
#include<fstream>
#ifndef passenger_h
#define passenger_h
using std::string;
using std::cin;
using std::cout;
using std::list;
using std::endl;
class Passenger {
public:
Passenger() {}
Passenger(string, string, string);
bool operator==(const Passenger&) const;
bool operator<(const Passenger&) const;
void print(std::ostream& os);
private:
string fname, lname, destination;
};
class Flightlist {
public:
int menu();
void read_from_file(string);
void insert(Passenger p);
void remove(Passenger p);
bool check_reservation(Passenger p);
void display_list();
void save_to_file(string);
// --- CHANGES START ----------------
Flightlist() {};
~Flightlist() {};
Flightlist(list<Passenger> flistInput) : flist(flistInput){};
private:
list<Passenger> flist;
};
int menu() {
static Flightlist FL;
return FL.menu();
}
void read_from_file(list<Passenger> flist, string s) {
Flightlist FL(flist);
FL.read_from_file(s);
}
void insert(list<Passenger> flist, string first, string last, string dest) {
Flightlist FL(flist);
Passenger p(first, last, dest);
FL.insert(p);
}
void remove(list<Passenger> flist, string first, string last) {
Flightlist FL(flist);
Passenger p(first, last, NULL);
FL.remove(p);
}
bool check_reservation(list<Passenger> flist, string first, string last) {
Flightlist FL(flist);
Passenger p(first, last, NULL);
return FL.check_reservation(p);
}
void display_list(list<Passenger> flist) {
Flightlist FL(flist);
FL.display_list();
}
void save_to_file(list<Passenger> flist, string s) {
Flightlist FL(flist);
FL.save_to_file(s);
}
// --- CHANGES STOP ----------------
#endif
Passenger::Passenger(string first, string last, string dest)
{
fname = first;
lname = last;
destination = dest;
}
bool Passenger::operator==(const Passenger& p) const
{
return fname == p.fname && lname == p.lname;
}
bool Passenger::operator<(const Passenger& p) const
{
return fname < p.fname || (fname == p.fname && lname < p.lname);
}
void Passenger::print(std::ostream& os)
{
os << fname << ' ' << lname << ' ' << destination << '\n';
}
int Flightlist::menu()
{
int option;
cout << endl;
cout << "Enter one of the following options:" << endl;
cout << "1. load reservations from file:" << endl;
cout << "2. reserve a ticket" << endl;
cout << "3. cancel a reservation" << endl;
cout << "4. check reservation" << endl;
cout << "5. display passenger list" << endl;
cout << "6. save passenger list" << endl;
cout << "7. exit" << endl << endl;
cin >> option;
cin.get();
return option;
}
void Flightlist::read_from_file(string filename)
{
string fname, lname, destination;
std::ifstream input(filename.c_str());
while (input >> fname >> lname >> destination)
{
flist.push_back(Passenger(fname, lname, destination));
}
input.close();
}
void Flightlist::insert(Passenger p)
{
flist.push_back(p);
}
void Flightlist::remove(Passenger p)
{
flist.remove(p);
}
bool Flightlist::check_reservation(Passenger p)
{
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
return flist.end() != find(flist.begin(), flist.end(), p);
}
void Flightlist::display_list()
{
flist.sort();
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
for (; i1 != i2; ++i1) {
i1->print(cout);
}
}
void Flightlist::save_to_file(string filename)
{
flist.sort();
list<Passenger>::iterator i1, i2;
i1 = flist.begin();
i2 = flist.end();
std::ofstream output(filename.c_str());
for (; i1 != i2; ++i1) {
i1->print(output);
}
output.close();
}