Accelerated C++第十章課後習題(上)
阿新 • • 發佈:2019-01-08
這些題目都是個人寫的,肯定會有很多問題,歡迎指出錯誤。
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;
}
執行結果:這道題目的執行結果正好也可以包含上一道的,所以上一道的就沒貼。