首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现自动售货机

实现自动售货机
EN

Code Review用户
提问于 2017-12-03 13:52:26
回答 2查看 11.9K关注 0票数 8

任务:设计一台自动售货机,其功能如下:接受1,5,10,25,50美分的硬币或1和2个用户选择的纸币:糖果,小吃,坚果,可乐,百事可乐和苏打水,允许用户取消要求,退货和更换,

注:我理解使用std::cin/std::cout等的需要。为了简单起见,我没有做这个特别的改变。

我将开始用我未来的代码来做这个改变。

另外,如果您可以按照设计原则的使用将这段代码从10条中筛选出来,那么我可以在哪里应用这些代码,以及哪一种。

此外,我还被要求使用指针和内存管理。

代码语言:javascript
复制
#include <iostream>
    using namespace std;

    class product
        {
            public :
            const int MAX_STOCK = 10;

            string *name = new string;
            int *price = new int,
                *remaining_stock = new int;

            product(string n, int p)
                {
                    *price = p;
                    *name = *name + n;
                    *remaining_stock = MAX_STOCK;
                }
            ~product()
                {
                    delete price;
                    delete name;
                    delete remaining_stock;
                }
        };

为金钱而设的班级:

代码语言:javascript
复制
  class money
        {
            public :

            int *max = new int;
            int *accepted_values = new int[10];
            int i;
            money()
                {
                }
            money(int *a, int how_many)
                {
                    *max = how_many;
                    //cout<<"\n this is max now : "<<*max;
                        for (i=0; i<how_many; i++)
                            {
                                *(accepted_values + i) = a[i];
                                //cout<<"\n inside money : "<<i<<" accepted value is "<<*(accepted_values + i)<<" value is a is :"<<a[i]<<endl;
                            }           
                }
            int check(int value, int loop_max)
                {
                    //cout<<"\nInside money checker, the value of max is :"<<loop_max;
                    bool present = 0;
                    //cout<<"\nInside money checker, the value of present is :"<<present;
                    for(i=0; i< loop_max; i++)
                        {
                            //cout<<"\n Accepted values - "<<i<<" is : "<<*(accepted_values + i)<<" value is :"<<value;
                            if (value == *(accepted_values + i))
                            {
                                //cout<<"\n value present!";
                                present = 1;
                            }
                        }
                    if(!present)
                        {
                            //cout<<"\n not present and present is now : "<<present;
                            value = 0;
                        }
                    return value;
                }
            ~money()
                {
                    delete max;
                    delete accepted_values;
                }
        };

等级自动售货机:

代码语言:javascript
复制
    class Vending_machine
        {
            public :

            product *candy = new product("Candy",10);
            product *snack = new product("Snack",50);
            product *nuts = new product("Nuts",90);
            product *coke = new product("Coke",25);
            product *soda = new product("Soda",45);

            int accepted_coins[5] = {1,5,10,25,50};
            int accepted_notes[2] = {1,2};

            money *coins = new money(accepted_coins, 5);
            money *notes = new money(accepted_notes, 2);

            int *amount_deposited = new int;

            Vending_machine()
                {
                    *amount_deposited = 0;
                }
            Vending_machine(bool reset)
                {   
                    if (reset == true)
                        {
                            *amount_deposited = 0;
                            //delete candy;
                            //delete snack;
                            //delete nuts;
                            //delete coke;
                            //delete soda;
                            //delete coins;
                            //delete notes;

                            product *candy = new product("Candy",10);
                            product *snack = new product("Snack",50);
                            product *nuts = new product("Nuts",90);
                            product *coke = new product("Coke",25);
                            product *soda = new product("Soda",45);
                            }
                }
            ~Vending_machine()
                {
                    delete candy;
                    delete snack;
                    delete nuts;
                    delete coke;
                    delete soda;
                    delete coins;
                    delete notes;
                    delete amount_deposited;
                }
            void get_money(int choice,int value)
                {
                    switch(choice)
                        {
                            case(1):
                                //cout<<"\nthis is the value of amount deposited before : "<<*amount_deposited;
                                *amount_deposited = coins->check(value, *coins->max);
                                //cout<<"\nthis is the value of amount deposited after : "<<*amount_deposited;
                            break;
                            case(2):
                                //cout<<"\nthis is the value of amount deposited before : "<<*amount_deposited;
                                *amount_deposited = notes->check(value, *notes->max) * 100;
                                //cout<<"\nthis is the value of amount deposited after : "<<*amount_deposited;
                            break;
                            default:
                                *amount_deposited = 0;
                        }
                }
            void compare_availability(int *remain, int *price)
                {
                    try
                    {
                        if(*remain !=0 && *amount_deposited >= *price)
                            {
                                *remain -= 1;;
                                *amount_deposited -= *price;
                                cout<<"\n Dispatched";
                                return_money('Y');
                            }
                        else if (*amount_deposited < *price)
                            {
                                throw "Amount deposited is low";
                            }
                        else if (*remain == 0)
                            {
                                throw "Stock not available";
                            }
                        else
                            {
                                throw "Unknown error";
                            }
                    }catch (const char* msg)
                        {
                            cout<<msg<<endl;
                        }
                }
            void get_selection(int selection)
                {
                    switch(selection)
                        {
                            case (1):
                                compare_availability(candy->remaining_stock, candy->price);
                            break;
                            case (2):
                                compare_availability(snack->remaining_stock, snack->price);
                            break;
                            case (3):
                                compare_availability(nuts->remaining_stock, nuts->price);
                            break;
                            case (4):
                                compare_availability(coke->remaining_stock, coke->price);
                            break;
                            case (5):
                                compare_availability(soda->remaining_stock, soda->price);
                            break;
                            default:
                                cout<<"Wrong selection !"<<endl;
                        }
                }
            void return_money(char choice)
            {
                if (*amount_deposited != 0)
                    { 
                        if (choice == 'Y' || choice == 'y')
                            {
                                cout<<"\n Your remaining change is : " << *amount_deposited/100.0 <<" $ \n";
                                *amount_deposited = 0;
                            }
                    }
            }
        };

主要:

代码语言:javascript
复制
    int main() 
        {
            int main_select, main_coin_note, main_val;
            char change_your_mind;
            Vending_machine *a = new Vending_machine(1);
            cout<<"Coin(1) or Note(2) : ";
            cin>>main_coin_note;
            cout<<"Enter your denomination :";
            cin>>main_val;
            a->get_money(main_coin_note, main_val);

            if (*a->amount_deposited == 0)
                {
                    cout<<"\n Wrong denomination, Value returned !";
                }
            else
                {
                    cout<<"\tEnter what product you want :"<<endl<<"\t\t1 for Candy"<<endl<<"\t\t2 for Snack"<<endl<<"\t\t3 for Nuts"<<endl<<"\t\t4 for Coke"<<endl<<"\t\t5 for Soda\n\t :..";
                    cin>>main_select;
                    cout<<"\n You want to cancel request?(Y/N) :";
                    cin>>change_your_mind;
                        if (change_your_mind == 'Y' || change_your_mind == 'y')
                            {
                                a->return_money(change_your_mind);
                            }
                        else
                            {
                                a->get_selection(main_select);
                            }
                }
        }
EN

回答 2

Code Review用户

回答已采纳

发布于 2017-12-03 15:48:49

您要求在应用设计原则方面对您的代码进行评级。我给你1/10,原因如下:

  1. 你有不同的班级,有不同的责任,这是一件好事。然而,您的类Vending_machine仍然执行I/O,这是它不应该做的,因为这不是它的责任。而且,尽管拥有类money的想法是好的,但是您几乎没有充分利用它,这就忽略了拥有这样一个类的意义。
  2. 注释掉单个代码行是我们都要做的事情,但是这些行应该从完成的代码中删除,因为它们在任何意义上都不是有用的注释。您当前的代码调用了一种非常“讨厌”的感觉,这是不好的。
  3. 因为我很懒,所以我不会重复我以前写过的关于您的代码的所有内容。由于您似乎忽略了我以前所有的建议,请回到我对这个问题前兆的回答,并重新研究这些要点。特别是,请再读一遍我关于new和动态内存的观点。您当前对操作符的使用非常类似于Java,并且非常不适合于C++。
  4. 请重新考虑您的缩进方案。虽然对于一刀切的缩进模型还没有达成共识,而且关于这个主题的每一个答案在一定程度上都是固执己见的,但我确实发现,您当前的缩进在很大程度上可以使您的代码保持一种可读的格式。例如,为什么在函数头后面缩进花括号,然后缩进另一个级别的身体?为什么您的开关中的实际代码语句与开关相比缩进了4个级别?如果你在一个开关箱里有一个开关箱呢?这是一个完整的8级缩进。每一等级的缩进是4个字符,那将是一个完整的32个字符丢失,这是超过1/3的标准线宽80个字符!最后,这些事情都符合你自己的喜好,但作为一个必须阅读你的代码的人,我恳请你注意,请选择一种不会产生比实际代码更多水平空白的样式。
  5. 为什么main之外的每个变量都是成员变量?imoney中有什么用途来证明在函数调用之间保持其值是合理的呢?没有。让它成为一个局部变量,最好是本地的for循环。
  6. void get_selection(int selection)本身就是一个反模式.几乎所有情况下,get方法都表示getter,getter是返回类的成员值的方法。但是,get_selection返回void
  7. 补充到第6点,你似乎对返回价值的概念没有一个明确的把握。单一责任原则和良好的面向对象代码的关键之一是让对象提供一个良好的接口,而好接口这个术语不包括“将其打印到标准输出”(-pattern)。这个接口的一个重要部分是所谓的getter和setter方法。Getter方法,顾名思义,负责“获取”,即返回对象中包含的值,而setter则设置成员变量的值。如果这些概念听起来不熟悉,那么您绝对应该阅读它们,因为它们是OOP的基石之一。

虽然这个答案不是我所说的简短,但很多重要的观点都被遗漏了,因为我不想只是复制和粘贴我对你的前兆问题的答案。正如我在第3点中所说的,请返回,阅读我以前的答案,纠正那些问题,阅读这个答案,纠正这些问题,然后发布一个后续问题(当然,如果您愿意的话),因为关于您的代码还有更多的内容要说。

正如您可能从我的评级和总体答案中猜测的那样,您的代码目前与我所称的“好C++”相去甚远。但是,并不是所有的东西都丢失了;如果您继续改进您的代码,我相信您将在几天内得到一些像样的东西。不要泄气,写(好的) C++是很难的!

票数 12
EN

Code Review用户

发布于 2017-12-03 16:55:16

与第一次尝试相比,这是一个明显的进步。保持良好的工作状态。

注:我理解使用std::cin/std::cout等的必要性。为了简单起见,我没有做这个特别的改变。就会开始用我未来的密码来做这个改变。

不,你需要练习使用std::使它成为一个习惯,这是一个很好的习惯。

将语句放在单独的行上

以下代码是一个非常坏的习惯:

代码语言:javascript
复制
    int *price = new int,
        *remaining_stock = new int;

这会使代码更难维护,而其他必须维护代码的人可能会忽略逗号。在单独的语句中将每个初始化放在单独的行上是一个更好的习惯:

代码语言:javascript
复制
    int *price = new int;
    int *remaining_stock = new int;

将内存分配移动到构造函数中。

在每个类中,内存分配发生在类本身的构造函数之前。在C++中,更好的习惯是在构造函数中分配所有内存,而在类本身中不分配内存。实际上,除了类静态变量之外,所有初始化都应该在构造函数中进行。

其中一个原因是,要维护代码的其他人不会在类中寻找初始化,而是在构造函数中寻找初始化。

我以前见过这种类型的初始化是在C#类中创建引用的时候,在Java中也可能是这样。

另一个原因是,在C++中,许多人使用头文件(#include)来定义类,但是函数本身位于CPP文件中。

示例:

product.hpp:

代码语言:javascript
复制
class product
{
    public :
    const int MAX_STOCK = 10;

    std::string *name;
    int *price;
    int *remaining_stock;

    product(string n, int p);
    ~product();
};

product.cpp:

代码语言:javascript
复制
product::product(string n, int p)
{       
    name = new string(n);
    price = new int;
    remaining_stock = new int;

    *price = p;
    *remaining_stock = MAX_STOCK;
}       

product::~product()
{       
    delete price;
    delete name;
    delete remaining_stock;
}       

可以在头文件中包含可执行代码,尤其是编译器可能通过内联优化的代码,但对于更复杂的代码,在单独的文件中维护可能更容易。它还增强了对用户隐藏实现的能力。

CPP文件中有可执行代码的另一个原因是,您不想强迫代码的用户每次修复错误或更改代码时都重新编译。将函数声明而不是函数定义放在头文件中意味着除非函数接口发生变化,否则用户不必重新编译他们的代码,他们可能只需要重新链接。如果代码在动态库中,甚至没有必要重新链接。

使代码更具可读性

通过空格将<<>>这样的运算符分开通常更容易被接受。

代码语言:javascript
复制
    std::cout<<"Wrong selection !"<<std::endl;

可读性

代码语言:javascript
复制
    std::cout << "Wrong selection !" << std::endl;

<<>>是与-=-+=+一样的运营商;

票数 6
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/181911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档