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: ";
}
}