C++ Premier Plus 6th edition - Programming excercise - Chapter16 - 10

main.cpp
练习版(函数的多重调用、STL容器操作方法、以及函数指针、稍复杂的容器类型表达等方面的掌握情况)
简版见后。

// has simple codes,here only want to practice more techniques
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <memory>

using namespace std;

struct Review
{
    string title;
    int rating;
    double price;
};

typedef vector<shared_ptr<Review>> vsr;

// prototype
bool FillReview(shared_ptr<Review> & rr);
void ShowReview(const shared_ptr<Review> & rr);
bool TworseThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2);
bool RworseThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2);
bool PworseThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2);
template<typename T>
void ShowbyUser(T& t);
void loopShow(void(*f)(vsr&), vsr& v);

int main()
{
    vsr books;

    //vector<Review> books;
    shared_ptr<Review> temp;
    while (FillReview(temp))
        books.push_back(temp);

    if (books.size() > 0)
    {
        cout << "\nThank you. You entered the following "
             << books.size() << " ratings:\n"
             << "Rating\tPrice\tBook\n";
        for_each(books.begin(), books.end(), ShowReview);
    }
	else
	{
		cout << "No entries. Bye!";
		cin.get();
		exit(EXIT_FAILURE);
	}

    // ask user to choose how to show results
    loopShow(ShowbyUser<vsr>, books);

	cout << "Bye!";
    cin.get();
	cin.get();
    return 0;
}

// fill
bool FillReview(shared_ptr<Review> & rr)
{
    // create a Review zone on heap
    Review* pr = new Review;

    // fill title
    std::cout << "Enter book title (quit to quit): ";
    std::getline(std::cin, pr->title);
    if (pr->title == "quit")
        return false;
    // fill rating
    std::cout << "Enter book rating: ";
    std::cin >> pr->rating;
    if (!std::cin)
    {
        // clear input queue,in case illegal-input-attempt to rating/price lelt in queue
        // and wrongly used by loopshow() in which there is a ch need to read from queue
		cerr << "Illegal input. This Review object failed to push to container. \n";
		cin.clear();
		while (std::cin.get() != '\n')
            continue;
        return false;
    }
    // fill price
    std::cout << "Enter book price: ";
    std::cin >> pr->price;
    if (!std::cin)
    {
        // clear input queue,in case illegal-input-attempt to rating/price lelt in queue
        // and wrongly used by loopshow() in which there is a ch need to read from queue
		cerr << "Illegal input. This Review object failed to push to container. \n";
		cin.clear();
		while (std::cin.get() != '\n')
            continue;
        return false;
    }
    // get rid of rest of input line
    while (std::cin.get() != '\n')
        continue;

    // initialize a temp shared_ptr with a pointer return by new
    shared_ptr<Review> temptr(pr);
    // initialize rr with this temp shared_ptr
    // heap zone pointed by temptr will not be released,as it's SHARED_ptr
    rr = temptr;
    // keep the heap zone
    //delete pr;
    return true;
}

// show, use as functor
void ShowReview(const shared_ptr<Review> & rr)
{
    std::cout << (*rr).rating
              << "\t" << (*rr).price
              << "\t" << (*rr).title << std::endl;
}

template<typename T>
void ShowbyUser(T& t)// accepts container type
{
    cout << "\nChoose which order you'd like to show the result:\n"
         << "1-original order\n"
         << "2-alphabetical order\n"
         << "3-increasing ratings\n"
         << "4-decreasing ratings\n"
         << "5-increasing price\n"
         << "6-decreasing price\n"
         << "7-quitting\n"
         << "Enter your choice(1~7): ";
    unsigned int choice;
    cin >> choice;
    // in case type dismatch,or user choose 'quitting'
    while (cin.good())
    {
        // use a bool value to quit while loop,
        // as 'break' only applies to innermost switch/loop
        // here is switch
        bool courier;
        switch (choice)
        {
        case 1:
        {
            cout << "Rating\tPrice\tBook\n";
            std::for_each(t.begin(), t.end(), ShowReview);
            courier = true;
        }

        break;
        case 2:
        {
            std::sort(t.begin(), t.end(), TworseThan);
            cout << "Rating\tPrice\tBook\n";
            std::for_each(t.begin(), t.end(), ShowReview);
            courier = true;
        }
        break;
        case 3:
        {
            std::sort(t.begin(), t.end(), RworseThan);
            cout << "Rating\tPrice\tBook\n";
            std::for_each(t.begin(), t.end(), ShowReview);
            courier = true;
        }
        break;
        case 4:
        {
            std::sort(t.begin(), t.end(), RworseThan);
            cout << "Rating\tPrice\tBook\n";
            std::for_each(t.rbegin(), t.rend(), ShowReview);
            courier = true;
        }
        break;
        case 5:
        {
            std::sort(t.begin(), t.end(), PworseThan);
            cout << "Rating\tPrice\tBook\n";
            std::for_each(t.begin(), t.end(), ShowReview);
            courier = true;
        }
        break;
        case 6:
        {
            std::sort(t.begin(), t.end(), PworseThan);
            cout << "Rating\tPrice\tBook\n";
            std::for_each(t.rbegin(), t.rend(), ShowReview);
            courier = true;
        }
        break;
        case 7:
        {
            cout << "You chose 'quit'. Bye!\n";
            courier = true;
        }
        break;
        default:
        {
            cout << "Num input out of range,Enter your choice(1~7) again: ";
            cin >> choice;
        }
        continue;
        }
        if (courier==true)
            break;// apply to innermost loop,here is while
    }
}

// string <, added new statements
bool TworseThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2)
{
    if ((*r1).title < (*r2).title)
        return true;
    else if ((*r1).title == (*r2).title && (*r1).rating < (*r2).rating)
        return true;
    // newly added
    else if ((*r1).title == (*r2).title && (*r1).rating == (*r2).rating && (*r1).price < (*r2).price)
        return true;
    else
        return false;
}

// rating <
bool RworseThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2)
{
    if ((*r1).rating < (*r2).rating)
        return true;
    else
        return false;
}

// price <
bool PworseThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2)
{
    if ((*r1).price < (*r2).price)
        return true;
    else
        return false;
}

// to make main() simple,use function pointer
void loopShow(void (*f)(vsr&), vsr& v)
{
    // ask user to choose how to show results
    cout << "\nYou're allowed to have different tries. Let's go!\n"
         << "(Y/y to continue, Q/q to quit the program.) \n";
    char ch;
    cin >> ch;
    // in case illegal input, only pass Y/y, Q/q
    while (!cin.good() || (tolower(ch) != 'y' && tolower(ch) != 'q'))
    {
        cout << "Illegal input,only Y/y or Q/q are allowed, try again: ";
        cin >> ch;
    }

    while (tolower(ch) == 'y')
    {
        f = ShowbyUser<vsr>;
        (*f)(v);
        cout << "\nWould you like to try other order of presentation?\n"
             << "(Y/y to continue, Q/q to quit the program.) \n";
        cin >> ch;
		// in case illegal input, only pass Y/y, Q/q
		while (!cin.good() || (tolower(ch) != 'y' && tolower(ch) != 'q'))
		{
			cout << "Illegal input,only Y/y or Q/q are allowed, try again: ";
			cin >> ch;
		}
    }
}

PS:补充于190215,尝试的精简版,水平有限只能缩减40行

// has simple codes,here only want to practice more techniques
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <memory>

using namespace std;
struct Review
{
    string title;
    int rating;
    double price;
};
typedef vector<shared_ptr<Review>> vsr;
typedef shared_ptr<Review> sr;

// PROTOTYPE,order of being used: loopshow(orderbyuser(caseBlock(ShowReview)))
bool FillReview(sr & rr);
// below 4 used in caseBlock()
bool TworseThan(const sr & r1, const sr & r2);
bool RworseThan(const sr & r1, const sr & r2);
bool PworseThan(const sr & r1, const sr & r2);
void ShowReview(const sr & rr);
// blow used in OrderbyUser()
enum Mode { inc_order, dec_order, ori_order }; // support caseBlock(),increasing,decreasing,original order
bool caseBlock(vsr& v, Mode mode, bool courier, bool(*pf)(const sr &, const sr &)=nullptr); // pf for sor(),mode for for_each()
// below used in looShow()
void OrderbyUser(vsr& v);
void loopShow(void(*f)(vsr&), vsr& v);

int main()
{
    vsr books;
    sr temp;
    while (FillReview(temp))
        books.push_back(temp);

    if (books.size() > 0)
    {
        cout << "\nThank you. You entered the following "
             << books.size() << " ratings:\n"
             << "Rating\tPrice\tBook\n";
        for_each(books.begin(), books.end(), ShowReview);
    }
    else
    {
        cout << "No entries. Bye!";
        cin.get();
        exit(EXIT_FAILURE);
    }
    // ask user to choose how to show results
    loopShow(OrderbyUser, books);

    cout << "Bye!";
    cin.get();
    cin.get();
    return 0;
}
// fill
bool FillReview(sr & rr)
{
    // create a Review zone on heap
    Review* pr = new Review;
    // fill title
    std::cout << "Enter book title (quit to quit): ";
    std::getline(std::cin, pr->title);
    if (pr->title == "quit")
        return false;
    // fill rating
    std::cout << "Enter book rating: ";
    std::cin >> pr->rating;
    if (!std::cin)
    {
        // clear input queue,in case illegal-input-attempt to rating/price lelt in queue
        // and wrongly used by loopshow() in which there is a ch need to read from queue
        cerr << "Illegal input. This Review object failed to push to container. \n";
        cin.clear();
        while (std::cin.get() != '\n')
            continue;
        return false;
    }
    // fill price
    std::cout << "Enter book price: ";
    std::cin >> pr->price;
    if (!std::cin)
    {
        // clear input queue,in case illegal-input-attempt to rating/price lelt in queue
        // and wrongly used by loopshow() in which there is a ch need to read from queue
        cerr << "Illegal input. This Review object failed to push to container. \n";
        cin.clear();
        while (std::cin.get() != '\n')
            continue;
        return false;
    }
    // get rid of rest of input line
    while (std::cin.get() != '\n')
        continue;
    // initialize a temp shared_ptr with a pointer return by new
    sr temptr(pr);
    // initialize rr with this temp shared_ptr
    // heap zone pointed by temptr will not be released,as it's SHARED_ptr
    rr = temptr;
    // keep the heap zone
    //delete pr;
    return true;
}
// string <, added new statements
bool TworseThan(const sr & r1, const sr & r2)
{
    if ((*r1).title < (*r2).title)
        return true;
    else if ((*r1).title == (*r2).title && (*r1).rating < (*r2).rating)
        return true;
    // newly added
    else if ((*r1).title == (*r2).title && (*r1).rating == (*r2).rating && (*r1).price < (*r2).price)
        return true;
    else
        return false;
}
// rating <
bool RworseThan(const sr & r1, const sr & r2)
{
    if ((*r1).rating < (*r2).rating)
        return true;
    else
        return false;
}
// price <
bool PworseThan(const sr & r1, const sr & r2)
{
    if ((*r1).price < (*r2).price)
        return true;
    else
        return false;
}
// show, use as functor,used in caseBlock()
void ShowReview(const sr & rr)
{
    std::cout << (*rr).rating
              << "\t" << (*rr).price
              << "\t" << (*rr).title << std::endl;
}
// statement block used in case
bool caseBlock(vsr& v,Mode mode, bool courier, bool(*pf)(const sr &, const sr &)) // pf for sor(),mode for for_each()
{
    cout << "Rating\tPrice\tBook\n";
    if (mode == ori_order)
    {
        vsr w = v;// use a copy, allow after show in different orders,still can show in original order
        std::for_each(w.begin(), w.end(), ShowReview);
        return courier = true;
    }
    // below is the situation:mode!=ori_order
    std::sort(v.begin(), v.end(), pf);// can use different functor
    if (mode == inc_order)// show in forward or backward order
        std::for_each(v.begin(), v.end(), ShowReview);
    else if (mode == dec_order)
        std::for_each(v.rbegin(), v.rend(), ShowReview);
    return courier=true;// always return ture,just send courier
}

void OrderbyUser(vsr& v)// accepts container type
{
	cout << "\nChoose which order you'd like to show the result:\n"
		<< "1-original order\n"
		<< "2-alphabetical order\n"
		<< "3-increasing ratings\n"
		<< "4-decreasing ratings\n"
		<< "5-increasing price\n"
		<< "6-decreasing price\n"
		<< "7-quitting\n"
		<< "Enter your choice(1~7): ";
	unsigned int choice;
	cin >> choice;
	// in case type dismatch,or user choose 'quitting'
	while (cin.good())
	{
		bool courier = true;// send signal to while
		switch (choice)
		{
		case 1:	caseBlock(v, ori_order, courier); break;
		case 2:	caseBlock(v, inc_order, courier, TworseThan);break;
		case 3:	caseBlock(v, inc_order, courier, RworseThan);break;
		case 4:	caseBlock(v, dec_order, courier, RworseThan);break;
		case 5:	caseBlock(v, inc_order, courier, PworseThan);break;
		case 6:	caseBlock(v, dec_order, courier, PworseThan);break;
		case 7:
		{
			cout << "You chose 'quit'. Bye!\n";
			courier = true;
		}
		break;
		default:
		{
			cout << "Num input out of range,Enter your choice(1~7) again: ";
			cin >> choice;
		}
		continue;
		}
		if (courier == true)
			break;// apply to innermost loop,here is while
	}
}
// to make main() simple,use function pointer
void loopShow(void(*f)(vsr&), vsr& v)
{
	// ask user to choose order of showing results
	cout << "\nYou're allowed to have different tries. Let's go!\n"
		<< "(Y/y to continue, Q/q to quit the program.) \n";
	// in case illegal input, only pass Y/y, Q/q
	char ch;
	while (cin >> ch && (!cin.good() || (tolower(ch) != 'y' && tolower(ch) != 'q')))
		cout << "Illegal input,only Y/y or Q/q are allowed, try again: ";
	while (tolower(ch) == 'y')
	{
		f = OrderbyUser;
		(*f)(v);
		cout << "\nWould you like to try other order of presentation?\n"
			<< "(Y/y to continue, Q/q to quit the program.) \n";
		while (cin >> ch && (!cin.good() || (tolower(ch) != 'y' && tolower(ch) != 'q')))
			cout << "Illegal input,only Y/y or Q/q are allowed, try again: ";
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值