C++ Primer Plus第六版编程题(第16章)

本篇博客主要介绍了C++ Primer Plus第六版中的编程练习,包括实现回文检测、数组排序、文件读取、模板函数、STL容器的操作等。通过示例详细讲解了如何处理字符串、vector和list,涉及排序算法的性能比较,并展示了如何在结构体中使用shared_ptr进行内存管理。

C++ Primer Plus第六版编程题(第16章)

题目

1.回文指的是顺读和逆读都一样的字符串。例如,“tot”和“otto”都是简短的回文。编写一个程序,让用户输入字符串,并将字符串引用传递给一个bool函数。如果字符串时回文,该函数将返回true,否则返回false.此时,不要担心诸如大小写、空格和标点符号这些复杂的问题。即这个简单的版本将拒绝 “Otto” 和 “Madam, I’m Adam”。请查看附录F中的字符串方法列表,以简化这项任务。

2.与编程练习1中给出的问题相同,但要考虑诸如大小写、空格和标点符号这样的复杂问题。即“Madam, I’m Adam”将作为回文来测试。例如,测试函数可能会将字符串缩略为“madamimadam”,然后测试倒过来是否一样。不要忘了有用的cctype库,您可能从中找到几个有用的STL函数,尽管不一定非要使用它们。

3.修改程序清单16.3,使之从文件中读取单词。一种方案是,使用vector< string>对象而不是string数组。这样便可以使用push_back()将数据文件中的单词复制到vector< string>对象中,并使用size()来确定单词列表的长度。由于程序应该每次从文件中读取一个单词,因此应使用运算符>>而不是getline()。文件中包含的单词应该用空格、制表符或换行符分隔。

4.编写一个具有老式风格接口的函数,其原型如下:

int reduce(long ar[], int n);

实参应是数组名和数组中的元素个数。该函数对数组进行排序,删除重复的值,返回缩减后数组中的元素数目。请使用STL函数编写该函数(如果决定使用通用的unique()函数,请注意它将返回结果区间的结尾)。使用一个小程序测试该函数。

5.问题与编程练习4相同,但要编写一个模板函数:

template< class T>

int reduce(T ar[], int n):

在一个使用long实例和string实例的小程序中测试该函数。

6.使用STL queue模板类而不是第12章的Queue类,重新编写程序清单12.12所示的示例。

7.彩票卡是一个常见的游戏。卡片上带编号的圆点,其中一些圆点被随机选中。编写一个lotto()函数,它接受两个参数。第一个参数是彩票卡上圆点的个数,第二个参数是随机选择的圆点个数。该函数返回一个vector对象,其中包含(按排列后的顺序)随机选择的号码。例如,可以这样使用该函数:

vector< int> winners;

winners = Lotto(51,6);

这样将把一个矢量赋给winner,该矢量包含1~51中随机选定的6个数字。注意,仅仅使用rand()无法完成这项任务,因它会生成重复的值。提示:让函数创建一个包含所有可能值的矢量,使用 random_shuffle(),然后通过打乱后的矢量的第一个值来获取值。编写一个小程序来测试这个函数。

8.Mat和Pat希望邀请他们的朋友来参加派对。他们要编写一个程序完成下面的任务。

  • 让Mat输入他朋友的姓名列表。姓名存储在一个容器中,然后按排列后的顺序显示出来。
  • 让Pat输入她朋友的姓名列表。姓名存储在另一个容器中,然后按排列后的顺序显示出来。
  • 创建第三个容器,将两个列表合并,删除重复的部分,并显示这个容器的内容。

9.相对于数组,在链表中添加和删除元素更容易,但排序速度更慢。这就引出了一种可能性:相对于使用链表算法进行排序,将链表复制到数组中,对数组进行排序,再将排序后的结果复制到链表中的速度可能更快;但这也可能占用更多的内存。请使用如下方法检验上述假设。

a. 创建大型vector< int>对象vi0,并使用rand()给它提供初始值。

b. 创建vector< int>对象vi和list< int>对象li,它们的长度都和初始值与vi0相同。

c. 计算使用STL算法sort()对vi进行排序所需的时间,再计算使用list的方法sort()对li进行排序所需的时间。

d. 将li重置为排序的vi0的内容,并计算执行如下操作所需的时间:将li的内容复制到vi中,对vi进行排序,并将结果复制到li中。

要计算这些操作所需的时间,可使用ctime库中的clock()。正如程序清单5.14演示的,可使用下面的语句来获取开始时间:

clock_t start = clock();

再在操作结束后使用下面的语句获取经过了多长时间:

clock_t end = clock();

cout << (double)(end - start)/CLOCKS_PER_SEC;

这种测试并非绝对可靠,因为结果取决于很多因素,如可用内存量、是否支持多处理以及数组(列表)的长度(随着要排序的元素数增加,数组相对于列表的效率将更明显)。另外,如果编译器提供了默认生成方式和发布生成方式,请使用发布生成方式。鉴于当今计算机的速度非常快,要获得有意义的结果,可能需要使用尽可能大的数组。例如,可尝试包含100000、1000000和10000000个元素。

10.请按如下方式修改程序清单16.9(vect3.cpp)。

a. 在结构Review中添加成员price。

b. 不使用vector< Review>来存储输入,而使用vector<shared_ptr< Review>>。别忘了,必须使用new返回的指针来初始化shared_ptr。

c.在输入阶段结束后,使用一个循环让用户选择如下方式之一显示书籍:按原始顺序显示、按字母表顺序显示、按评级升序显示、按评级降序显示、按价格升序显示、按价格降序显示、退出。

下面是一种可能的解决方案:获取输入后,再创建一个shared_ptr矢量,并用原始数组初始化它。定义一个对指向结构的指针进行比较的operator<()函数,并使用它对第二个矢量进行排序,让其中的shared_ptr按其指向的对象中的书名排序。重复上述过程,创建按rating和price排序的shared_ptr矢量。请注意,通过使用rbegin()和rend(),可避免创建按相反的顺序排列的shared_ptr矢量。

程序

#include <iostream>
#include <string>
using namespace std;

bool IsPlalindrome(const string &s);
int main()
{
	cout<<"Enter a string:\n";
	string s;
	getline(cin,s);
	while(cin&&s.size()>0)
	{
		if(IsPlalindrome(s))
			cout<<s<<" is a plalindrome.\n";
		else
			cout<<s<<" is not a plalindrome.\n";
		cout<<"Enter the next string:\n";
		getline(cin,s);
	}
	cout<<"Bye.\n";
	return 0;
 } 
 bool IsPlalindrome(const string &s)
 {
 	string r(s.rbegin(),s.rend());
 	return(s==r);
 }
#include <iostream>
#include <string>
#include <cctype>
using namespace std;

bool IsPlalindrome(const string &s);
int main()
{
   cout<<"Enter a string:\n";
   string s;
   getline(cin,s);
   while(cin&&s.size()>0)
   {
   	if(IsPlalindrome(s))
   		cout<<s<<" is a plalindrome.\n";
   	else
   		cout<<s<<" is not a plalindrome.\n";
   	cout<<"Enter the next string:\n";
   	getline(cin,s);
   }
   cout<<"Bye.\n";
   return 0;
} 
bool IsPlalindrome(const string &s)
{
	string temp;
	for(int i=0;i<s.length();i++)
	{
		if(isalpha(s[i]))
		{
			temp.push_back(tolower(s[i]));
   	 }
    }
	string r(temp.rbegin(),temp.rend());
	return(temp==r);
}
// hangman.cpp -- some string methods
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <vector>
#include <fstream>
using namespace std;

int main()
{
   ifstream fin;
   fin.open("wordlist.txt");
   if (fin.is_open() == false)
   {
   	cerr << "Can't open file. Bye.\n";
       exit(EXIT_FAILURE);
   } 
   vector<string> wordlist;
   string temp;
   while(fin>>temp)
   {
   	wordlist.push_back(temp);
   }
   fin.close();	
   const int NUM=wordlist.size();
   
   srand(time(0));
   char play;
   cout << "Will you play a word game? <y/n> ";
   cin >> play;
   play = tolower(play);
   while (play == 'y')
   {
       string target = wordlist[std::rand() % NUM];
       int length = target.length();
       string attempt(length, '-');
       string badchars;
       int guesses = 6;
       cout << "Guess my secret word. It has " << length
           << " letters, and you guess\n"
           << "one letter at a time. You get " << guesses
           << " wrong guesses.\n";
       cout << "Your word: " << attempt << endl;
       while (guesses > 0 && attempt != target)
       {
           char letter;
           cout << "Guess a letter: ";
           cin >> letter;
           if (badchars.find(letter) != string::npos
               || attempt.find(letter) != string::npos)
           {
               cout << "You already guessed that. Try again.\n";
                   continue;
           }
           int loc = target.find(letter);
           if (loc == string::npos)
           {
               cout << "Oh, bad guess!\n";
               --guesses;
               badchars += letter; // add to string
           }
           else
           {
               cout << "Good guess!\n";
               attempt[loc]=letter;
               // check if letter appears again
               loc = target.find(letter, loc + 1);
               while (loc != string::npos)
               {
                   attempt[loc]=letter;
                   loc = target.find(letter, loc + 1);
               }
          }
           cout << "Your word: " << attempt << endl;
           if (attempt != target)
           {
               if (badchars.length() > 0)
                   cout << "Bad choices: " << badchars << endl;
               cout << guesses << " bad guesses left\n";
           }
       }
       if (guesses > 0)
           cout << "That's right!\n";
       else
           cout << "Sorry, the word is " << target << ".\n";

       cout << "Will you play another? <y/n> ";
       cin >> play;
       play = tolower(play);
   }

   cout << "Bye\n";

   return 0; 
}
#include <iostream>
#include <algorithm>
using namespace std;
int reduce(long ar[],int n);

int main()
{
	long ar[10]={123,33,42,37,44,79,42,58,37,26};
	cout<<"The original array:\n";
	for(int i=0;i<10;i++)
	{
		cout<<ar[i]<<" ";
	}
	cout<<endl;
	int n=reduce(ar,10);
	cout<<"The reduced array:\n";
	for(int i=0;i<n;i++)
	{
		cout<<ar[i]<<" ";
	}
	cout<<endl;
	return 0;
}

int reduce(long ar[],int n)
{
	sort(ar,ar+n);
	long *last=unique(ar,ar+n);
	return last-ar;
}
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
template <class T>
int reduce(T ar[],int n);

int main()
{
	long ar[10]={123,33,42,37,44,79,42,58,37,26};
	cout<<"The original array:\n";
	for(int i=0;i<10;i++)
	{
		cout<<ar[i]<<" ";
	}
	cout<<endl;
	int n=reduce(ar,10);
	cout<<"The reduced array:\n";
	for(int i=0;i<n;i++)
	{
		cout<<ar[i]<<" ";
	}
	cout<<endl;
	
	string ar1[10]={"are","key","see","hi","grey","dear","see","left","key","buy"};
	cout<<"The second original array:\n";
	for(int i=0;i<10;i++)
	{
		cout<<ar1[i]<<" ";
	}
	cout<<endl;
	int n1=reduce(ar1,10);
	cout<<"The second reduced array:\n";
	for(int i=0;i<n;i++)
	{
		cout<<ar1[i]<<" ";
	}
	cout<<endl;
	return 0;
}

template <class T>
int reduce(T ar[],int n)
{
	sort(ar,ar+n);
	T *last=unique(ar,ar+n);
	return last-ar;
}
// bank.cpp -- using the Queue interface
// compile with queue.cpp
#include <iostream>
#include <cstdlib> // for rand() and srand()
#include <ctime>   // for time()
#include <queue>
using namespace std;

class Customer
{
private:
    long arrive;        // arrival time for customer
    int processtime;    // processing time for customer
public:
    Customer() : arrive(0), processtime (0){}
    void set(long when);
    long when() const { return arrive; }
    int ptime() const { return processtime; }
};
void Customer::set(long when)
{
    processtime = std::rand() % 3 + 1;
    arrive = when; 
}

const int MIN_PER_HR = 60;
bool newcustomer(double x); // is there a new customer?

int main()
{
    srand(time(0));    //  random initializing of rand()

    cout << "Case Study: Bank of Heather Automatic Teller\n";
    cout << "Enter maximum size of queue: ";
    int qs;
    cin >> qs;
    queue<Customer> line;         // line queue holds up to qs people

    cout << "Enter the number of simulation hours: ";
    int hours;              //  hours of simulation
    cin >> hours;
    // simulation will run 1 cycle per minute
    long cyclelimit = MIN_PER_HR * hours; // # of cycles

    cout << "Enter the average number of customers per hour: ";
    double perhour;         //  average # of arrival per hour
    cin >> perhour;
    double min_per_cust;    //  average time between arrivals
    min_per_cust = MIN_PER_HR / perhour;

    Customer temp;              //  new customer data
    long turnaways = 0;     //  turned away by full queue
    long customers = 0;     //  joined the queue
    long served = 0;        //  served during the simulation
    long sum_line = 0;      //  cumulative line length
    int wait_time = 0;      //  time until autoteller is free
    long line_wait = 0;     //  cumulative time in line


// running the simulation
    for (int cycle = 0; cycle < cyclelimit; cycle++)
    {
        if (newcustomer(min_per_cust))  // have newcomer
        {
            if (qs==line.size())
                turnaways++;
            else
            {
                customers++;
                temp.set(cycle);    // cycle = time of arrival
                line.push(temp); // add newcomer to line
            }
        }
        if (wait_time <= 0 && !line.empty())
        {
            temp=line.front();      // attend next customer
            wait_time = temp.ptime(); // for wait_time minutes
            line_wait += cycle - temp.when();
            served++;
            line.pop();
        }
        if (wait_time > 0)
            wait_time--;
        sum_line += line.size();
    }

// reporting results
    if (customers > 0)
    {
        cout << "customers accepted: " << customers << endl;
        cout << "  customers served: " << served << endl;
        cout << "         turnaways: " << turnaways << endl;
        cout << "average queue size: ";
        cout.precision(2);
        cout.setf(ios_base::fixed, ios_base::floatfield);
        cout << (double) sum_line / cyclelimit << endl;
        cout << " average wait time: "
             << (double) line_wait / served << " minutes\n";
    }
    else
        cout << "No customers!\n";
    cout << "Done!\n";
    // cin.get();
    // cin.get();
    return 0;
}

//  x = average time, in minutes, between customers
//  return value is true if customer shows up this minute
bool newcustomer(double x)
{
    return (std::rand() * x / RAND_MAX < 1); 
}
#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
using namespace std;
vector<int> Lotto(int cnum,int rnum);

int main()
{
	vector<int> winners;
	int cnum,rnum;
	cout<<"Enter a draw range: ";
	cin>>cnum;
	cout<<"The number you choose: ";
	cin>>rnum;
	winners=Lotto(cnum,rnum);
	for(auto n=winners.begin();n!=winners.end();n++)
	{
		cout<<*n<<" ";
	}
	cout<<"\nBye.\n";
	return 0;
}

vector<int> Lotto(int cnum,int rnum)
{
	vector<int> ticket;
	for(int i=0;i<cnum;i++)
	{
		ticket.push_back(i+1);
	}
	random_shuffle(ticket.begin(),ticket.end());
	vector<int> choose;
	for(int i=0;i<rnum;i++)
	{
		choose.push_back(ticket[i]);
	}
	return choose;
}

8.该题使用了两种方法,使用vector时应注意unique函数只是将重复元素放到末尾而并未删除,应再使用一个erase()函数将重复元素删除。
方法1:vector

//unique函数只是将重复元素放到末尾并未删除 
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
void show(const string &s);

int main()
{
	vector<string> matf,patf,tf;
	cout<<"Enter Mat's friends: \n";
	string temp;
	getline(cin,temp);
	while(temp!="quit")
	{
		matf.push_back(temp);
		tf.push_back(temp);
		getline(cin,temp);
	}
	cout<<"Mat's friends are:\n";
	sort(matf.begin(),matf.end());
	for_each(matf.begin(),matf.end(),show);
	cout<<endl;
	
	cout<<"Enter Pat's friends: \n";
	getline(cin,temp);
	while(temp!="quit")
	{
		patf.push_back(temp);
		tf.push_back(temp);
		getline(cin,temp);
	}
	cout<<"Pat's friends are:\n";
	sort(patf.begin(),patf.end());
	for_each(patf.begin(),patf.end(),show);
	cout<<endl;
	
	sort(tf.begin(),tf.end());
	vector<string>::iterator new_end; 
	new_end=unique(tf.begin(),tf.end());
	tf.erase(new_end,tf.end());
	cout<<"Total friends:\n";
	for_each(tf.begin(),tf.end(),show);
	return 0;
 } 
 
 void show(const string &s)
 {
 	cout<<s<<endl;
 }

方法2:list

#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
void show(const string &s){cout<<s<<endl;}

int main()
{
   list<string> matf,patf,tf;
   cout<<"Enter Mat's friends: \n";
   string temp;
   getline(cin,temp);
   while(temp!="quit")
   {
   	matf.push_back(temp);
   	tf.push_back(temp);
   	getline(cin,temp);
   }
   cout<<"Mat's friends are:\n";
   matf.sort();
   for_each(matf.begin(),matf.end(),show);
   cout<<endl;
   
   cout<<"Enter Pat's friends: \n";
   getline(cin,temp);
   while(temp!="quit")
   {
   	patf.push_back(temp);
   	tf.push_back(temp);
   	getline(cin,temp);
   }
   cout<<"Pat's friends are:\n";
   patf.sort();
   for_each(patf.begin(),patf.end(),show);
   cout<<endl;
   
   tf.sort();
   tf.unique();
   cout<<"Total friends:\n";
   for_each(tf.begin(),tf.end(),show);
   return 0;
} 
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <ctime>
#include <cstdlib>
using namespace std;
const int Num=1000000;

int main()
{
   srand(time(0));
   vector<int> vi0(Num);
   for(int i=0;i<Num;i++)
   	vi0[i]=rand();
   vector<int> vi(vi0);
   list<int> li(vi0.begin(),vi0.end());
   cout<<"sort() running time for vector<int>:\n";
   clock_t vstart=clock();
   sort(vi.begin(),vi.end());
   clock_t vend=clock();
   cout<<(double)(vend-vstart)/CLOCKS_PER_SEC<<"s.\n";
   
   cout<<"sort() running time for list<int>:\n";
   clock_t lstart=clock();
   li.sort();
   clock_t lend=clock();
   cout<<(double)(lend-lstart)/CLOCKS_PER_SEC<<"s.\n";
   
   cout<<"copy() and sort() running time:\n";
   copy(vi0.begin(),vi0.end(),li.begin());
   clock_t cstart=clock();
   copy(li.begin(),li.end(),vi.begin());
   sort(vi.begin(),vi.end());
   copy(vi.begin(),vi.end(),li.begin());
   clock_t cend=clock();
   cout<<(double)(cend-cstart)/CLOCKS_PER_SEC<<"s.\n";
   return 0;
}
// vect3.cpp -- using STL functions
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <memory>
using namespace std;

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

bool operator<(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2);
bool worseThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2);
bool betterThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2);
bool expensiveThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2);
bool cheapThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2);
bool FillReview(Review & rr);
void ShowReview(const shared_ptr<Review> & rr);
int main()
{
    vector<shared_ptr<Review>> books;
    Review temp;
    while (FillReview(temp))
    {
    	shared_ptr<Review> newtemp(new Review(temp));
        books.push_back(newtemp);
	}
    if (books.size() > 0)
    {
        cout << "Thank you. You entered the following "
             << books.size() << " ratings:\n"
              << "Rating\tprice\tBook\n";
        for_each(books.begin(), books.end(), ShowReview);
        
        cout<<"Please choose a type to show: "
        	<<"0 for original, 1 for alphabet, 2 for rating ascend,\n"
        	<<"3 for rating discend, 4 for price ascend, 5 for price discend, q for quit: ";
		int choose;
		while(cin>>choose)
		{
			switch(choose)
			{
				case 0:	break;
				case 1:	sort(books.begin(),books.end());
						break;
				case 2:	sort(books.begin(),books.end(),worseThan);
						break;
				case 3:	sort(books.begin(),books.end(),betterThan);
						break;
				case 4:	sort(books.begin(),books.end(),cheapThan);
						break;
				case 5:	sort(books.begin(),books.end(),expensiveThan);
						break;
				default:break;
			}
			for_each(books.begin(), books.end(), ShowReview);
			cout<<"Please choose a type to show: "
        		<<"0 for original, 1 for alphabet, 2 for rating ascend,\n"
        		<<"3 for rating discend, 4 for price ascend, 5 for price discend, q for quit: ";
		}
    }
    else
        cout << "No entries. ";
    cout << "Bye.\n";
    // cin.get();
    return 0;
}

bool operator<(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;
    else
        return false;
}

bool worseThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2)
{
    if (r1->rating < r2->rating)
        return true;
    else
        return false;
}

bool betterThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2)
{
	if (r1->rating > r2->rating)
        return true;
    else
        return false;
}

bool expensiveThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2)
{
	if(r1->price > r2->price)
		return true;
	else
		return false;
}

bool cheapThan(const shared_ptr<Review> & r1, const shared_ptr<Review> & r2)
{
	if(r1->price < r2->price)
		return true;
	else
		return false;
}

bool FillReview(Review & rr)
{
    cout << "Enter book title (quit to quit): ";
    getline(cin,rr.title);
    if (rr.title == "quit")
        return false;
    cout << "Enter book rating: ";
    cin >> rr.rating;
    cout<<"Enter book price: ";
    cin>>rr.price;
    if (!cin)
        return false;
    // get rid of rest of input line
    while (cin.get() != '\n')
        continue;
    return true;
}

void ShowReview(const shared_ptr<Review> & rr)
{
    cout << rr->rating << "\t" <<rr->price<<"\t"<< rr->title << endl; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值