Accelerated C++:通过示例进行编程实践——练习解答(第4章)

4-0. Compile, execute, and test the programs in this chapter.分模块实现各部分功能,初步了解组织大型程序设计方法
//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.8

lyj@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实质是一无符号整数类型,另外当普通整数和无符号整数在表达式结合在一起时,普通整数会被自动转为无符号整数。

4-2. Write a program to calculate the squares of int values up to 100. The program should write two columns: The first lists the value; the second contains the square of that value. Use setw (described above) to manage the output so that the values line up in columns.

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
lyj@qt:~/Desktop$ ./2
1           1
2           4
3           9
4          16
5          25
6          36
7          49

........

4-3. What happens if we rewrite the previous program to allow values up to but not including 1000 but neglect to change the arguments to setw? Rewrite the program to be more robust in the face of changes that allow i to grow without adjusting the setw arguments.

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

4-5. Write a function that reads words from an input stream and stores them in a vector. Use that function both to write programs that count the number of words in the input, and to count how many times each word occurred.
//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 !     
the total words is:10
I                 1
am             1
a                2
handsome 1
boy            1
,                 1
not             1
a                1
girl             1
!                 1
lyj@qt:~/Desktop/1/bin/Debug$ 
4-6. Rewrite the Student_info structure to calculate the grades immediately and store only the final grade.
//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
lyj@qt:~/Desktop$ ./7
1.2 3.4 6 7.8 9 10
avg=6.23333
lyj@qt:~/Desktop$ 

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
lyj@qt:~/Desktop$ ./7
f()[0]=1
f()[1]=2
f()[2]=3
f()[3]=4
f()[4]=5
f()[5]=6
f()[6]=7
lyj@qt:~/Desktop$ 

你可能感兴趣的:(C++,C++,Accelerated,Accelerated,C++习题解答,通过示例进行编程实践)