//median.h 求中值 #ifndef median_H #define median_H #include <vector> double median(std::vector<double>); #endif
//median.cpp #include <algorithm> #include <vector> #include <stdexcept> using namespace std; double median(vector<double> vec) { typedef vector<double>::size_type vec_sz; vec_sz size=vec.size(); if(size==0) throw domain_error ("median of an empty vector"); sort(vec.begin(),vec.end()); vec_sz mid=size/2; return size%2==0?(vec[mid-1]+vec[mid])/2:vec[mid]; }
//Student_info.h #ifndef Student_info_H #define Student_info_H #include <iostream> #include <string> #include <vector> struct Student_info { std::string name; double midterm,fin; std::vector<double> homework; }; //for the names' sort(s1,s2,compare) bool compare(const Student_info& x,const Student_info& y); //read the students' info std::istream& read(std::istream& is,Student_info& s); //read the homework scores std::istream& read_hw(std::istream& is,std::vector<double>& hw); #endif
//grade.h #ifndef grade_H #define grade_H #include <vector> #include "Student_info.h" double grade(double midterm,double fin,double homework); double grade(double midterm,double fin,const std::vector<double>& hw); double grade(const Student_info& s); #endif
//grade.cpp #include <stdexcept> #include <vector> #include "grade.h" #include "median.h" #include "Student_info.h" using namespace std; double grade(double midterm,double fin,double homework) { return 0.2*midterm+0.4*fin+0.4*homework; } double grade(double midterm,double fin,const vector<double>& hw) { return grade(midterm,fin,median(hw)); } double grade(const Student_info& s) { return grade(s.midterm,s.fin,s.homework); }
//Student_info.cpp #include "Student_info.h" using namespace std; bool compare(const Student_info &x,const Student_info &y) { return x.name<y.name; } istream& read(istream& is,Student_info& s) { cout<<"input name,midterm,fin:"; is>>s.name>>s.midterm>>s.fin; cout<<endl<<"homework score:"; read_hw(is,s.homework); return is; } istream& read_hw(istream& is,vector<double>& hw) { if(is) { hw.clear(); double x; while(is>>x) hw.push_back(x); is.clear(); } return is; }
//main.cpp #include <algorithm> #include <iomanip> #include <ios> #include <iostream> #include <stdexcept> #include <string> #include <vector> #include "grade.h" #include "Student_info.h" using namespace std; int main() { vector<Student_info> students; Student_info record; string::size_type maxlen=0;//the longest name size while(read(cin,record)) { maxlen=max(maxlen,record.name.size()); students.push_back(record); } sort(students.begin(),students.end(),compare); //output for(vector<Student_info>::size_type i=0; i!=students.size();++i) { cout<<students[i].name <<string(maxlen+1-students[i].name.size(),' '); try { double total=grade(students[i]); streamsize prec=cout.precision(); cout<<setprecision(4)<<total<<setprecision(prec)<<endl; } catch(domain_error e) { cout<<e.what(); } } cout<<endl; return 0; }input name,midterm,fin:tianya 99 98homework score:98 97 96input name,midterm,fin:haijiao 98 99homework score:99 99 99
haijiao 98.8
tianya 97.8lyj@qt:~/Desktop/4/bin/Debug$
4-1. We noted in §4.2.3/65 that it is essential that the argument types in a call to max match exactly. Will the following code work? If there is a problem, how would you fix it?int maxlen; Student_info s; max(s.name.size(), maxlen);Ans;该程序会正常work的。因为string::size_type实质是一无符号整数类型,另外当普通整数和无符号整数在表达式结合在一起时,普通整数会被自动转为无符号整数。
Ans:setw(n),设置位于其后的字段的域宽;如果该字段宽度小于设置的值n,则用空格补齐(默认右对齐,设置左对齐则用left指示即可);如果该字段宽度大于设置的n值,则忽略setw(n)设置。
#include <iostream> #include <iomanip> using namespace std; int main() { int f; for(int i=1;i<=100;++i) { cout<<i<<setw(7)<<i*i<<endl; } return 0; }lyj@qt:~/Desktop$ g++ 2.cpp -o 2
........
Ans:由4-2分析可知,为了具有更好适应性,设置域宽为,这样即使最后一列999宽为3,仍然与第二列有两个空白间隔。程序修改如下:
#include <iostream> #include <iomanip> using namespace std; int nSize(int n) { int k=0; while(n>0) { n/=10; ++k; } return k; } int main() { int f,n=999; for(int i=1;i<=n;++i) { cout<<setw( nSize(n)+2 )<<setiosflags(ios::left)<<i<<i*i<<endl; } return 0; }
998 996004
999 998001
lyj@qt:~/Desktop$
4-4. Now change your squares program to use double values instead of ints. Use manipulators to manage the output so that the values line up in columns.
#include <iostream> #include <iomanip> using namespace std; int nSize(int n) { int k=0; while(n>0) { n/=10; ++k; } return k; } int main() { double f,n=99,k=0;//修改int为double for(double i=1;i<=n;i=i+0.5)//修改i=i+0.5 { cout<<setw( nSize(n)*3 )<<setiosflags(ios::left)<<i<<i*i<<endl;//修改setw(nSize(n)*3 } return 0; }
//read.h //read the words and save it into the vector #ifndef read_H #define read_H #include <vector> #include <iostream> #include <string> int read(std::istream& in,std::vector<std::string>& words); #endif
//read.cpp #include "read.h" using std::string;using std::vector;using std::istream;using std::cout; int read(istream& in,vector<string>& words) { string word; cout<<"input words:"; while(in>>word) words.push_back(word); int maxlen=0; for(vector<string>::const_iterator it=words.begin(); it!=words.end();++it) { string::size_type tmp; tmp=(*it).size(); if(maxlen<tmp) maxlen=tmp; } return maxlen; }
//mian #include <iostream> #include <vector> #include "read.h" using namespace std; int main() { vector<string> words; int n=read(cin,words); cout<<"the total words is:"<<words.size()<<endl; vector<string>::const_iterator i,j,first=words.begin(),second=words.end(); for(i=first;i!=second;++i) { string tmpi=*i; int k=1; for(j=i+1;j!=second;++j) { string tmpj=*j; if(tmpi==tmpj) ++k; } cout<<tmpi<<string(n-tmpi.size()+1,' ')<<k<<endl;//string(n,' ')word和其出现次数之间有合适的间隔 } return 0; }input words:I am a handsome boy , not a girl !
//median.h #ifndef median_H #define median_H #include <vector> double median(std::vector<double>); #endif
//median.cpp #include <algorithm> #include <vector> #include <stdexcept> using namespace std; double median(vector<double> vec) { typedef vector<double>::size_type vec_sz; vec_sz size=vec.size(); if(size==0) throw domain_error ("median of an empty vector"); sort(vec.begin(),vec.end()); vec_sz mid=size/2; return size%2==0?(vec[mid-1]+vec[mid])/2:vec[mid]; }
//grade.h #ifndef grade_H #define grade_H #include <vector> #include "Student_info.h" double grade(double midterm,double fin,double homework); double grade(double midterm,double fin,const std::vector<double>& hw); double grade(const Grade& s); #endif
//grade.cpp #include <stdexcept> #include <vector> #include "grade.h" #include "median.h" #include "Student_info.h" using namespace std; double grade(double midterm,double fin,double homework) { return 0.2*midterm+0.4*fin+0.4*homework; } double grade(double midterm,double fin,const vector<double>& hw) { return grade(midterm,fin,median(hw)); } double grade(const Grade& s) { return grade(s.midterm,s.fin,s.homework); }
//Student_info.h #ifndef Student_info_H #define Student_info_H #include <iostream> #include <string> #include <vector> struct Student_info { std::string name; double total;//最终成绩 }; struct Grade//成绩结构体 { double midterm,fin; std::vector<double> homework; }; //for the names' sort(s1,s2,compare) bool compare(const Student_info& x,const Student_info& y); //read the students' info std::istream& read(std::istream& is,std::string name,Grade& s); //read the homework scores std::istream& read_hw(std::istream& is,std::vector<double>& hw); #endif
//Student_info.cpp #include "Student_info.h" using namespace std; bool compare(const Student_info &x,const Student_info &y) { return x.name<y.name; } istream& read(istream& is,string name,Grade& s)//输入姓名name和成绩结构(midterm,fin,homework) { cout<<"input name,midterm,fin:"; is>>name>>s.midterm>>s.fin; cout<<endl<<"homework score:"; read_hw(is,s.homework); return is; } istream& read_hw(istream& is,vector<double>& hw) { if(is) { hw.clear(); double x; while(is>>x) hw.push_back(x); is.clear(); } return is; }
//main.cpp #include <algorithm> #include <iomanip> #include <ios> #include <iostream> #include <stdexcept> #include <string> #include <vector> #include "grade.h" #include "Student_info.h" using namespace std; int main() { vector<Student_info> students; Student_info student; Grade record; string::size_type maxlen=0;//the longest name size while(read(cin,student.name,record)) { maxlen=max(maxlen,student.name.size()); try { double finalGrade=grade(record); student.total=finalGrade; } catch(domain_error e) { cout<<e.what(); } students.push_back(student); } sort(students.begin(),students.end(),compare); //output cout<<"total is:"<<endl; for(vector<Student_info>::size_type i=0; i!=students.size();++i) { streamsize prec=cout.precision(); cout<<setprecision(4)<<students[i].total<<setprecision(prec)<<endl; } cout<<endl; return 0; }
lyj@qt:~/Desktop$ ./4
input name,midterm,fin:tianya 99 98
homework score:98 99 99
input name,midterm,fin:sanzang 97 98
homework score:97 98 99
98.6
97.8
4-7. Write a program to calculate the average of the numbers stored in a vector<double>.
#include <iostream> #include <vector> using namespace std; int main() { double n; vector<double> vec; while(cin>>n) vec.push_back(n); typedef vector<double>::size_type sz; sz size=vec.size(); double avg=0; for(vector<double>::const_iterator it=vec.begin(); it!=vec.end();++it) avg+=(*it); cout<<"avg="<<avg/size<<endl; return 0; }lyj@qt:~/Desktop$ g++ 7.cpp -o 7
4-8. If the following code is legal, what can we infer about the return type of f?
double d = f()[n];Ans:从double d=f(0[n]可以看出,该表达式的结果为一个double值,对f()[n],将f()看做arr,即arr[n],实际上是一个数组第n项的值;而arr是一个数组名,也表示数组的首地址,所以f()其实可以表示为f()=arr,故f()返回的是一个指针类型。
如下:
#include <iostream> using namespace std; double *f() { static double arr[7]={1,2,3,4,5,6,7}; return arr; } int main() { for(int i=0;i!=7;++i) { double d=f()[i]; cout<<"f()["<<i<<"]="<<d<<endl; } return 0; }lyj@qt:~/Desktop$ g++ 7.cpp -o 7