任务:设计一台自动售货机,其功能如下:接受1,5,10,25,50美分的硬币或1和2个用户选择的纸币:糖果,小吃,坚果,可乐,百事可乐和苏打水,允许用户取消要求,退货和更换,
注:我理解使用std::cin/std::cout等的需要。为了简单起见,我没有做这个特别的改变。
我将开始用我未来的代码来做这个改变。
另外,如果您可以按照设计原则的使用将这段代码从10条中筛选出来,那么我可以在哪里应用这些代码,以及哪一种。
此外,我还被要求使用指针和内存管理。
#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;
}
};为金钱而设的班级:
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;
}
};等级自动售货机:
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;
}
}
}
};主要:
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);
}
}
}发布于 2017-12-03 15:48:49
您要求在应用设计原则方面对您的代码进行评级。我给你1/10,原因如下:
Vending_machine仍然执行I/O,这是它不应该做的,因为这不是它的责任。而且,尽管拥有类money的想法是好的,但是您几乎没有充分利用它,这就忽略了拥有这样一个类的意义。new和动态内存的观点。您当前对操作符的使用非常类似于Java,并且非常不适合于C++。main之外的每个变量都是成员变量?i在money中有什么用途来证明在函数调用之间保持其值是合理的呢?没有。让它成为一个局部变量,最好是本地的for循环。void get_selection(int selection)本身就是一个反模式.几乎所有情况下,get方法都表示getter,getter是返回类的成员值的方法。但是,get_selection返回void。虽然这个答案不是我所说的简短,但很多重要的观点都被遗漏了,因为我不想只是复制和粘贴我对你的前兆问题的答案。正如我在第3点中所说的,请返回,阅读我以前的答案,纠正那些问题,阅读这个答案,纠正这些问题,然后发布一个后续问题(当然,如果您愿意的话),因为关于您的代码还有更多的内容要说。
正如您可能从我的评级和总体答案中猜测的那样,您的代码目前与我所称的“好C++”相去甚远。但是,并不是所有的东西都丢失了;如果您继续改进您的代码,我相信您将在几天内得到一些像样的东西。不要泄气,写(好的) C++是很难的!
发布于 2017-12-03 16:55:16
与第一次尝试相比,这是一个明显的进步。保持良好的工作状态。
注:我理解使用std::cin/std::cout等的必要性。为了简单起见,我没有做这个特别的改变。就会开始用我未来的密码来做这个改变。
不,你需要练习使用std::使它成为一个习惯,这是一个很好的习惯。
将语句放在单独的行上
以下代码是一个非常坏的习惯:
int *price = new int,
*remaining_stock = new int;这会使代码更难维护,而其他必须维护代码的人可能会忽略逗号。在单独的语句中将每个初始化放在单独的行上是一个更好的习惯:
int *price = new int;
int *remaining_stock = new int;将内存分配移动到构造函数中。
在每个类中,内存分配发生在类本身的构造函数之前。在C++中,更好的习惯是在构造函数中分配所有内存,而在类本身中不分配内存。实际上,除了类静态变量之外,所有初始化都应该在构造函数中进行。
其中一个原因是,要维护代码的其他人不会在类中寻找初始化,而是在构造函数中寻找初始化。
我以前见过这种类型的初始化是在C#类中创建引用的时候,在Java中也可能是这样。
另一个原因是,在C++中,许多人使用头文件(#include)来定义类,但是函数本身位于CPP文件中。
示例:
product.hpp:
class product
{
public :
const int MAX_STOCK = 10;
std::string *name;
int *price;
int *remaining_stock;
product(string n, int p);
~product();
};product.cpp:
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文件中有可执行代码的另一个原因是,您不想强迫代码的用户每次修复错误或更改代码时都重新编译。将函数声明而不是函数定义放在头文件中意味着除非函数接口发生变化,否则用户不必重新编译他们的代码,他们可能只需要重新链接。如果代码在动态库中,甚至没有必要重新链接。
使代码更具可读性
通过空格将<<和>>这样的运算符分开通常更容易被接受。
std::cout<<"Wrong selection !"<<std::endl;可读性
std::cout << "Wrong selection !" << std::endl;<<和>>是与-=、-、+=和+一样的运营商;
https://codereview.stackexchange.com/questions/181911
复制相似问题