1. 程式人生 > >Accelerated C++第十章課後習題(上)

Accelerated C++第十章課後習題(上)

  這些題目都是個人寫的,肯定會有很多問題,歡迎指出錯誤。

10-0   編譯,執行並測試本章中的例程。    < 略>

10-1   重寫9.6節的學生成績,可以生成字母成績。

       由於是要修改書上的程式碼,程式碼比較長,而且直接就將老師給的書上的原始碼拿來進行了寫修改,老師給的課本原始碼是多檔案,所以這裡也用的是多檔案。

median.h

#ifndef GUARD_median_h
#define GUARD_median_h

#include <algorithm>
#include <stdexcept>
#include <vector>

using std::domain_error;
using std::sort;
using std::vector;
template <class T>
T median(vector<T> v)
{
	typedef typename vector<T>::size_type vec_sz;

	vec_sz size = v.size();
	if (size == 0)
		throw domain_error("median of an empty vector");

	sort(v.begin(), v.end());

	vec_sz mid = size/2;

	return size % 2 == 0 ? (v[mid] + v[mid-1]) / 2 : v[mid];
}
#endif

grade.h

#ifndef GUARD_grade_h
#define GUARD_grade_h

// `grade.h'
#include <vector>

double grade(double, double, double);
double grade(double, double, const std::vector<double>&);

#endif

grade.cpp

#include <vector>
#include <stdexcept>

using std::domain_error;
using std::vector;

#include "grade.h"
#include "median.h"

// compute a student's overall grade from midterm and final exam grades and homework grade
double grade(double midterm, double final, double homework)
{
	return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}

// compute a student's overall grade from midterm and final exam grades
// and vector of homework grades.
// this function does not copy its argument, because `median' does so for us.
double grade(double midterm, double final, const vector<double>& hw)
{
	if (hw.size() == 0)
		throw domain_error("student has done no homework");
	return grade(midterm, final, median(hw));
}


Student_info.h

#ifndef GUARD_Student_info
#define GUARD_Student_info

#include <string>
#include <vector>

class Student_info {
public:
	Student_info();              // construct an empty `Student_info' object
	Student_info(std::istream&); // construct one by reading a stream
	std::string name() const { return n; }
	bool valid() const { return !homework.empty(); }

	// as defined in 9.2.1/157, and changed to read into `n' instead of `name'
	std::istream& read(std::istream&);

	double grade() const;    // as defined in 9.2.1/158
private:
	std::string n;
	double midterm, final;
	std::vector<double> homework;
};

bool compare(const Student_info&, const Student_info&);

#endif


Student_info.cpp

#include <iostream>
#include <vector>

#include "grade.h"
#include "Student_info.h"

using std::istream;
using std::vector;

double Student_info::grade() const
{
	return ::grade(midterm, final, homework);
}

bool compare(const Student_info& x, const Student_info& y)
{
	return x.name() < y.name();
}

Student_info::Student_info(): midterm(0), final(0) { }

Student_info::Student_info(istream& is) { read(is); }	

// read homework grades from an input stream into a `vector<double>'
istream& read_hw(istream& in, vector<double>& hw)
{
	if (in) {
		// get rid of previous contents
		hw.clear();

		// read homework grades
		double x;
		while (in >> x)
			hw.push_back(x);

		// clear the stream so that input will work for the next student
		in.clear();
	}
	return in;
}

istream& Student_info::read(istream& in)
{
	in >> n >> midterm >> final;
	read_hw(in, homework);
	return in;
}


main.cpp

#include <algorithm>
#include <iomanip>

#include <ios>

#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

using std::max;

#include "Student_info.h"
#include "median.h"

using std::cin;                    using std::cout;
using std::domain_error;           using std::endl;
using std::setprecision;           using std::setw;
using std::sort;                   using std::streamsize;
using std::string;                 using std::vector;

int main()
{
	vector<Student_info> students;
	Student_info record;
	string::size_type maxlen = 0;

	// read and store the data
	while (record.read(cin)) {                           // changed
		maxlen = max(maxlen, record.name().size());      // changed
		students.push_back(record);
	}

	// alphabetize the student records
	sort(students.begin(), students.end(), compare);

	// write the names and grades
	for (vector<Student_info>::size_type i = 0;
		i != students.size(); ++i) {
			cout << students[i].name()   // this and the next line changed
				<< string(maxlen + 1 - students[i].name().size(), ' ');
			try {
				double final_grade = students[i].grade();   // changed
				switch((int)final_grade/10)
				{
				case 10:cout<<"A"<<endl;break;
				case 9:cout<<"A"<<endl;break;
				case 8:cout<<"B"<<endl;break;
				case 7:cout<<"C"<<endl;break;
					cout<<"D"<<endl;
				}
			} catch (domain_error e) {
				cout << e.what() << endl;
			}
	}
	return 0;
}


 

10-2   重寫8.1.1節中的mdian函式,使之可以通過向量或者C++自帶陣列以呼叫該函式。該函式要求可以呼叫容納有任何算術型別的容器。

       分析:因為可以用於vector,list,以及C++自帶的陣列等容器,所以對原來只適用於向量的函式需要進行修改。可以考慮將vector,list,自帶陣列中的元素傳遞給median函式後,將裡邊的元素複製到一個新的向量中,而median函式本來就是對一個向量進行操作的。

程式碼:

#include<iostream>
#include<vector>
#include<stdexcept>
#include<algorithm>
#include<list>
#include<iterator>

using namespace std;

template<typename T,typename P>
T median(T con,P begin,P end)
{

	vector<T>V;
	copy(begin,end,back_inserter(V));
	if(V.size()==0)
		throw domain_error("median is empty");
	sort(V.begin(),V.end());
	int mid=V.size()/2;
	return V.size()%2==0?(V[mid]+V[mid-1])/2:V[mid];
}

int main()
{
	int q[10];
	vector<int> vec;
	list<int> lis;
	int a,i=0;
	while(cin>>a)
	{
		*(q+i)=a;
		i++;
		vec.push_back(a);
		lis.push_back(a);
	}

	int t1=median(q[0],q,q+i);
	cout<<"using array:"<<endl;
	cout<<t1<<endl;


	int t2=median(vec[0],vec.begin(),vec.end());
	cout<<"using vector:"<<endl;
	cout<<t2<<endl;
	
	int t3=median(*lis.begin(),lis.begin(),lis.end());
	cout<<"using list:"<<endl;
	cout<<t3<<endl;
    return 0;
}


10-3  寫一個測試程式驗證剛才寫的median函式,確保呼叫median函式時不會改變容器內的元素的先後順序。

      分析:因為是將容器中的元素複製到了median函式中的新建vector中,所以肯定不會改變裡邊的元素順序,就是簡單寫個測試程式輸出原來容器中的元素。

程式碼:

#include<iostream>
#include<vector>
#include<stdexcept>
#include<algorithm>
#include<list>
#include<iterator>

using namespace std;

template<typename T,typename P>
T median(T con,P begin,P end)
{

	vector<T>V;
	copy(begin,end,back_inserter(V));
	if(V.size()==0)
		throw domain_error("median is empty");
	sort(V.begin(),V.end());
	int mid=V.size()/2;
	return V.size()%2==0?(V[mid]+V[mid-1])/2:V[mid];
}

int main()
{
	int q[10];
	vector<int> vec;
	list<int> lis;
	int a,i=0;
	while(cin>>a)
	{
		*(q+i)=a;
		i++;
		vec.push_back(a);
		lis.push_back(a);
	}

	int t1=median(q[0],q,q+i);
	cout<<"using array:"<<endl;
	cout<<t1<<endl;
	for(int j=0;j<i;j++)
		cout<<*(q+j)<<" ";
	cout<<endl<<endl;


	int t2=median(vec[0],vec.begin(),vec.end());
	cout<<"using vector:"<<endl;
	cout<<t2<<endl;
	for(int j=0;j<i;j++)
		cout<<vec[j]<<" ";
	cout<<endl<<endl;
	
	int t3=median(*lis.begin(),lis.begin(),lis.end());
	cout<<"using list:"<<endl;
	cout<<t3<<endl;
	for(list<int>::iterator it=lis.begin();it!=lis.end();it++)
		cout<<*it<<" ";
	cout<<endl;
    return 0;
}

執行結果:這道題目的執行結果正好也可以包含上一道的,所以上一道的就沒貼。