简体   繁体   English

C ++对函数和向量感到困惑

[英]C++ Confused about functions and vectors

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). 在我的班级清单,公共:void SetSumInv中,该程序执行的操作是获取用户输入,并汇总所有内容,因此在打印时,应打印清单,然后再打印清单的总和。价值(以美元为单位)。 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 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; main.cpp并没有成堆的代码行; it is always good practice to keep main.cpp short and simple since this is where the main executable starts. 始终使main.cpp简短易行是一个好习惯,因为这是主可执行文件开始的地方。 I created a class of your inventory and put it in its own module in a *.h and *.cpp file. 我创建了清单类,并将其放在*.h*.cpp文件中的自己的模块中。 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. 接口或*.h文件应该告诉您有关类对象及其使用方法的所有信息。 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. 这也使构建过程更快捷,因为仅当您在其中进行了某些更改而不是重新构建整个解决方案时,才需要编译此类的*.cpp文件。

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. 您可能希望将实现包含在头文件中的情况是,如果您的方法被声明为inline或者您正在创建仅头文件的库。 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; 您可能别无选择,只能在头文件中进行选择的情况是,如果要创建class templatesfunction templates但是当您同时拥有inline member functionsclass template member functionsfunction templates这两种类型时,通常是*.inl联文件或*.inl ,您可以在类声明的外部且在#endif标头保护之前使用#include指令包含此文件; if you are using #pragma once instead of the #ifndef #define #endif then you would just have this after the class's declaration. 如果您只使用#pragma once而不是#ifndef #define #endif那么在类的声明之后就可以使用它。

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. 该程序使用C ++编写,使用Win32控制台应用程序和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. StoreItem类是一个抽象基类,这意味着您不能直接创建此类型的对象,因为其构造函数受到保护。 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. 基类中唯一的私有成员是继承类在构造时的Type 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. Inventory类是存储和删除项目,计算总计并打印其清单的大部分工作。

I designed it this way so that the StoreItem and its inherited classes do not have any dependences with the iostream objects. 我以这种方式进行了设计,以使StoreItem及其继承的类与iostream对象没有任何依赖关系。 The Inventory class only uses the std::cout objects within its printing method. 库存类仅在其打印方法中使用std::cout对象。

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. 与输入或std::cin对象一起使用的唯一代码部分位于while循环工作的main函数内。

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. 您将必须创建另一个派生自StoreItem的类,在Enumerated类型中添加Add,然后重复在Inventory和用户选择分支内添加适当功能的过程。

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 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 stdafx.cpp

#include "stdafx.h"

StoreItem.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 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 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 生产.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 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 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 几个问题:1.)priceInDollars未正确初始化2.)totalInvPriceInDollars需要为静态

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM