diff --git a/Chapter-15/15.30/Quote.cpp b/Chapter-15/15.30/Quote.cpp new file mode 100644 index 0000000..2467cff --- /dev/null +++ b/Chapter-15/15.30/Quote.cpp @@ -0,0 +1,43 @@ + #include + #include "Quote.h" + +double Quote::net_price(std::size_t n) const +{ + return n * price; +} + +double print_total(std::ostream & os, const Quote & item, std::size_t n) +{ + double ret = item.net_price(n); + os << "ISBN: " << item.isbn() << " # sold: " << n << " total due: " << ret << std::endl; + return ret; +} + +double Bulk_quote::net_price(std::size_t cnt) const +{ + if(cnt >= quantity) + return cnt * (1 - discount) * price; + else + return cnt * price; +} + +std::ostream & Quote::debug(std::ostream & os) const +{ + os << bookNo << " " << price; + return os; +} + +std::ostream & Disc_quote::debug(std::ostream & os) const +{ + this->Quote::debug(os) << " " << quantity << " " << discount; + return os; +} + +double Basket::total_receipt(std::ostream &os) const +{ + double sum = 0.0; + for(std::multiset, decltype(compare)*>::const_iterator iter = items.cbegin(); iter != items.cend(); iter = items.upper_bound(*iter)) + sum += print_total(os, **iter, items.count(*iter)); + os << "Total Sales: " << sum << std::endl; + return sum; +} diff --git a/Chapter-15/15.30/Quote.h b/Chapter-15/15.30/Quote.h new file mode 100644 index 0000000..b18dcdc --- /dev/null +++ b/Chapter-15/15.30/Quote.h @@ -0,0 +1,78 @@ +#ifndef QUOTE_H +#define QUOTE_H + +#include +#include +#include +#include + +class Quote +{ +public: + Quote() = default; + Quote(const std::string &book, double sales_price) : bookNo(book), price(sales_price) { } + std::string isbn() const { return bookNo; } + + virtual double net_price(std::size_t n) const; + virtual ~Quote() = default; + virtual std::ostream & debug(std::ostream & os) const; + + virtual Quote * clone() const & { return new Quote(*this); } + virtual Quote * clone() && { return new Quote(std::move(*this)); } + + Quote(const Quote &) = default; + Quote(Quote &&) = default; + Quote & operator=(const Quote &) = default; + Quote & operator=(Quote &&) = default; + +private: + std::string bookNo; + +protected: + double price = 0.0; +}; + +class Disc_quote : public Quote +{ +public: + Disc_quote() = default; + Disc_quote(const std::string & book, double price, std::size_t qty, double disc) : Quote(book, price), quantity(qty), discount(disc) { } + + std::ostream & debug(std::ostream & os) const override; + double net_price(std::size_t) const = 0; + +protected: + std::size_t quantity = 0; + double discount = 0.0; +}; + +class Bulk_quote : public Disc_quote +{ +public: + Bulk_quote() = default; + Bulk_quote(const std::string & book, double price, std::size_t qty, double disc) : Disc_quote(book, price, qty, disc) { } + + Bulk_quote * clone() const & override { return new Bulk_quote(*this); } + Bulk_quote * clone() && override { return new Bulk_quote(std::move(*this)); } + + double net_price(std::size_t) const override; +}; + +double print_total(std::ostream & os, const Quote & item, std::size_t cnt); + +class Basket +{ +public: + void add_item(const Quote &sale){ items.insert(std::shared_ptr(sale.clone())); } + void add_item(Quote &&sale){ items.insert(std::shared_ptr(std::move(sale).clone())); } + double total_receipt(std::ostream &) const; + +private: + static bool compare(const std::shared_ptr &lhs, const std::shared_ptr &rhs) + { return lhs->isbn() < rhs->isbn(); } + + std::multiset, decltype(compare)*> items{compare}; +}; + + +#endif diff --git a/Chapter-15/15.30/main.cpp b/Chapter-15/15.30/main.cpp new file mode 100644 index 0000000..d707891 --- /dev/null +++ b/Chapter-15/15.30/main.cpp @@ -0,0 +1,19 @@ +#include +#include +#include "Quote.h" + +int main() +{ + Basket b; + b.add_item(Quote("qwe", 10)); + b.add_item(Quote("qwe", 10)); + b.add_item(Bulk_quote("wer", 20, 2, 0.2)); + b.add_item(Bulk_quote("wer", 20, 2, 0.2)); + b.add_item(Bulk_quote("wer", 20, 2, 0.2)); + b.add_item(Bulk_quote("ert", 20, 2, 0.2)); + b.add_item(Quote("rty", 10)); + b.total_receipt(std::cout); + + return 0; +} + diff --git a/Chapter-15/15.35/Query.cpp b/Chapter-15/15.35/Query.cpp new file mode 100644 index 0000000..2aec37f --- /dev/null +++ b/Chapter-15/15.35/Query.cpp @@ -0,0 +1,22 @@ +#include +#include +#include "TextQuery.h" +#include "Query.h" + +Query::Query(const std::string &s) : q(new WordQuery(s)) { } + +Query operator~(const Query &operand) +{ + return std::shared_ptr(new NotQuery(operand)); +} + +Query operator&(const Query &lhs, const Query &rhs) +{ + return std::shared_ptr(new AndQuery(lhs, rhs)); +} + +Query operator|(const Query &lhs, const Query &rhs) +{ + return std::shared_ptr(new OrQuery(lhs, rhs)); +} + diff --git a/Chapter-15/15.35/Query.h b/Chapter-15/15.35/Query.h new file mode 100644 index 0000000..18a5b45 --- /dev/null +++ b/Chapter-15/15.35/Query.h @@ -0,0 +1,82 @@ +#ifndef QUERY_H +#define QUERY_H + +#include +#include +#include "TextQuery.h" + +class Query_base +{ + friend class Query; +protected: + using line_no = TextQuery::line_no; + virtual ~Query_base() = default; +private: + virtual QueryResult eval(const TextQuery &) const = 0; + virtual std::string rep() const = 0; +}; + +class Query +{ + friend Query operator~(const Query &); + friend Query operator|(const Query &, const Query &); + friend Query operator&(const Query &, const Query &); +public: + Query(const std::string &); + QueryResult eval(const TextQuery &t) const { return q->eval(t); } + std::string rep() const { return q->rep(); } +private: + Query(std::shared_ptr query) : q(query) { } + std::shared_ptr q; +}; + +class WordQuery : public Query_base +{ + friend class Query; + WordQuery(const std::string &s) : query_word(s) { } + QueryResult eval(const TextQuery &t) const { return t.query(query_word); } + std::string rep() const { return query_word; } + + std::string query_word; +}; + +class NotQuery : public Query_base +{ + friend Query operator~(const Query &); + NotQuery(const Query &q) : query(q) { } + std::string rep() const { return "~(" + query.rep() + ")"; } + //todo Test substitution function + QueryResult eval(const TextQuery &t) const { return t.query(query.rep()); } + Query query; +}; + +class BinaryQuery : public Query_base +{ +protected: + BinaryQuery(const Query &l, const Query &r, std::string s) : lhs(l), rhs(r), opSym(s) { } + std::string rep() const { return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")"; } + Query lhs, rhs; + std::string opSym; +}; + +class AndQuery : public BinaryQuery +{ + friend Query operator&(const Query &, const Query &); + AndQuery(const Query &left, const Query &right) : BinaryQuery(left, right, "&") { } + //todo Test substitution function + QueryResult eval(const TextQuery &t) const { return t.query("temp"); } +}; + +class OrQuery : public BinaryQuery +{ + friend Query operator|(const Query &, const Query &); + OrQuery(const Query &left, const Query &right) : BinaryQuery(left, right, "|") { } + //todo Test substitution function + QueryResult eval(const TextQuery &t) const { return t.query("temp"); } +}; + +Query operator~(const Query &); +Query operator|(const Query &, const Query &); +Query operator&(const Query &, const Query &); + +#endif diff --git a/Chapter-15/15.35/TextQuery.cpp b/Chapter-15/15.35/TextQuery.cpp new file mode 100644 index 0000000..cebc75f --- /dev/null +++ b/Chapter-15/15.35/TextQuery.cpp @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "TextQuery.h" + +std::string make_plural(size_t ctr, const std::string &word, const std::string &ending) +{ + return (ctr > 1) ? word + ending : word; +} + +TextQuery::TextQuery(std::ifstream & is) : file(new std::vector) +{ + std::string text; + while(std::getline(is, text)) + { + file->push_back(text); + int n = file->size()-1; + std::istringstream line(text); + std::string word; + while(line >> word) + { + std::shared_ptr> &lines = wm[word]; + if(!lines) + lines.reset(new std::set); + lines->insert(n); + } + } +} + +QueryResult TextQuery::query(const std::string & sought) const +{ + static std::shared_ptr> nodata(new std::set); + std::map>>::const_iterator loc = wm.find(sought); + if(loc == wm.cend()) + return QueryResult(sought, nodata, file); + else + return QueryResult(sought, loc->second, file); +} + +std::set::iterator QueryResult::begin() +{ + return lines->begin(); +} + +std::set::iterator QueryResult::end() +{ + return lines->end(); +} + +std::shared_ptr> QueryResult::get_file() +{ + return file; +} + +std::ostream & print(std::ostream & os, const QueryResult &qr) +{ + os << qr.sought << " occurs " << qr.lines->size() << " " << make_plural(qr.lines->size(), "time", "s") << std::endl; + for(TextQuery::line_no num : *qr.lines) + os << "\t(line " << num+1 << ") " << *(qr.file->begin() + num) << std::endl; + return os; +} + diff --git a/Chapter-15/15.35/TextQuery.h b/Chapter-15/15.35/TextQuery.h new file mode 100644 index 0000000..4177eda --- /dev/null +++ b/Chapter-15/15.35/TextQuery.h @@ -0,0 +1,44 @@ +#ifndef TEXTQUERY_H +#define TEXTQUERY_H + +#include +#include +#include +#include +#include +#include +#include + +class QueryResult; + +class TextQuery +{ +public: + using line_no = std::vector::size_type; + TextQuery(std::ifstream &); + QueryResult query(const std::string &) const; + TextQuery(const TextQuery & tq) = default; + TextQuery & operator=(const TextQuery & tq) = default; + ~TextQuery() = default; + +private: + std::shared_ptr> file; + std::map>> wm; +}; + +class QueryResult +{ + friend std::ostream & print(std::ostream &, const QueryResult &); +public: + QueryResult(std::string s, std::shared_ptr> p, std::shared_ptr> f) : sought(s), lines(p), file(f) { } + std::set::iterator begin(); + std::set::iterator end(); + std::shared_ptr> get_file(); +private: + std::string sought; + std::shared_ptr> lines; + std::shared_ptr> file; +}; + +#endif + diff --git a/Chapter-15/15.35/main.cpp b/Chapter-15/15.35/main.cpp new file mode 100644 index 0000000..a9a1de3 --- /dev/null +++ b/Chapter-15/15.35/main.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include "TextQuery.h" +#include "Query.h" + +int main() +{ + std::ifstream ifs("C:\\Users\\jz\\Desktop\\1.txt"); + TextQuery tq1(ifs); + std::string s1, s2; + std::cin >> s1 >> s2; + Query q1(s1), q2(s2); + Query qand = q1 & q2; + Query qor = q1 | q2; + print(std::cout, q1.eval(tq1)) << std::endl; + print(std::cout, (~q1).eval(tq1)) << std::endl; + print(std::cout, qand.eval(tq1)) << std::endl; + print(std::cout, qor.eval(tq1)) << std::endl; + std::cout << q1.rep() << " " << q2.rep() << " " << qand.rep() << " " << qor.rep() << std::endl; + return 0; +} diff --git a/Chapter-15/chapter-15-answer.md b/Chapter-15/chapter-15-answer.md index 9728fd7..2225f69 100644 --- a/Chapter-15/chapter-15-answer.md +++ b/Chapter-15/chapter-15-answer.md @@ -198,3 +198,54 @@ Quote类 书上的版本 不一致,因为智能指针进行了动态绑定 * **练习15.30** +Quote类 书上的版本 +增加了Basket类 +[15.30 Quote.h程序代码](15.30/Quote.h) +[15.30 Quote.cpp程序代码](15.30/Quote.cpp) +[15.30 测试程序代码](15.30/main.cpp) + +* **练习15.31** +仅为示意 +(a) WordQuery(s1) WordQuery(s2) WordQuery(s3) OrQuery(s1, s2 & ~s3) NotQuery(s3) AndQuery(s2, ~s3) +(b) WordQuery(s1) WordQuery(s2) WordQuery(s3) OrQuery(s1, s2 & ~s3) NotQuery(s3) AndQuery(s2, ~s3) +(c) WordQuery(s1) WordQuery(s2) WordQuery(s3) WordQuery(s4) AndQuery(s1, s2) AndQuery(s3, s4) OrQuery(s1 & s2, s3 & s4) + +* **练习15.32** +拷贝,移动,赋值,销毁一个shared_ptr的指针 + +* **练习15.33** +Query_base无数据成员,仅拷贝,移动,赋值,销毁类本身 + +* **练习15.34** +``` +(a) +Query(const std::string &); +Query_base(); +WordQuery(const std::string &); +BinaryQuery(const Query &l, const Query &r, std::strin s); +AndQuery(const Query &left, const Query &right); +OrQuery(const Query &left, const Query &right); +(b) +Query::rep +WordQuery::rep +AndQuery::rep +OrQuery::rep +(c) +Query::eval +WordQuery::eval +AndQuery::eval +OrQuery::eval +``` + +* **练习15.35** +TextQuery类 书上的版本 +Query和继承类 书上的版本 +未定义的eval用了无意义的内容代替 +[15.35 TextQuery.h程序代码](15.35/TextQuery.h) +[15.35 TextQuery.cpp程序代码](15.35/TextQuery.cpp) +[15.35 Query.h程序代码](15.35/Query.h) +[15.35 Query.cpp程序代码](15.35/Query.cpp) +[15.35 测试程序代码](15.35/main.cpp) + +* **练习15.36** +