thoughtworks家庭作业C++版本
商品类:
#ifndef ITEM_H_ #define ITEM_H_ class SalesTax; //This represents the Items which don't have an Import duty or any sales tax class Item { public: //Constructors Item(); Item (SalesTax *aSalesTax); //Interface Functions for Item //To calculate the price after tax and import duty virtual void CalculateTotalPrice(); //To calculate the total tax and import duty virtual void CalculateTotalTax(); //To set the price of the Items void SetPrice(double aPrice); //To set the number of the Items void SetNum(int aNum); //To set the message of the Items void SetMessage(char *src); //To get the message of the Items char* GetMessage(); //To get the price of the Items before tax double getPrice(); //To get the price of the items after tax double getTotalPrice(); //To get the total tax and import duty of the items double getTax(); //Data protected: //Works as the Strategy of the Sales Tax problem. //If in future the tax calculation becomes more complicated for different Items //we will just have to change this Strategy. We can also subclass this Strategy class //for future expansion of the tax calculation strategy SalesTax* iSalesTax; //Data protected: //These are the basic properties of any Item. //Hence these are made protected members so that the subclasses of Item can inherit //these properties int iNum; double iPrice; double iTotalPrice; double iTotalTax; //the information of the input char message[100]; }; //This class represents the Items which have only Import Duty class ImportedItem : virtual public Item { public: //Constructors ImportedItem(); //This constructor helps to create Items having only Import duty ImportedItem(SalesTax* aSalesTax, double aImportDuty); //Override virtual void CalculateTotalTax(); protected: double iImportDuty; }; //This class represents the Items which have only Sales Tax but no Import Duty class NonFoodBookMedicalItem : virtual public Item { public: //Constructors NonFoodBookMedicalItem(); //This constructor helps to create Items having only Sales tax NonFoodBookMedicalItem(SalesTax* aSalesTax, double aRate); //Override virtual void CalculateTotalTax(); protected: double iRate; }; //This class represents the Items which have got both Import Duty as well as sales Tax class NormalItem: public ImportedItem, public NonFoodBookMedicalItem { public: NormalItem(); //This constructor helps to create Items having both Sales tax and Import duty NormalItem(SalesTax* aSalesTax, double aRate, double aImportDuty); //Override virtual void CalculateTotalTax(); }; #endif /* ITEM_H_ */
#include "SalesTax.h" #include "Item.h" Item::Item(){} Item::Item(SalesTax* aSalesTax):iSalesTax(aSalesTax),iPrice(0),iTotalPrice(0),iTotalTax(0){} void Item::CalculateTotalPrice() { iTotalPrice = iNum * iPrice + iTotalTax; } double Item::getTotalPrice() { return iTotalPrice; } void Item::CalculateTotalTax() { iTotalTax = iNum * iSalesTax->ComputeSalesTax(iPrice, 0, 0); } void Item::SetPrice(double aPrice) { iPrice = aPrice; } void Item::SetNum(int aNum) { iNum = aNum; } void Item::SetMessage(char *src) { char *tmp = message; while((*tmp++ = *src++) != '\0'); } char* Item::GetMessage() { return message; } double Item::getPrice() { return iPrice; } double Item::getTax() { return iTotalTax; } ImportedItem::ImportedItem(){} ImportedItem::ImportedItem(SalesTax* aSalesTax, double aImportDuty):Item(aSalesTax) { iImportDuty = aImportDuty; } void ImportedItem::CalculateTotalTax() { iTotalTax = iNum * iSalesTax->ComputeSalesTax(iPrice, 0, iImportDuty); } NonFoodBookMedicalItem::NonFoodBookMedicalItem(){} NonFoodBookMedicalItem::NonFoodBookMedicalItem(SalesTax* aSalesTax, double aRate):Item(aSalesTax) { iRate = aRate; } void NonFoodBookMedicalItem::CalculateTotalTax() { iTotalTax = iNum * iSalesTax->ComputeSalesTax(iPrice, iRate, 0); } NormalItem::NormalItem() {} NormalItem::NormalItem(SalesTax* aSalesTax, double aRate, double aImportDuty):Item(aSalesTax) { iRate = aRate; iImportDuty = aImportDuty; } void NormalItem::CalculateTotalTax() { iTotalTax = iNum * iSalesTax->ComputeSalesTax(iPrice, iRate, iImportDuty); }
商品工厂
#ifndef ITEMCREATOR_H_ #define ITEMCREATOR_H_ #include "Item.h" const int ITEM_WITH_NOSALESTAX_AND_IMPORTDUTY = 1; const int ITEM_WITH_NOSALESTAX_ONLY_IMPORTDUTY = 2; const int ITEM_WITH_ONLY_SALESTAX_AND_NOIMPORTDUTY = 3; const int ITEM_WITH_BOTH_SALESTAX_AND_IMPORTDUTY = 4; const double SALES_TAX_RATE = 10; const double IMPORT_DUTY_RATE = 5; class Not_A_Standard_Item_Type_Exception { public: void printerrormsg(); }; class ItemCreator { public: virtual Item* Create(int aItemId); }; #endif /* ITEMCREATOR_H_ */
#include "ItemCreator.h" #include "Item.h" #include "SalesTax.h" #include <iostream> using namespace std; void Not_A_Standard_Item_Type_Exception::printerrormsg() { cout<<"Not the right Item Type..."<<endl; } Item* ItemCreator::Create(int aItemId) { SalesTax* st = new SalesTax(); switch(aItemId) { case ITEM_WITH_NOSALESTAX_AND_IMPORTDUTY: return new Item(st); break; case ITEM_WITH_NOSALESTAX_ONLY_IMPORTDUTY: return new ImportedItem(st,IMPORT_DUTY_RATE); break; case ITEM_WITH_ONLY_SALESTAX_AND_NOIMPORTDUTY: return new NonFoodBookMedicalItem(st,SALES_TAX_RATE); break; case ITEM_WITH_BOTH_SALESTAX_AND_IMPORTDUTY: return new NormalItem(st,SALES_TAX_RATE,IMPORT_DUTY_RATE); break; default: throw Not_A_Standard_Item_Type_Exception(); } }
税收政策:
#ifndef SALESTAX_H_ #define SALESTAX_H_ //This class works as the Strategy of the Sales tax problem class SalesTax { public: //Default constructor SalesTax(); //This function helps to compute the Sales Tax virtual double ComputeSalesTax(double aPrice, double aRate, double aImportduty); private: //This is an helper function which will round off the sales tax double RoundOff(double aTax); }; #endif /* SALESTAX_H_ */
#include "SalesTax.h" SalesTax::SalesTax(){} double SalesTax::ComputeSalesTax(double aPrice, double aRate, double aImportduty) { double tx = aPrice * aRate / (double(100)); double ty = aPrice * aImportduty / (double(100)); double rtx = RoundOff(tx); double rty = RoundOff(ty); return rtx + rty; } double SalesTax::RoundOff(double aTax) { double floor = 0.0; double ceil = 0.0; //获取整数 int taxTemp = (int)aTax; //获取小数部分 double decimaltaxTemp = (double)(aTax - (int)taxTemp); //获取第一位小数 int tempy = (int)(1000 * decimaltaxTemp) / 100; //获取第二第三为小数 int tempz = (int)(1000 * decimaltaxTemp - tempy *100); //获取第二位小数 int temp = (int)(tempz / 10); if(temp < 5) { floor = (double)taxTemp + (double)tempy * 0.1; ceil = floor + 0.05; } else { floor = (double)taxTemp + (double)tempy * 0.1 + 0.05; ceil = floor + 0.05; } return (aTax-floor) >= (ceil-aTax) ? ceil : floor; }
main函数代码:
#include "SalesTax.h" #include "Item.h" #include "ItemCreator.h" #include <iostream> #include <iomanip> #include <vector> #include <stdlib.h> #include <set> #include <string> #include <fstream> using namespace std; void decodeInfo(char *str, int &num, int &type, double &price); void initNoBasicTaxLib(); //建立一个书本、食物、药品的库 set<string> noBasicTaxLib; int main(int argc, char *argv[]) { //初始化字典库 initNoBasicTaxLib(); //输出文件的名字 char output[20]; //分割用到的变量 char str[100]; int iNum; int iType; double iPrice; typedef vector<Item*> listOfItem; listOfItem::iterator theIterator; listOfItem Basket; double totalprice = 0; double totaltax = 0; //产品制造工厂 ItemCreator *itemCreator = new ItemCreator(); for (int i = 1; i < argc; i++) { totalprice = 0; totaltax = 0; ifstream in; ofstream out; char * src = argv[i]; char *p = output; //建立输出文档的名字 while ((*p++ = *src++) != '\0'); output[0] = 'o'; output[1] = 'u'; //打开文件 in.open(argv[i], ios::in); if (!in.is_open()) { exit(0); } out.open(output, ios::out); if (!out.is_open()) { exit(0); } while (in.getline(str, 100)) { decodeInfo(str, iNum, iType, iPrice); try { Item* item = itemCreator->Create(iType); item->SetPrice(iPrice); item->SetMessage(str); item->SetNum(iNum); Basket.push_back(item); } catch(Not_A_Standard_Item_Type_Exception& e) { e.printerrormsg(); } }//while //根据读取到的数据处理 theIterator = Basket.begin(); int pos = 0; while (theIterator != Basket.end()) { Basket.at(pos)->CalculateTotalTax(); totaltax += Basket.at(pos)->getTax(); Basket.at(pos)->CalculateTotalPrice(); double price = Basket.at(pos)->getPrice(); double price_after_tax = Basket.at(pos)->getTotalPrice(); totalprice += price_after_tax; out << Basket.at(pos)->GetMessage() << " " << fixed << setprecision(2) << price_after_tax << endl; theIterator++; pos++; } out<< "------------" << endl; out<< "Sales Tax: " << fixed << setprecision(2) << totaltax << endl; out<< "Total: " << totalprice << endl; Basket.clear(); //关闭文件 in.close(); out.close(); }//for system("pause"); return 0; } //初始化药品库 void initNoBasicTaxLib() { noBasicTaxLib.insert("pills"); noBasicTaxLib.insert("chocolates"); noBasicTaxLib.insert("book"); noBasicTaxLib.insert("bar"); } //分析字符串 void decodeInfo(char *str, int &num, int &type, double &price) { bool imported_flag = false; bool basicTax_flag = true; const char *pImported = "imported"; const char *pAt = "at"; num = 0; char *pBegin = str; char *pEnd = pBegin; //得到商品的数量 while (*pBegin == ' ') { ++pBegin; ++pEnd; } while (*pEnd != ' ') { num = num * 10 + (*pEnd - '0'); ++pEnd; } pBegin = pEnd; //获取商品是否为进口货 //在整个字符串中找到at char *at_tag; while (*pBegin != '\0') { if(*pBegin == ' ') { ++pBegin; ++pEnd; } else if (*pEnd == ' ' || *pEnd == '\0') { if (pEnd - pBegin == 2 && strncmp(pBegin, pAt, 2) == 0) { at_tag = pBegin; break; } if(pEnd - pBegin == 8 && strncmp(pBegin, pImported, 8) == 0) imported_flag = true; pBegin = ++pEnd; } else { ++pEnd; } }//while //定位了at之后,获取商品的类型和价格 //类型 --pBegin; while (*pBegin == ' ') { --pBegin; } char *pLast = pBegin; while(*pBegin != ' ') { --pBegin; } ++pBegin; ++pLast; string type_str(pBegin, pLast); if (noBasicTaxLib.find(type_str) != noBasicTaxLib.end()) { basicTax_flag = false; } if(basicTax_flag == true && imported_flag == true) { type = 4; } else if (basicTax_flag == false && imported_flag == false) { type = 1; } else if (basicTax_flag = true && imported_flag == false) { type = 3; } else if (basicTax_flag == false && imported_flag == true) { type = 2; } else {} //价格 while (*pEnd == ' ') { ++pEnd; } price = atof(pEnd); //调整字符数组为输出格式 *at_tag = ':'; ++at_tag; *at_tag = '\0'; }