一個電商平臺對在其平臺之上銷售的除了書籍、食品以及藥物之外的商品收取 10% 的費用。而對於進口的商品則額外收取 5% 的附加費用。對於平臺抽取的費用計算時,舍入的規則是:對於 n% 抽取率,價格爲 p的商品, np/100 的值就近舍入到 0.05(如: 7.125 -> 7.15, 6.66 -> 6.70 )。算法
賣家賣出一些商品後,能夠要求平臺提供一個清單,列出其賣出的全部商品名稱,價格(包括平臺抽取費用),以及平臺抽取的總費用和商品總價 。app
寫一個程序能夠根據下面的輸入值,輸出下面的預期的正確的清單 。spa
要求:設計
1. 使用面向對象的設計思想進行設計。
2. 請分析猜想將來可能的變化點,考慮程序的擴展性。
(考察重點是面向對象的設計能力 )code
輸入:orm
Input 1:對象
1 book at 12.49blog
1 music CD at 14.99遞歸
1 chocolate bar at0.85ci
Input 2:
1 imported box ofchocolates at 10.00
1 imported bottleof perfume at 47.50
Input 3:
1 imported bottleof perfume at 27.99
1 bottle of perfumeat 18.99
1 packet ofheadache pills at 9.75
1 box of importedchocolates at 11.25
輸出:
Outpu1:
1 book: 12.49
1 music CD: 16.49
1 chocolate bar:0.85
Sales Fee: 1.50
Total: 29.83
Output 2:
1 imported box ofchocolates: 10.50
1 imported bottleof perfume: 54.65
Sales Fee: 7.65
Total: 65.15
Output 3:
1 imported bottleof perfume: 32.19
1 bottle ofperfume: 20.89
1 packet ofheadache pills: 9.75
1 box of importedchocolates: 11.85
namespace Test1 { /// <summary> /// 商品基本信息類 /// </summary> public class Goods { /// <summary> /// 商品名稱 /// </summary> public string Name { get; set; } /// <summary> /// 商品類別 /// </summary> public GoodsCategory Category { get; set; } /// <summary> /// 是否進口 /// </summary> public bool IsImported { get; set; } /// <summary> /// 價格 /// </summary> public double Price { get; set; } /// <summary> /// 商品單位 /// </summary> public string Unit { get; set; } /// <summary> /// 賣家 /// </summary> public Vendor Seller { get; set; } } }
商品類別枚舉
namespace Test1 { /// <summary> /// 商品類別枚舉 /// </summary> public enum GoodsCategory { /// <summary> /// 書籍 /// </summary> Book, /// <summary> /// 食品 /// </summary> Food, /// <summary> /// 藥物 /// </summary> Medicine, /// <summary> /// 其它 /// </summary> Other } }
賣家基本信息類
namespace Test1 { /// <summary> /// 賣家基本信息類 /// </summary> public class Vendor { /// <summary> /// 賣家名稱 /// </summary> public string Name { get; set; } /// <summary> /// 賣家聯繫電話 /// </summary> public string Phone { get; set; } } }
某種商品銷售狀況
namespace Test1 { /// <summary> /// 某種商品銷售狀況 /// </summary> public class SalesStatus { /// <summary> /// 銷售數量 /// </summary> public int Amount { get; set; } /// <summary> /// 電商平臺收取費用 /// </summary> public double Fee { get;private set; } /// <summary> /// 總計 /// </summary> public double Total { get; private set; } /// <summary> /// 對應的商品 /// </summary> public Goods SellGoods; public SalesStatus(Goods goods,int amount) { SellGoods = goods; Amount = amount; SetFeeAndTotal(); } /// <summary> /// 計算應收取的費用及總計 /// </summary> private void SetFeeAndTotal() { //單個商品收取的費率 double rate = FeeRate.GetFeeRate(SellGoods); //賣出多個商品應收的費用 Fee = Amount*Utility.Round(rate*SellGoods.Price); //總計=單價*數量+費用 Total = Fee + Amount*SellGoods.Price; } } }
商品收取費率
namespace Test1 { /// <summary> /// 商品收取費率 /// </summary> public class FeeRate { //除了書籍、食品以及藥物之外的商品收取10%的費用 public const double BookRate = 0; public const double FoodRate = 0; public const double MedicineRate = 0; public const double OtherRate = 0.1; //進口的商品則額外收取5%的附加費用 public const double ImportedRate = 0.05; /// <summary> /// 獲取商品費率 /// </summary> /// <returns>返回該商品應收的費率</returns> public static double GetFeeRate(Goods goods) { //商品費率 double rate = 0; //根據商品類別獲取對應的費率 switch (goods.Category) { case GoodsCategory.Book: rate = BookRate; break; case GoodsCategory.Food: rate = FoodRate; break; case GoodsCategory.Medicine: rate = MedicineRate; break; case GoodsCategory.Other: rate = OtherRate; break; } //進口商品收取額外費用 if (goods.IsImported) rate += ImportedRate; return rate; } } }
通用類
using System; namespace Test1 { /// <summary> /// 通用類 /// </summary> public class Utility { /// <summary> /// 數值就近舍入到0.05 /// </summary> public static double Round(double val) { return Math.Ceiling(val * 20) / 20; } } }
銷售清單
using System; using System.Collections.Generic; namespace Test1 { /// <summary> /// 銷售清單 /// </summary> public class SalesOrder { /// <summary> /// 銷售清單明細 /// </summary> public List<SalesStatus> SalesList { get; set; } /// <summary> /// 收取費用合計 /// </summary> public double SalesFee { get; private set; } /// <summary> /// 總計 /// </summary> public double Total { get; private set; } public SalesOrder() { SalesList = new List<SalesStatus>(); } /// <summary> /// 統計 /// </summary> private void CalTotalAndSalesFee() { SalesFee = 0; Total = 0; foreach (var sale in SalesList) { SalesFee += sale.Fee; Total += sale.Total; } } /// <summary> /// 打印銷售清單 /// </summary> public void PrintSalesOrder() { CalTotalAndSalesFee(); string result = ""; foreach (var sale in SalesList) { if (string.IsNullOrWhiteSpace(sale.SellGoods.Unit)) result += sale.Amount + " " + sale.SellGoods.Name + ":" + String.Format("{0:N2}", sale.Total) + "\n"; else result += sale.Amount + " " + sale.SellGoods.Unit + " " + sale.SellGoods.Name + ":" + String.Format("{0:N2}", sale.Total) + "\n"; } result += "Sales Fee: " + String.Format("{0:N2}", SalesFee) + "\n"; result += "Total: " + String.Format("{0:N2}", Total) + "\n"; Console.Write(result); } } }
控制檯程序入口
using System; namespace Test1 { class Program { static void Main(string[] args) { #region Input1 //賣家張三的銷售狀況 Vendor zhangsan = new Vendor { Name = "張三" }; //書的基本信息及銷售狀況 Goods book = new Goods { Name = "book", Category = GoodsCategory.Book, IsImported = false, Price = 12.49, Seller = zhangsan }; SalesStatus bookSalesStatus = new SalesStatus(book, 1); //音樂CD的基本信息及銷售狀況 Goods musicCD = new Goods { Name = "music CD", Category = GoodsCategory.Other, IsImported = false, Price = 14.99, Seller = zhangsan }; SalesStatus musicCDSalesStatus = new SalesStatus(musicCD, 1); //巧克力棒的基本信息及銷售狀況 Goods chocolateBar = new Goods { Name = "chocolate bar", Category = GoodsCategory.Food, IsImported = false, Price = 0.85, Seller = zhangsan }; SalesStatus chocolateBarStatus = new SalesStatus(chocolateBar, 1); //生產銷售清單 SalesOrder order1 = new SalesOrder(); order1.SalesList.Add(bookSalesStatus); order1.SalesList.Add(musicCDSalesStatus); order1.SalesList.Add(chocolateBarStatus); //輸出銷售清單 Console.Write("Outpu1:\n"); order1.PrintSalesOrder(); Console.Write("\n"); #endregion Input1 Console.ReadKey(); } } }
二. 設計程序生成貨架位
在倉庫中爲了方便的管理每一個貨架,咱們會爲每一個貨架命名一個編號,這個編號由字母數字和分隔符(除數字和字母的其它字符,例如:- * | # 等)組成,如今須要設計一個程序輸入起始值和結束值按照必定規則生成一組貨架編號,且一次最多隻能生成5000個。
例如:
一、起始值:A-10 結束值:D-15 輸出的結果以下:
A-10,A-11,A-12,A-13,A-14,A-15,
B-10,B-11,B-12,B-13,B-14,B-15,
C-10,C-11,C-12,C-13,C-14,C-15,
D-10,D-11,D-12,D-13,D-14,D-15
二、起始值:A-10A*E 結束值:B-15B*G 輸出的結果以下:
A-10A*E,A-10A*F,A-10A*G,A-10B*E,A-10B*F,A-10B*G,A-11A*E,A-11A*F,A-11A*G,A-11B*E,A-11B*F,A-11B*G,A-12A*E,A-12A*F,A-12A*G,A-12B*E,A-12B*F,A-12B*G,A-13A*E,A-13A*F,A-13A*G,A-13B*E,A-13B*F,A-13B*G,A-14A*E,A-14A*F,A-14A*G,A-14B*E,A-14B*F,A-14B*G,A-15A*E,A-15A*F,A-15A*G,A-15B*E,A-15B*F,A-15B*G,B-10A*E,B-10A*F,B-10A*G,B-10B*E,B-10B*F,B-10B*G,B-11A*E,B-11A*F,B-11A*G,B-11B*E,B-11B*F,B-11B*G,B-12A*E,B-12A*F,B-12A*G,B-12B*E,B-12B*F,B-12B*G,B-13A*E,B-13A*F,B-13A*G,B-13B*E,B-13B*F,B-13B*G,B-14A*E,B-14A*F,B-14A*G,B-14B*E,B-14B*F,B-14B*G,B-15A*E,B-15A*F,B-15A*G,B-15B*E,B-15B*F,B-15B*G
三、起始值:A10 結束值:B15 輸出的結果以下:
A10,A11,A12,A13,A14,A15,B10,B11,B12,B13,B14,B15
輸入錯誤示例:
起始值 |
結束值 |
錯誤緣由 |
A10 |
B203 |
起始值和結束值長度不同 |
A-10 |
B*20 |
第二個字符分隔符不同 |
D-10 |
B-20 |
起始值字母D大於結束值字母B |
B-30 |
D-10 |
起始值中數字30 大於結束值中數字10 |
A-5 |
D-C |
起始值第三個字符是數字,而結束值第三個字符是字母 |
A-0001 |
E-1100 |
生成了5500個,超過一次最大5000個的限制 |
貨架編號生成器類
using System; using System.Collections.Generic; namespace Test2 { /// <summary> /// 貨架編號生成器 /// </summary> public class ShelvesNumGenerator { /// <summary> /// 起始編號 /// </summary> public string StartNum { get; set; } /// <summary> /// 結束編號 /// </summary> public string EndNum { get; set; } /// <summary> /// 生成貨架編號的數量 /// </summary> public int NumCount { get; set; } /// <summary> /// 最大貨架編號的數量 /// </summary> public const int MaxCount = 5000; /// <summary> /// 錯誤編號提示信息 /// </summary> public string ErrorMsg { get; set; } /// <summary> /// 分隔符 /// </summary> public char[] Separators = { '-', '*', '|', '#' }; /// <summary> /// 生成的編號列表 /// </summary> public List<string> NumList { get; private set; } public ShelvesNumGenerator(string startNum, string endNum) { StartNum = startNum; EndNum = endNum; NumList=new List<string>(); } /// <summary> /// 生成貨架編號列表 /// </summary> public void GenerateShelvesNumList() { //編號拆分,例如A-10B*G|12拆分紅["A","-","10","B","*","G","|","12"] List<string> sList = SplitNumToList(StartNum); List<string> eList = SplitNumToList(EndNum); List<string[]> strsList=new List<string[]>(); for (int i = sList.Count-1; i >=0; i--) { string[] strs; //若是元素是數字 int sNum; if (Int32.TryParse(sList[i], out sNum)) { int eNum = Int32.Parse(eList[i]); strs = new string[eNum - sNum + 1]; for (int j = sNum; j <= eNum; j++) { strs[j - sNum] = j.ToString().PadLeft(sList[i].Length, '0'); } } else { //元素是字母或者分隔符的狀況 strs = new string[eList[i][0] - sList[i][0] + 1]; for (int j = sList[i][0]; j <= eList[i][0]; j++) { strs[j - sList[i][0]] =((char)j).ToString(); } } strsList.Add(strs); } Recursion(strsList, new Stack<string>()); } /// <summary> /// 遞歸組合生成貨架編號 /// </summary> private void Recursion(List<string[]> list, Stack<string> stack) { if (stack.Count == list.Count) { NumList.Add(string.Join("", stack.ToArray())); } else { string[] strs = list[stack.Count]; foreach (string s in strs) { stack.Push(s); Recursion(list, stack); stack.Pop(); } } } /// <summary> /// 打印貨架編號列表 /// </summary> public void PrintShelvesNumList() { Console.WriteLine("共生成"+NumList.Count+"個貨架編號:"); NumList.Sort(); Console.WriteLine(string.Join(",",NumList)+"\n"); } /// <summary> /// 檢查起始編號和結束編號是否合法 /// </summary> public bool CheckInvalidNum() { if (StartNum.Length != EndNum.Length) { ErrorMsg = "起始編號和結束編號長度不同"; return false; } //分隔符位置不一致的狀況 foreach (var separator in Separators) { int sIdx = StartNum.IndexOf(separator); int eIdx = EndNum.IndexOf(separator); if (sIdx == 0 || eIdx == 0) { ErrorMsg = "編號不能以分隔符開頭"; return false; } if (sIdx > 0 || eIdx > 0) { if (sIdx != eIdx) { int idx = sIdx > 0 && eIdx > 0 ? Math.Min(sIdx, eIdx) : sIdx > 0 ? sIdx : eIdx; ErrorMsg = "第" + (idx + 1) + "個字符分隔符不同"; return false; } } } //起始編號字母大於結束編號字母 //起始值第三個字符是數字,而結束值第三個字符是字母 for (int i = 0; i < StartNum.Length; i++) { if (IsAlphabet(StartNum[i]) && IsAlphabet(EndNum[i])) { if (StartNum[i] > EndNum[i]) { ErrorMsg = "起始編號字母" + StartNum[i] + "大於結束編號字母" + EndNum[i]; return false; } } if (IsAlphabet(StartNum[i]) && IsNumber(EndNum[i])) { ErrorMsg = "起始編號第" + (i + 1) + "個字符是字母,而結束值第" + (i + 1) + "個字符是數字"; return false; } if (IsNumber(StartNum[i]) && IsAlphabet(EndNum[i])) { ErrorMsg = "起始編號第" + (i + 1) + "個字符是數字,而結束值第" + (i + 1) + "個字符是字母"; return false; } } //起始編號中數字大於結束編號中數字 List<string> sInts = GetIntList(StartNum); List<string> eInts = GetIntList(EndNum); for (int i = 0; i < sInts.Count; i++) { if (Convert.ToInt32(sInts[i]) > Convert.ToInt32(eInts[i])) { ErrorMsg = "起始編號中數字" + sInts[i] + "大於結束編號中數字"+ eInts[i]; return false; } } //能夠生成的貨架編號數量是否超過了最大值 //計算貨架數量的算法:A01B,B05C, COUNT=(B-A+1)*(5-1+1)*(C-B+1) NumCount = 1; for (int i = 0; i < StartNum.Length; i++) { if (IsAlphabet(StartNum[i])) { NumCount *= EndNum[i] - StartNum[i] + 1; } } for (int i = 0; i < sInts.Count; i++) { NumCount *= Convert.ToInt32(eInts[i]) - Convert.ToInt32(sInts[i]) + 1; } if (NumCount > MaxCount) { ErrorMsg = "生成了" + NumCount + "超過一次最大" + MaxCount + "個的限制"; return false; } return true; } /// <summary> /// 判斷一個字符是不是字母 /// </summary> public bool IsAlphabet(char c) { //字母A-Z的ASCII碼是從65-90 if (c >= 'A' && c <= 'Z') return true; else return false; } /// <summary> /// 判斷一個字符是不是數字 /// </summary> public bool IsNumber(char c) { //數字0-9的ASCII碼是從48-57 if (c >= '0' && c <= '9') return true; else return false; } /// <summary> /// 提取字符串中的int數放入List /// </summary> public List<string> GetIntList(string str) { List<string> myList = new List<string>(); string number = ""; for (int i = 0; i < str.Length; ++i) { if (IsNumber(str[i])) { number += str[i]; if (i == str.Length - 1) { myList.Add(number); } } else { if (!number.Equals("")) { myList.Add(number); number = ""; } } } return myList; } /// <summary> /// 編號拆分,例如A-10B*G|12拆分紅["A","-","10","B","*","G","|","12"] /// </summary> public List<string> SplitNumToList(string str) { List<string> myList = new List<string>(); string number = ""; for (int i = 0; i < str.Length; ++i) { if (IsNumber(str[i])) { number += str[i]; if (i == str.Length - 1) { myList.Add(number); } } else { if (!number.Equals("")) { myList.Add(number); number = ""; } myList.Add(str[i].ToString()); } } return myList; } } }
控制檯程序入口
using System; namespace Test2 { class Program { static void Main(string[] args) { do { Console.WriteLine("\n請輸入起始編號:"); string startNum = Console.ReadLine(); Console.WriteLine("請輸入結束編號:"); string endNum = Console.ReadLine(); if (string.IsNullOrWhiteSpace(startNum) || string.IsNullOrWhiteSpace(endNum)) { Console.WriteLine("\n錯誤信息:起始編號或者結束編號不能爲空\n"); } else { //負責生成貨架編號的生成器類 //編號中的字母統一轉換成大寫 ShelvesNumGenerator generator = new ShelvesNumGenerator(startNum.ToUpper(), endNum.ToUpper()); //首先檢查輸入的編號是否合法 bool isValid = generator.CheckInvalidNum(); if (!isValid) { Console.WriteLine("\n錯誤信息:" + generator.ErrorMsg + "\n");//輸出錯誤信息 } else { generator.GenerateShelvesNumList();//生成貨架編號列表 generator.PrintShelvesNumList();//輸出貨架編號列表 } } Console.Write("請輸入exit退出系統,其它鍵繼續:"); } while (!Console.ReadLine().ToUpper().Contains("EXIT")); } } }