C++ Primer Plus(第 6 版)第二至九章课后习题答案

转载公众号: iDoitnow 用于学习笔记使用。

目录

第二章课后习题答案

复习题

编程练习

 第三章课后习题答案

复习题

编程练习

第四章课后习题答案 

复习题

编程练习

 第五章课后习题答案 

复习题

编程练习

第六章课后习题答案 

复习题

编程练习

第七章课后习题答案 

复习题

编程练习

第八章课后习题答案 

复习题

编程练习

第九章课后习题答案 

复习题

编程题

第十章课后习题答案 

复习题

编程练习

第十一章课后习题答案

复习题

编程练习

 第十二章课后习题答案

复习题

编程练习

第十三章课后习题答案

复习题

编程练习

第十四章课后习题答案

复习题

编程练习

第十五章课后习题答案

复习题

编程练习

第十六章课后习题答案

复习题

编程练习

第十七章课后习题答案

复习题

编程练习

第十八章课后习题答案

复习题

编程练习


第二章课后习题答案

复习题

1.c++程序模块叫什么?

叫做函数。

2.下面的预处理编译器指令是做什么用的?

#include<iostream>

在最终编译之前,将iostream里的文件内容替换该编译指令。

3.下面语句是做什么用的?

using namespace std;

使程序使用std名称空间的定义。

4.什么语句可以用来打印“Hello,world”,然后打印新的一行?

cout<<"Hello,world\n";  //或者cout<<"Hello,world"<<endl;

5.什么语句可以用来创建名为cheeses的整数变量?

int cheeses;

6.什么语句可以用来将32赋值给变量cheeses?

cheeses=32;

7.什么语句可以用来将键盘输入的值读入变量cheeses中?

cin>>cheeses;

8.什么语句可以用来打印“We have X varieties of cheeses”,其中X为变量cheese的当前值。

cout<<"We have "<<cheeses<<"varieties of cheeses"<<endl;

9.下面的函数原型指出关于函数的哪些信息?

int froop(double t);
void rattle(int n);
int prune(void);
  • int froop(double)
    指出函数在调用时需要输入一个double类型的参数,函数返回一个int类型值。

  • void rattle(int n)
    指出函数在调用的时候需要输入一个int类型参数,且该函数无返回值。

  • int prune(void)
    指出函数不接收任何输入参数,函数返回一个int值。

10.定义函数时,什么情况下不必使用关键字return?

当函数的返回值类型为void的时,不用在函数中使用return。

11.假设你编写的main()函数包含如下代码:cout<<"Please enter your PIN:",而编译器指出cout是一个未知标识符。导致这种问题的原因很可能是什么?指出3种修复这种问题的方法。

可能原因:

没有#include<iostream>,或未使用using namespace std

解决方法:
1.添加#include<iostream>,在main()函数外使用using namespace std;
2.添加include<iostream>,使用using std::cout<<"Please enter your PIN:";
3.添加include<iostream>,使用std::cout << "Please enter your PIN:";

编程练习

1.编写一个c++程序,它显示您的姓名和地址。

#include<iostream>
using namespace std;
int main()
{
    cout<<"My name is iDoit,my address is BLABLA.."<<endl;
    return 0;
}

2.编写一个c++程序,它要求用户输入一个以long为单位的距离,然后将它转换为码(一long等于200码)。

#include<iostream>
using namespace std;
 int main()
{
    int longNum=0;
    cout<<"Please enter distance(long): ";
    cin>>longNum;
    cout<<"You input "<<longNum<<" long"<<endl;
    cout<<longNum<<"long = "<<longNum*220<<" 码"<<endl;
    return 0;
}     

3.编写一个c++程序,他使用3个用户定义的函数(包括main(),并生成下面的输出:

Three blind mice
Three blind mice
See how they run
See how they run

其中一个函数要调用两次,该函数生成前两行;另外一个函数也调用两次,并生成其余的输出。

#include<iostream>
using namespace std;
void A_function()
{    cout<<"Three blind mice"<<endl;    }
void B_function()
{    cout<<"See how they run"<<endl;   }
int main()
{
    A_function();
    A_function();
    B_function();
    B_function();
    return 0;
}

4.编写一个程序,让用户输入其年龄,然后显示该年龄包含多少个月,如下图所示:

Enter your age:29

#include<iostream>
using namespace std;
int main()
{
    int age;
    cout<<"Enter your  age:";
    cin>>age;
    cout<<"your age include "<<age*12<<" months."<<endl;
    return 0;
}

5.编写一个程序,其中main()调用一个用户定义的的函数(以摄氏温度值为参数,并返回相应的华氏温度值)。该程序按下面的格式要求用户输入摄氏温度值,并显示结果:

Please enter a Celsius value:20
20 degrees Celsius is 69 degrees Fahrenheit.

下面是转换公式:

华氏温度=1.8*摄氏温度+32.0

#include<iostream>
using namespace std;
double CtoF(double C)
{
    double F=1.8*C+32.0;
    return F;
}
int main()
{
    double celsiusValue,fahrenheitValue;
    cout<<"Please enter a Celsius value: ";
    cin>>celsiusValue;
    fahrenheitValue=CtoF(celsiusValue);
    cout<<celsiusValue<<" degrees Celsius is  "<<fahrenheitValue<<" degress Fahrenheit"<<endl;
}

6.编写一个程序,其main()调用一个用户的函数(以光年为参数,并返回对应天文单位的值)。该程序按下面的格式要求用户输入光年值,并显示结果:

Enter the number of light years: 4.2
4.2 light years =265608 astronomical units.

天文单位是从地球到太阳的平均距离(约150000000公里或93000000英里),光年是光一年走的距离(约10万亿公里或6万亿英里)(除太阳外,最近的恒星大约离地球4.2光年)。请使用double类型,转换公式为:1光年=63240天文单位。

#include<iostream>
using namespace std;
double LYtoAU(double lightYears)
{
    double astroUnits=lightYears*63240;
    return astroUnits;
}
int main()
{
    double lightYears;
    cout<<"Enter the number of light years: ";
    cin>>  lightYears;
    double astroYears=LYtoAU(lightYears);
    cout<<lightYears<<" light Years ="<<astroYears<<" astronomical units"<<endl;
    return 0;
}

7.编写一个程序,要求用户输入小时数和分钟数,在main()函数中,将这两个值传递给一个void函数,后者以下面这样的格式显示这两个值:

Enter the number of hours: 9
Enter the number of minutes: 28
Time: 9:28

#include<iostream>
using namespace std;
void Time(int hours,int minutes)
{
    cout<<"Time: "<<hours<<":"<<minutes<<endl;
}
int main()
{
    int hours,minutes;
    cout<<"Enter the number of hours: ";
    cin>>hours;
    cout<<"Enter the number of minutes: ";
    cin>>minutes;
    Time(hours,minutes);
    return 0;
}

 第三章课后习题答案

复习题

1.为什么c++有多种整形?

有多种整形类型,可以根据特定需求选择最合适的类型。例如,可以使用short来存储空格,使用long来确保存储容量,也可以寻找可提高特定计算的速度的类型。

2.声明与下述描述相符的变量。

a.short整数,值为80
b.unsigned int整数,值为42110
c.值为3000000000的整数

short a=80;       //or short int a=80;
unsigned int b=42110;    //or unsigned b=42110;
unsigned long long c=3000000000;    //or unsigned long c=3000000000;
//(注意:不要指望int变量能够存储300000000)

3.c++提供了什么措施来防止超出整形的范围?

c++没有提供自动防止超出整型限制的功能,可以使用头文件climits来确定限制情况。

4.33L与33之间有什么区别?

常量33L的类型为long,常量33类型为int。

5.下面两条c++语句是否等价?

char grade =45;
char grade = 'A';
这两条语句并不真正等价,虽然对于某些系统来说,他们是等效的。最重要的是,只有在使用ASCII码的系统上,第一条语句才将得分设置为字母A,而第二条语句还可用于使用其他编码的系统。其次,65是一个int常量,而‘A’是一个char常量。

6.如何使用c++来找出编码88表示的字符?指出至少两种方法。

//method 1
char c=88;
cout<<c<<endl;
//method 2
cout.put(char(88));
//method 3
cout<<char(88)<<endl; //new-style type cast value to char
cout<<(char)88<<endl; //old-style type cast value to char

7.将long赋值给float变量会导致舍入误差,将long值赋给double变量呢?将long long值赋给double变量呢?

这个问题取决于这两个类型的长度。如果long为4个字节,则没有损失。因为最大的long值是20亿,及有10位数。由于double提供至少13位有效数字,因而不需要进行任何舍入。long long类型可提供19位有效数字,超过了double保证的13位有效数字。

8.下列c++表达式的结果分别是多少?

a.89+2 b.63/4
c.3/46 d.6.03/4
e.15%4

a=74;b=4;c=0;d=4.5;e=3

9.假设x1和x2是两个double变量,你要将他们作为整数相加,再将结果赋给一个整型变量。请编写一条完成这项任务的c++语句。如果要将他们作为double值相加并转换为int呢?

int a=(int)x1+(int)x2;
int a=int(x1)+int(x2);

要将他们作为double类型相加,在进行转换,可采取下述方式之一:

int a=(int)(x1+x2);
int a=int(x1+x2);

10.下面每一条语句的变量都是什么类型?

a.auto cars=15;
b.auto iou=150.37f;
c.auto level='B';
d.auto crat=U'/U00002155';
e.auto fract=8.25f/2.5;

a. int
b. float
c. char
d. char32_t
e. double

编程练习

1.编写一个小程序,要求用户使用一个整数指出自己的身高(单位为英寸),然后将身高转换为英尺,该程序使用下划线字符来指示输入位置。另外,使用一个const符号来表示转换因子。

#include <iostream>

const double Inch_per_feet = 12.0;
using namespace std;
int main(void)
{
    cout << "Please enter your height:_____\b\b\b\b\b";
    double ht_inch;
    cin >> ht_inch;

    double ht_feet = ht_inch/Inch_per_feet;
    cout << "Your height is:" << ht_feet << " feets<<endl";    

    return 0;
}

2.编写一个程序,要求以几英尺几英寸的方式输入其身高,并以磅为单位输入其体重。(使用3个变量来存储这些信息。)该程序报告其BMI(Body Mass Index ,体重指数)。为了计算BMI,该程序以英寸的方式指出用户的身高(一英尺为十二英寸),并将以英寸为单位的身高身高转换为以米为单位的身高(1英寸=0.0254米)。然后,将以磅为单位的体重转换为千克为单位的体重(1千克=2.2磅)。最后,计算相应的BMI-体重(千克)除以身高(米)的平方。用符号常量表示各种转换因子。

#include <iostream>
using namespace std;
const double Inch_per_feet = 12.0;
const double Meter_per_inch = 0.0254;
const double Pound_per_kilogram = 2.2;
int main()
{
    cout << "Enter your height of feet:";
    double ht_feet;
    cin >> ht_feet;

    cout << "Enter your height of inch:";
    double ht_inch;
    cin >> ht_inch;

    double ht_meter = (ht_feet*Inch_per_feet + ht_inch)*Meter_per_inch;

    cout << "Enter your weight in pound: ";
    double wt_pound;
    cin >> wt_pound;

    double wt_kilogram = wt_pound / Pound_per_kilogram;

    double BMI = wt_kilogram / ht_meter/ht_meter;
    cout << "BMI:" << BMI << endl;
    system("pause");
    return 0;
}

3.编写一个程序,要求用户以度分秒的方式输入一个纬度,然后以度为单位显示该纬度。1度为60分,1分等于60秒,请以符号常量的方式表示这些值。对于每个输入值,应使用一个独立的变量存储它。下面是该程序运行时的情况:

Enter a latitude in degrees,minutes,and seconds:
First,enter the degrees:37
Next,enter the minutes of arc:51
Finally,enter the seconds of arc:19
37 degrees,51 minutes,19 seconds =37.8553 degrees

#include <iostream>
using namespace std;
const double Minute_per_degree = 60.0;
const double Second_per_minute = 60.0;
int main()
{
    cout << "Enter a latitude in degrees,minutes,and seconds:"<<endl;
    cout << "First,enter the degrees:";
    int degrees;
    cin >> degrees;

    cout << "Next,enter the minutes of arc:";
    int minutes;
    cin >> minutes;

    cout << "Finally,enter the seconds of arc:";
    int seconds;
    cin >> seconds;

    double Degree = degrees + minutes / Minute_per_degree + seconds / Second_per_minute / Minute_per_degree;

    cout << degrees << " degrees, " << minutes << " minutes, " << seconds << " seconds = " << Degree<< " degrees";
    system("pause");
    return 0;
}

4.编写一个程序,要求用户以整数方式输入秒数(使用long或long long变量存储),然后以天、小时、分钟和秒的方式显示这段时间。使用符号常量来表示每天有多少小时、每小时有多少分钟以及每分钟有多少秒。该程序的输出应与下面类似:

Enter the number of seconds:3160000
3160000 seconds = 365 days,17 hours,46 minutes,40 seconds

#include <iostream>
using namespace std;
const int Sec_per_min = 60;
const int Min_per_hour = 60;
const int Hour_per_day = 24;
int main()
{
    cout << "Enter the number of seconds:";
    long long total_sec;
    cin >> total_sec;

    int sec = total_sec%Sec_per_min;
    int total_min = total_sec / Sec_per_min;

    int min = total_min%Min_per_hour;
    int total_hour = total_min / Min_per_hour;

    int hour= total_hour%Hour_per_day;
    int day = total_hour / Hour_per_day;

    cout << total_sec << " seconds = " << day << " days," << hour << " hours," << min << " minutes," << sec << " seconds";

    system("pause");
    return 0;
}

5.编写一个程序,要求用户输入全球当前的人口和美国当前的人口(或其他国家的人口)。将这些信息存储在long long变量中,并让程序显示美国(或其他国家)的人口占全球人口的百分比。该程序的输出与下面类似:

Enter the world's population:6898758899
Enter the population of the US:310783781
The population of the US is 4.50492% of the world population.

#include <iostream>
using namespace std;
const int Sec_per_min = 60;
const int Min_per_hour = 60;
const int Hour_per_day = 24;
int main()
{
    cout << "Enter the world's population:";
    long long tW_population;
    cin >> tW_population;

    cout << "Enter the population of the US:";
    long long US_population;
    cin >> US_population;

    cout << "The population of the Us is " << double(US_population) / double(tW_population) *100<< "% of the world population";

    system("pause");
    return 0;
}

6.编写一个程序,要求用户输入驱车里程(英里)和使用汽油量(加仑),然后指出汽车耗油量为一加仑的里程。如果愿意,也可以让程序要求用户以公里为单位输入距离,并以升为单位输入汽油量,然后指出欧洲风格的结果-即每100公里的耗油量(升)。

#include <iostream>
using namespace std;
int main()
{
    cout << "Please enter the distance(miles):";
    double distance;
    cin >> distance;

    cout << "Please enter volume of gasoline(gallon):";
    double volume;
    cin >> volume;

    cout << "You can run " << distance / volume << " miles per gallon" << endl;
    system("pause");
    return 0;
}

7.编写一个程序,要求每个用户按欧洲风格输入汽车的耗油量(每100公里消耗汽油量(升 )),然后将其转换为美国风格的耗油量-每加仑多少英里。注意,除了使用不同的单位计量外,美国方法(距离/燃料)与欧洲方法(燃料/距离)相反。100公里等于62.14英里,1加仑等于3.875升。因此,19mpg大约合12.41/100km,127mpg大约合8.71/100km。

#include <iostream>
using namespace std;
int main()
{
    cout << "Please enter fuel consumption per 100 km(UN):";
    double UN;
    cin >> UN;

    cout <<" Gallons per mile(US) : "<< 1 / UN*62.14*3.875;

    system("pause");
    return 0;
}

第四章课后习题答案 

复习题

1.如何声明下述数据?

a. actor是由30个char组成的数组
b. betsie是由100个short组成的数组
c. chuck是由13个float组成的数组
d. dipsea是由64个long double组成的数组

char actor[30];
short betsie[100];
float chuck[13];
long double dipsea[64];

2.使用模板类array而不是数组来完成1的问题。

array<char,30>actor;
array<short,100>betsie;
arry<float,13>chuck;
array<long double,64>dipsea;

3.声明一个包含5个元素的int数组,并将他们初始化为前5个正奇数。

int a[5]={1,3,5,7,9};

4.编写一条语句,将问题3中数组第一个元素和最后一个元素的和赋值给变量even。

int a[5]={1,3,5,7,9};
int even=a[0]+a[4];

5.编写一条语句,显示float数组ideas中的第二个元素的值。

cout<<ideas[1]<<endl;

6.声明一个char的数组,并将其初始化为字符串“cheeseburger”。

char a[]="cheeseburger";

7.声明一个string对象,并将其初始化为字符串“Waldorf Salad”。

string a="Waldorf Salad";

8.设计一个描述鱼的结构声明,结构中应当包括品种、重量(整数,单位为盎司)和长度(英寸,包括小数)。

struct fish{
    char kind[20];
    int weight;
    float length;
}

9.声明8中定义的结构变量,并对她进行初始化。

fish Xfish=
{
    "xiaoyu";
    10;
    20.5;
}

10.用enum定义一个名为Response的类型,它包含Yes、No和Maybe等枚举量,其中Yes的值为1,No为0,Maybe为2.

enum Response{No,Yes,Maybe};

11.假设ted是一个double变量,请声明一个指向ted的指针,并使用该指针来显示ted的值。

double *p=&ted;
cout<<*p<<endl;

12.假设treacle是一个包含10个元素的float数组,请声明一个指向treacle的第一个元素的指针,并使用该指针来显示数组的第一元素和最后一个元素。

float *p=treacle;
cout<<p[0]<<" "<<p[9]<<endl;
//or cout<<*p<<"  "<<*(p+10) ;

13.编写一段代码,要求用户输入一个正整数,然后创建一个动态int数组,其中包含的元素数目等于用户的输入值,首先使用new来完成这项任务,再使用vector对象完成这项任务。

//use new
int num;
cout<<"Please input a positive integer: ";
cin>>num;
int *shu=new int[num];

//use vector
int num;
cout<<"Please input a number: ";
cin>>num;
vector<int>shu(num);

14.下面的代码是否有效,如果有效,他将输出什么结果。

cout<<(int*)"Home of the jolly bytes";
有效,输出该字符串的地址。

15.编写一段代码,给问题8中的结构动态分配内存,再读取该结构的成员的值。

fish yu=new fish{xiaoyu,10,20.5};
cout<<yu.name<<endl;
cout<<yu.weight<<endl;
cout<<yu.length<<endl;

16.程序清单4.6指出了混合输入数字和一行字符串存储的问题,如果将下面的代码:

cin.getline(adress,80);替换为:cin>>address;将对程序带来什么影响?
使用cin>>address 将使得程序跳过空白,直到找到给空白字符为止。然后它将读取字符,直到再次遇到空白为止。因此,它将跳过数字输入的换行符,从未避免这种问题。另一方面,它值读取一个单词,而不是整行。

17.声明一个vector对象和一个array对象,他们都包含10个string对象。指出所需的头文件,但不要使用using,使用const来指定要包含的string对象数。

#include<vector>
#include<array>
#include<string>
const int str_num=10;
std::vector<std::string>vstr(str_num);
std::array<<std::string,str_num>astr;

编程练习

1.编写一个c++程序,如下述输出示例的那样请求并显示信息:

What is your first name? Betty Sue
What is your last name? Yewe
What letter grade do you deserve? B
What is your age? 22
Name:Yewe,Betty Sue
Grade:C
Age:22

(注意,该程序应该接受的名字包含多个单词。另外,程序将向下调整成绩,即向上调一个字母。假设用户请求A、B或C,所以不必担心D和F之间的空档。)

#include<iostream>
#include<string>
int main()
{
    using namespace std;
    cout << "What your first name? ";
    string first_name;
    getline(cin,first_name) ;

    cout << "What your last name? ";
    string last_name;
    getline(cin,last_name);

    cout << "What letter grade do you deserve? ";
    char  my_grade;
    cin >> my_grade ;

    cout << "What is you age? ";
    int age;
    cin >> age ;

    cout << "Name: " << last_name << "," << first_name << endl;
    cout << "Grade: " << ++my_grade<< endl;
    cout << "Age: " << age << endl;

    system("pause");
    return 0;
}

2.修改程序清单4.4,使用c++string类而不是char数组。

#include <iostream>
#include<string>
int main()
{
    using namespace std;
    string name;
    string dessert;

    cout << "Enter your name:\n";
    getline(cin, name);  // reads through newline
    cout << "Enter your favorite dessert:\n";
    getline(cin,dessert);
    cout << "I have some delicious " << dessert;
    cout << " for you, " << name << ".\n";

    system("pause");
    return 0;
}

3.编写一个程序,他要求用户首先输入其名,然后输入其姓;然后程序使用一个逗号和一个空格将姓和名组合起来,并存储和显示结合效果,请使用char数组和头文件cstring中的函数。下面是该程序的运行时的情形:

Enter your first name: Flip
Enter your last name: Fleaming
Here's the information in a single string: Fleming, Flip

#include<iostream>
#include<cstring>
//#pragma warning(disable:4996)  //vs2017需要加上这句话,忽略4996警告
const int Strlen = 20;
int main()
{
    using namespace std;
    char first_name[Strlen];
    char last_name[Strlen];
    char full_name[2 * Strlen];

    cout << "Enter your first name: ";
    cin.get(first_name,Strlen).get();

    cout << "Enter your last name:";
    cin.get(last_name,Strlen).get();

    strcpy(full_name,last_name);
    strcat(full_name,", ");
    strcat(full_name, first_name);

    cout << "Here's the information in a single string: " << full_name << endl;
    system("pause");
    return 0;
}

4.编写一个程序,他要求用户首先输入其名,然后输入其姓;然后程序使用一个逗号和一个空格将姓和名组合起来,并存储和显示结合效果,请使用string对象和文件string中的函数。下面是该程序的运行时的情形:

Enter your first name: Flip
Enter your last name: Fleaming
Here's the information in a single string: Fleming, Flip

#include<iostream>
#include<string>
int main()
{
    using namespace std;
    string first_name;
    string last_name;
    string full_name;

    cout << "Enter your first name: ";
    getline(cin,first_name);

    cout << "Enter your last name:";
    getline(cin, last_name);

    full_name = last_name + ", " + first_name;

    cout << "Here's the information in a single string: " << full_name << endl;
    system("pause");
    return 0;
}

5.结构CandyBar包含3个成员。第一个成员存储了糖块的品牌;第二个成员存储糖块的重量(可以有小数);第三个成员存储了糖的卡路里含量(整数)。请编写一个程序,声明这个结构,创建一个名为snack的CandBar变量,并将其成员分别初始化为“Mocha Munch”、2.3和350。初始化在声明snack时进行。最后,程序显示snack变量的内容。

#include<iostream>
#include<string>
struct CandyBar {
    std::string brand;
    float weight;
    int calorie;
};
int main()
{
    using namespace std;
    CandyBar snack = {"Mocha Munch",2.3,350};
    cout << "brand: " << snack.brand << endl;
    cout << "weight: " << snack.weight << endl;
    cout << "calorie: " << snack.calorie << endl;

    system("pause");
    return 0;
}

6.结构CandyBar包含3个成员,如编程练习5所示。请编写一个程序,创建一个包含3个元素的CandyBar数组,并将他们初始化为所选择的值,然后显示每个结构的内容。

#include<iostream>
#include<string>
struct CandyBar {
    std::string brand;
    float weight;
    int calorie;
};
int main()
{
    using namespace std;
    CandyBar snack[3] = {
        { "Mocha Munch",2.3,350 },
        { "Mocha Munch",2.3,350 },
        { "Mocha Munch",2.3,350 }
    };
    for (int i = 0; i < 3; i++)
    {
        cout << "brand: " << snack[i].brand << endl;
        cout << "weight: " << snack[i].weight << endl;
        cout << "calorie: " << snack[i].calorie << endl;
    }

    system("pause");
    return 0;
}

7.William Wingate从事披萨分析服务。对于每个披萨饼,他都需要记录下列信息:

  • 披萨饼公司的名称,可以有多个单词组成。

  • 披萨饼的直径

  • 披萨饼的重量
    请设计一个能够存储这些信息的结构,并编写一个使用这种结构变量的程序。程序将请求用户输入上述信息,然后显示这些信息。请使用cin(或它的方法)和cout。

#include<iostream>
#include<string>
struct Pizza {
    std::string company;
    double diameter;
    double weight;
};
int main()
{
    using namespace std;
    Pizza pizza;
    cout << "Please input pizza's company: ";
    getline(cin, pizza.company);
    cout << "Please input pizza's diameter: ";
    cin>>pizza.diameter;
    cout << "Please input pizza's weight: ";
    cin>> pizza.weight;

    cout << "Company: " << pizza.company << endl;
    cout << "Diameter: " <<pizza.diameter << endl;
    cout << "Weight: " << pizza.weight<< endl;

    system("pause");
    return 0;
}

8.完成编程练习7,但使用new来为结构动态分配内存,而不是声明一个结构变量。另外,让程序在请求输入披萨名称之前输入披萨直径。

#include<iostream>
#include<string>
struct Pizza {
    std::string company;
    double diameter;
    double  weight;
};
int main()
{
    using namespace std;
    Pizza *p=new Pizza;

    cout << "Please input p's diameter: ";
    cin >> p->diameter;
    cin.get();
    cout << "Please input p's company: ";
    getline(cin, p->company);
    cout << "Please input p's weight: ";
    cin>>p->weight;

    cout << "Company: " << p->company << endl;
    cout << "Diameter: " <<p->diameter << endl;
    cout << "Weight: " << p->weight<< endl;


    system("pause");
    return 0;
}

9.完成编程练习6,但使用new来动态分配数组,而不是声明一个包含3个元素的CandyBar的数组。

#include<iostream>
#include<string>
struct CandyBar {
    std::string brand;
    double weight;
    int calorie;
};
int main()
{
    using namespace std;
    CandyBar *snack = new CandyBar[3];
    for (int i = 0; i < 3; i++)
        snack[i]={"Mocha Munch", 2.3, 350};

    for (int i = 0; i < 3; i++)
    {
        cout << "brand: " << snack[i].brand << endl;
        cout << "weight: " << snack[i].weight << endl;
        cout << "calorie: " << snack[i].calorie << endl;
    }
    delete[] snack;
    system("pause");
    return 0;
}

10.编写一个程序,让用户输入三次40码跑的成绩(如果你愿意,也可以让用户输入40米跑的成绩),并显示次数和平均成绩。请使用一个array对象来存储数据(如果编译器不支持array类,请使用数组)。

#include<iostream>
#include<array>
int main()
{
    using namespace std;
    array<double, 3>grade;

    cout << "Please input your first grade:";
    cin >> grade[0];
    cout << "Please input your second grade:";
    cin >> grade[1];
    cout << "Please input your third grade:";
    cin >> grade[2];

    cout << "Average three times:" << (grade[0] + grade[1] + grade[2]) / 3.0 << endl;
    system("pause");
    return 0;
}

 第五章课后习题答案 

复习题

1.入口条件循环和出口条件循环之间的区别是什么?各种c++循环分别属于其中的哪一种?

入口循环就是程序在执行循环体中的语句之前先检查循环条件;出口循环是在执行循环体中的语句之后检查循环条件。for循环和while循环都是入口条件循环;do while循环为出口条件循环。

2.如果下面的代码片段是有效程序的组成部分,它将打印什么内容?

int i;
for(i=0;i<5;i++)
      cout<<i;
cout<<endl;

打印内容:01234

3.如果下面的代码片段是有效程序的组成部分,它将打印什么内容?

int j;
for(j=0;j<11;j+=3)
    cout<<j;
cout<<endl<<j<<endl;

打印内容:
0369
12

4.如果下面代码是有效程序的组成部分,它将打印什么内容?

int j=5;
while(++j<9)
    cout<<j++<<endl;

打印内容:
6
8

5.如果下面代码是有效程序的组成部分,它将打印什么内容?

int k=8;
do
    cout<<"k="<<k<<endl;
while(k++<5);

打印内容:
k=8

6.编写一个打印1、2、4、8、16、32、64的for循环,每轮循环都将计数变量的值乘以2。

int i;
for(i=1;i<=64;i*=2)
    cout<<i<<" ";

7.如何在循环体中包括多条语句?

将语句放在一对大括号中形成一个复合语句或代码块。

8.下面的语句是否有效?如果无效,原因是什么?如果有效,它将完成什么工作?

a.int x={1,024}
b.int y=1,024;
语句a是有效的,表达式1,024为逗号表达式,该表达时的右侧表达式的值,由于024为8进制数,对应的十进制数为20,因此x的值应为20,即x=20。
语句b也是有效的,但是逗号运算符的优先级低于赋值运算符,因此b中表达式等效为(int y=1),024;

9.在查看输入方面,cin>>ch同cin.get(ch)和ch=cin.get()有什么不同?

cin>>ch将跳过空格、换行符和制表符,其他两种格式将读取这些字符。

编程练习

1.编写一个要求用户输入两个整数的程序。该程序将计算并输出这两个整数之间(包括这两个整数)所有整数的和。这里假设先输入较小的整数。例如,如果用户输入的是2和9,则程序将指出2~9之间所有整数的和为44。

#include<iostream>
using namespace std;
int main()
{
    int a, b, sum = 0;
    cout << "Please enter two integers(enter the smaller integer first)." << endl;
    cout << "The first integer : _\b";
    cin >> a;
    cout << "The second integer: _\b";
    cin >> b;
    for (int i = a; i <= b; i++)
        sum += i;
    cout << "The sum of integers between "<<a<<" and "<<b<<" is : " << sum << endl;
    system("pause");
    return 0;
}

2.使用array对象(而不是数组)和long double(而不是long long)重新编写程序清单5.4,并计算100!的值。

Listing 5.4 formore.cpp


// formore.cpp -- more looping with for
#include <iostream>
const int ArSize = 16; // example of external declaration
int main()
{
    long long factorials[ArSize];
    factorials[1] = factorials[0] = 1LL;
    for (int i = 2; i < ArSize; i++)
    factorials[i] = i * factorials[i-1];
    for (int i = 0; i < ArSize; i++)
    std::cout << i << "! = " << factorials[i] << std::endl;
    return 0;
}


编写后程序清单:

#include<iostream>
#include<array>
const int ArSize = 16; 
int main()
{
    using namespace std;
    array<long double,ArSize>factorials;
    factorials[1] = factorials[0] = 1.0;
    for (int i = 2; i < ArSize; i++)
        factorials[i] = i * factorials[i - 1];
    for (int i = 0; i <ArSize; i++)
        cout << i << "! = " << factorials[i] << endl;
    system("pause");
    return 0;
}

3.编写一个要求用户输入数字的程序。每次输入后,程序都将报告到目前为止,所有输入的累计和,当用户输入0时,程序结束。

#include<iostream>
#include<array>
int main()
{
    using namespace std;
    double num,sum=0;
    for (int i = 1; i != 0; i=num)
    {
        cout << "Please enter a number(if 0,the end the program.)_\b";
        cin >> num;
        sum += num;
        cout << "At this point, the cumulative sum of the Numbers is : " << sum << endl;
    }
    cout << "Bye" << endl;
    system("pause");
    return 0;
}

4.Daphne以10%的单利投资了100美元。也就是说,每一年的利润都是投资额的10%,即每年10美元:利息=0.10*原始存款。而Cleo在第一年投资100美元的盈利是5%--一共得到105美元。下一年的盈利是105美元的5%--即5.25美元,以此类推。请编写一个程序,计算多少年后,Cleo的投资价值超过Daphne的投资价值。并显示此时两个人的投资价值。

#include<iostream>
int main()
{
    using namespace std;
    double daphne = 100.0;
    double cleo = 100.0;
    int year;
    for (year = 1; cleo <= daphne; year++)
    {
        daphne += 10.0;
        cleo *= 1.05;
    }
    cout << year << " years later,Cleo's investment is worth more than Daphne's." << endl;
    cout << "Daphne has $" << daphne << endl;
    cout << "Cleo has $" << cleo << endl;
    system("pause");
    return 0;
}

5.假设要销售《C++ For Fools》一书。请编写一个程序,输入全年中每个月的销售量(图书数量,而不是销售额)。程序通过循环,使用初始化为月份字符串的char*数组(或string对象数组)逐月进行提示,并将输入数据存储的int数组中。然后,程序计算数组中各元素的总数,并报告这一年的销售情况。

#include<iostream>
#include<string>
int main()
{
    using namespace std;
    string months[12]  = {
        "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November",
        "December"
    };
    int sales[12];
    int sum = 0;

    for (int i = 0; i < 12; i++)
    {
        cout << "Please enter the sales volume for " << months[i] << " : _\b";
        cin >> sales[i];
    }

    for (int i = 0; i < 12; i++)
    {
        cout << months[i] << " sales : " << sales[i]<<endl;
        sum += sales[i];
    }

    cout << "Annual sales :" << sum << endl;
    system("pause");
    return 0;
}

6.完成编程练习5,但这一次使用大的一个二位数组来存储输入---3年中每个月的销售量。程序将报告每年销量以及三年的总销量。

#include<iostream>
#include<string>
int main()
{
    using namespace std;
    string months[12]  = {
        "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November",
        "December"
    };
    int sales[3][12];
    int sum = 0;
    for (int i = 0; i < 3; i++)
    {
        cout << "Year " << i+1 << ": " << endl;
        for (int f = 0; f < 12; f++)
        {
            cout << "Please enter the sales volume for " << months[f] << " : _\b";
            cin >> sales[i][f];
        }
    }
    for (int j=0; j < 3; j++)
    {
        cout << "*********Year " << j+1 << "*********" << endl;
        for (int i = 0; i < 12; i++)
        {
            cout << months[i] << " sales : " << sales[j][i] << endl;
            sum += sales[j][i];
        }
    }
    cout << "Annual sales :" << sum << endl;
    system("pause");
    return 0;
}

7.设计一个名为car的结构,用它存储下述有关汽车的信息:生产商(存在字符数组或string对象中的字符串)、生产年份(整数)。编写一个程序向用户询问有多少辆汽车。随后,程序使用new来创建一个有相应数量的car结构组成的动态数组。接下来,程序提示用户输入每辆车的生产商(可能有多个单词组成)和年份信息。请注意,这需要特别小心,因为它将交替读取数值和字符串。最后,程序将显示每个结构的内容。该程序的运行情况如下:

How many cars do you wish to catalog? 2
Car #1:
Please enter the make:Hudson Hornet
Please enter the year made:1952
Car #2:
Please enter the make:Kaiser
Please enter the year made:1951
Here is your collection:
1952 HUdson Hornet
1951 Kaiser

实现代码:

#include<iostream>
#include<string>
using namespace std;
struct Car {
    string maker;
    int year;
};

int main()
{
    int num;
    cout << "How many cars do you wish to catalog? ";
    (cin >> num).get();
    Car *cars=new Car[num];
    for (int i=0; i < num; i++)
    {
        cout << "Car #" << i + 1 << " : " << endl;
        cout << "Please enter the make : ";
        getline(cin ,cars[i].maker);
        cout << "Please enter the year made : ";
        (cin >> cars[i].year).get();
    }
    cout << "Here is your collection:" << endl;
    for (int i = 0; i < num; i++)
        cout << cars[i].year << " " << cars[i].maker << endl;
    delete []cars;
    system("pause");
    return 0;
}

8.编写一个程序,它使用一个char数组和循环来每次读取一个单词,直到用户输入done为止。随后,该程序指出用户输入多少个单词(不包含done)。下面是程序的运行情况:

Enter words(to stop,type the word done):
anteater birthday category dumpster
envy finagle geometry done for sure
You entered a total of 7words.

您应在程序中包含头文件cstring,并使用strcmp()来进行比较测试。

实现代码:

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

int main()
{
    char word[20];
    cout << "Enter words(to stop,type the word done):" << endl;
    cin >> word;
    int num = 0;
    while (strcmp("done", word))
    {
        num++;
        cin >> word;
    }
    cout << "You entered a total of " << num << " words." << endl;
    system("pause");
    return 0;
}

9.编写一个满足前一个练习的中描述的程序,但使用string对象而不是字符数组。请在程序中包含头文件string,并使用关系运算符来进行比较测试。

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

int main()
{
    string word;
    cout << "Enter words(to stop,type the word done):" << endl;
    cin >> word;
    int num = 0;
    while ( word.compare("done"))
    {
        num++;
        cin >> word;
    }
    cout << "You entered a total of " << num << " words." << endl;
    system("pause");
    return 0;
}

10.编写一个使用嵌套循环的程序,要求用户输入一个值,指出要显示多少行。然后,程序将显示相应行数的型号,其中第一行包括一个星号,第二行包括两个星号,以此类推。每一行包含的字符数等于用户指定的行数,在星号不够的情况下,在星号前面加句点。程序的运行情况如下:

Enter number of row : 5
....*
...**
..***
.****
*****

代码实现:

#include<iostream>
using namespace std;

int main()
{
    int row;
    cout << "Enter number of rows : ";
    cin >> row;
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < row; j++)
        {
            if (i < row -j-1)
                cout << '.';
            else
                cout << '*';
        }
        cout << endl;
    }
    system("pause");
    return 0;
}

第六章课后习题答案 

复习题

1.请看下面两个计算空格和换行符数目的代码片段:

//version 1
while(cin.get(ch))   //quit on eof
{  
    if(ch==' ')
         spaces++;
    if(ch=='\n')
         newlines++;
}

//version 2
while(cin.get(ch))   //quit eof
{
    if(ch==' ')
         spacees++;
    else if(ch=='\n')    
         newlines++;
}

第二个格式比第一个格式好在哪里?

第二个版本比第一个版本效率更高,因为在第一个中对于每个字符都需要判断两次,而在第二个版本中,如果字符为空格,在经过if判断确定为空格后,该字符肯定不是换行符,第二个else if的判断直接跳过,节省判断时间。

2.在程序清单6.2中,用ch+1替换++ch将发生什么情况?

程序清单6.2 ifelse.cpp

// ifelse.cpp -- using the if else statement
#include <iostream>
int main()
{
   char ch;
   std::cout << "Type, and I shall repeat.\n";
   std::cin.get(ch);
   while (ch != '.')
   {
       if (ch == '\n')
            std::cout << ch; // done if newline
       else
            std::cout << ++ch; // done otherwise
       std::cin.get(ch);
}
   // try ch + 1 instead of ++ch for interesting effect
   std::cout << "\nPlease excuse the slight confusion.\n";
   // std::cin.get();
   // std::cin.get();
   return 0;
}

++ch的数据类型依旧是char型,但对于char+1最终类型为int型,因此当++ch换成ch+1后,输出的是数字。

3.请认真考虑下面的程序:

#include<iostream>
using namespace std;
int main()
{
    char ch;
    int ct1,ct2;
    ct1=ct2=0;
    while((ch=cin.get())!='$')
    {
        cout<<ch;
        ct1++;
        if(ch='$')
              ct2++;
         cout<<ch;
    }
    cout<<"ct1="<<ct1<<",ct2="<<ct2<<"\n";
    return 0;
}

假设输入如下(请在每行末尾按回车键):

Hi!
Send $10 or $20 now!

则输出将是什么(还记得吗,输入被缓冲)?

输入输出结果为

Hi!
H$i$!$
$Send $10 or $20 now!
S$e$n$d$ $ct1=9,ct2=9

由于程序中使用的是ch='$',所以每次循环该if条件内代码都执行一次,因此ct1与ct2相等。同时在输入Hi!之后键入回车,因此在读取回车之后,打印出来,光标换行,紧接着打印$。

4.创建表示下述条件的逻辑表达式:

a.weight大于或等于115,但小于125。
b.ch为q或Q。
c.x为偶数,但不是26.
d.x为偶数,但不是26。
e.donation为1000-2000或guest为1。
f.ch是小写字母或大写字母(假设小写字母是依次编码的,大写字母也是依次编码的,但在大小写字母间编码是不连续的)。

//a
weight>=115 && weight<125   

//b
ch=='q' || ch=='Q'

//c
x%2==0 && x!=26

//d
x%2==0 && x%26!=0

//e
donation>=1000 && donation<=20000 || guest==1

//f
(ch>='a' && ch<='z') || (ch<='Z' && ch>='A')

5.在英语中,"I will not not speak(我不会不说) "的意思与"I will speak(我要说)"相同。在c++中,!!x是否与x相同呢?

对于bool变量而言,!!x与x是相同的,但对于其他类型变量不一定相同,例如!!5=1,!!5≠5。

6.创建一个条件表达式,其值为变量的绝对值。也就是说,如果变量x为正,则表达式的值为x;但如果x为负,则表达式的值为-x--这是一个正值。

x>=0 ? x : -x;

7.用switch改写下面的代码片段:

if(ch=='A')
    a_grade++;
else if(ch=='B')
    b_grade++;
else if(ch=='C')
    c_grade++;
else if(ch=='D')
    d_grade++;
else
    f_grade++;

改写后代码:

switch(ch)
{
    case 'A' : a_grade++;
                    break;
    case 'B' : b_grade++;
                    break;
    case 'C' : c_grade++;
                    break;
    case 'D' : d_grade++;
                    break;
    default :   f_grade++;
                    break;
}

8.对于程序清单6.10,与使用字符(如a和c)表示菜单选项和case标签有何优点呢?(提示:想一想用户输入q和输入5的情况。)

程序清单6.10 switch.cpp

// switch.cpp -- using the switch statement
#include <iostream>
using namespace std;
void showmenu(); // function prototypes
void report();
void comfort();
int main()
{
   showmenu();
   int choice;
   cin >> choice;
   while (choice != 5)
   {
       switch (choice)
       {
       case 1: cout << "\a\n";
           break;
       case 2: report();
           break;
       case 3: cout << "The boss was in all day.\n";
           break;
       case 4: comfort();
           break;
       default: cout << "That's not a choice.\n";
       }
       showmenu();
       cin >> choice;
   }
   cout << "Bye!\n";
   return 0;
}
void showmenu()
{
   cout << "Please enter 1, 2, 3, 4, or 5:\n"
       "1) alarm 2) report\n"
       "3) alibi 4) comfort\n"
       "5) quit\n";
}
void report()
{
   cout << "It's been an excellent week for business.\n"
       "Sales are up 120%. Expenses are down 35%.\n";
}
void comfort()
{
   cout << "Your employees think you are the finest CEO\n"
       "in the industry. The board of directors think\n"
       "you are the finest CEO in the industry.\n";
}

使用数字作为菜单选项和case标签,限定了用户只有输入数字的时候才能有效,若用户错误的输入非整数类型,导致程序被挂起。而使用字符作为菜单选项和case标签,当用户输入错误类型,程序能正确通过default部分提示用户输入错误,用户体验更加友好,提高了程序的容错性和健壮性。

9.请看下面的代码片段

int line = 0;
char ch;
while(cin.get(ch))
{
    if(ch=='Q')
        break;
    if(ch!='\n')
        continue;
    line++;
}

重写后代码:

int line = 0;
char ch;
while(cin.get(ch) && ch!='Q')
{
    if(ch=='\n')
        line++;
}

编程练习

1.编写一个程序,读取键盘输入,直到遇到@符号为止,并回显输入(数字除外),同时将大写字符转换为小写字符,将小写字符转换为大写(别忘了cctype函数系列)

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

int main()
{
    cout << "Please enter characters (type @ to stop):";
    char ch;
    cin.get(ch);
    while (ch != '@')
    {
        if (islower(ch))
            ch = toupper(ch);
        else if (isupper(ch))
            ch = tolower(ch);
        if (!isdigit(ch))
            cout << ch;
        cin.get(ch);
    }
    system("pause");
    return 0;
}

2.编写一个程序,最多将10个donation值读入一个double数组中(如果你愿意,也可以使用模板类array)。程序遇到非数字输入时将结束输入,并报告这些数字的平均值以及数组中有多少个数字大于平均值。

#include<iostream>
#include<array>
using namespace std;
int main()
{
    array<double,10>donations;
    double sum=0;
    cout<<"Please enter donation(non-number to stop):";
    int i;
    double donation;
    for(i=0;(i<10)&&(cin>>donation);++i)
    {
        donations[i]=donation;
        sum=+donations[i];
    }    

    double avg=sum/(i+1);
    cout<<"Average:"<<avg<<endl;
    cout<<"Number larger than average:";
    for(int j=0;j<i;j++)
     {
        if(donations[j]>avg)
            cout<<donations[j]<<" ";
     }   
    cout<<endl;
    return 0;
}

3.编写一个菜单驱动程序的雏形。该程序显示一个提供四个选项的菜单--每个选项用一个字母表标记。如果用户使用有效选项之外的字母进行响应,程序将提示用户输入有效的字母,直到用户这样选择为止。然后,该程序使用一条switch语句,根据用户的选择执行一个简单操作。该程序的运行情况如下:

Please enter one of the following choices:
c) carnivore         p) pianist
t) tree                  g)game
f
Please enter a c,p,t or g:q
Please enter a c,p,t or g:t
A maple is a tree.

代码实现:

#include <iostream>
using namespace std;
int main()
{
    cout<<"Please enter one of the following choices:"<<endl;
    cout<<"c) carnivore         p) pianist"<<endl;
    cout<<"t) tree              g) game"<<endl;
    char ch;
    cin>>ch;
    while(ch!='c' && ch!='p' && ch!='t' && ch!='g')
    { 
        cout<<"Please enter a c,p,t or g:";
        cin>>ch;
    }   
    switch (ch)
    {
        case 'c':
            cout<<"A maple is a carnivore."<<endl;
            break;
        case 'p':
            cout<<"A maple is a pianist."<<endl;
            break;
        case 't':
            cout<<"A maple is a tree."<<endl;
            break;
        case 'g':
            cout<<"A maple is a game."<<endl;
            break;
        default:
            break;
    }
    return 0;
}

4.加入Benevolent Order of Programmer后,在BOP大会上,人们便可以通过加入者的真实姓名、头衔或秘密BOP姓名来了解他(她)。请编写一个程序,可以使用真实姓名、头衔、秘密姓名或成员偏好来列出成员。编写该程序时,请使用下面的结构:

//Benevolent Order of Programmers name structure
struct bop{
    char fullname[strsize];     //real name
    char title[strzie];              //job title
    char bopname[strsize];   //secret BOP name
    int preference;                //0=fullname,1=title,2=bopname
};

该程序创建一个由上述结构组成的小型数组,并将其初始化为适当的值。另外,该程序使用一个循环,让用户在下面的选项中进行选择:

a.display by name        b.diaplay by title
c.display by bopname     d.display by preference
q.quit

注意,“display by preference”并不意味显示成员的偏好,而是意味着根据成员的偏好来列出成员。例如,如果偏好号为1,则选择d将显示程序员的头衔。该程序的运行情况如下:

Benevolent Order of Programmers Report
a. display by name         b. display by title
c. display by bopname      d. display by preference
q. quit
Enter your choice: a
Wimp Macho
Raki Rhodes
Celia Laiter
Hoppy Hipman
Pat Hand
Next choice: d
Wimp Macho
Junior Programmer
MIPS
Analyst Trainee
LOOPY
Next choice: q
Bye!

代码实现 :

#include <iostream>

using namespace std;

const int strsize = 20;
struct bop
{
    char fullname[strsize];
    char title[strsize];
    char bopname[strsize];
    int preference;         //0 = fullname, 1 = title, 2 = bopname
};

int main()
{
    int programmerNum = 5;
    bop programmers[programmerNum]={{"Wimp Macho", "Junior Programmer", "WM",0},
    {"Raki Rhodes", "Junior Programmer", "RR", 1},
    {"Celia Laiter", "Junior Programmer", "MIPS", 2},
    {"Hoppy Hipman", "Analyst Trainee", "HH", 1},
    {"Pat Hand", "Junior Programmer", "LOOPY", 2}};
    cout << "Benevolent Order of Programmers Report" << endl;
    cout << "a. display by name          b. display by title" << endl;
    cout << "c. display by bopname       d. display by preference" << endl;
    cout << "q. quit" << endl;
    cout << "Enter your choice: ";
    char choice;
    while(cin.get(choice))
    {
        if(choice == 'a')
        {
            for(int i = 0; i < programmerNum; i++)
            {
                cout << programmers[i].fullname << endl;
            }
        }
        else if(choice == 'b')
        {
            for(int i = 0; i < programmerNum; i++)
            {
                cout << programmers[i].title << endl;
            }
        }
        else if(choice == 'c')
        {
            for(int i = 0; i < programmerNum; i++)
            {
                cout << programmers[i].bopname << endl;
            }
        }
        else if(choice == 'd')
        {
            for(int i = 0; i < programmerNum; i++)
            {
                if(programmers[i].preference == 0)
                {
                    cout << programmers[i].fullname << endl;
                }
                else if(programmers[i].preference == 1)
                {
                    cout << programmers[i].title << endl;
                }
                else
                {
                    cout << programmers[i].bopname << endl;
                }
            }
        }
        else if(choice == 'q')
        {
            cout << "Bye!" << endl;
            break;
        }
        else
        {
            if(choice == '\n')
            {
                continue;
            }
            cout << "input error, please re-enter!" << endl;
        }
        cout << "Next choice: ";
    }

    return 0;
}

5.在Neutronia王国,货币单位是tvarp,收入所得税的计算方式如下:

5000 tvarps: 不收税
5001-15000 tvarps: 10%
15001-35000 tvarps: 15%
35000 tvarps以上: 20%

例如,收入为38000 tvarps时,所得税为5000×0.00+10000×0.10+2000×0.15+3000×0.20,即 4600tvarps。请编写一个程序,使用循环来要求用户输入收入,并报告所得税,当用户输入负数或非数字时,循环将结束。

代码实现:

#include<iostream>

using namespace std;

int main()
{
    cout << "Please enter your income(if you enter negative number or non-numberic, it will exit.) : ";
    double income, tax;
    while(cin >> income)
    {
        cout<< income <<endl;
        if(income > 35000)
        {
            tax = 10000 * 0.10 + 20000 * 0.15 + (income - 35000) * 0.20;
        }
        else if(income >= 15001)
        {
            tax = (income - 3500) * 0.15 +10000 * 0.10;
        }
        else if(income >= 5001)
        {
            tax = (income - 5000) * 0.10;
        }
        else if(income >= 0)
        {
            tax = 0;
        }
        else
        {
            cout << "Enter negative number, exiting soon..." << endl;
            break;
        }
        cout << "your should pay tax : " << tax << " tvarps." << endl;
        cout << "Please enter another income(if you enter negative number or non-numberic, it will exit.) : ";
    }
    cout << "Exited, Bye !" << endl;
    return 0;
}

6.编写一个程序,记录捐助给"维护合法权利团体"的资金。该程序要求用户输入捐赠者数目,然后要求用户输入每一个捐献者的姓名和款项。这些信息被存储在一个动态分配的结构数组中.每个数据结构有两个成员:用来存储姓名的字符串数组(或string对象)和用来存储款项的double成员。读取所有的数据后,程序将显示所有捐款超过10000的捐款着姓名及其捐款数额。该列表前应包含一个标题,指出下面的捐款者是重要捐款人(Grand Patrons)。然后,程序将列出其他的捐款者,该列表要以Partons开头。如果某种类别没有捐款者,则程序将打印单词"none"。该程序只显示这两种类别,而不进行排序。

代码实现:

#include<iostream>
#include<string>

using namespace std;

struct DonationInfo{
    string name;
    double amount;
};

void donationInfoDisplay(DonationInfo donationInfo[], int num, bool isGrandPatrons)
{
    int countNum = 0;
    for(int i = 0 ; i < num ; i++)
    {
        if(isGrandPatrons)
        {
            if(donationInfo[i].amount > 10000)
            {
                countNum++;
                cout << donationInfo[i].name  << endl;
            }
        }
        else
        {
            if(donationInfo[i].amount <= 10000)
            {
                countNum++;
                cout << donationInfo[i].name  << endl;
            }
        }
    }
    if(countNum == 0)
        cout << "none" << endl;
}

int main()
{
    cout << "Please enter the number of donors :";
    int num;
    while(!(cin >> num))
    {
        cin.clear();
        cin.sync();
        cin.ignore();
        cout << "***[WARNING]:Please enter positive integer.***" << endl;
        cout << "Please enter the number of donors :";
    }
    DonationInfo* donationInfo = new DonationInfo[num];
    for(int i = 0; i < num; i++)
    {
        cout << "enter the donor name :";
        cin >> donationInfo[i].name;
        cout << "enter the donation amount :";
        cin >> donationInfo[i].amount;
    }
    cout << "******Grand Partons******" << endl;
    donationInfoDisplay(donationInfo, num, true);
    cout << "******Partons******" << endl;
    donationInfoDisplay(donationInfo, num, false);
    return 0;
}

7.编写一个程序,它每次读取一个单词,直到用户只输入q。然后,该程序指出有多少个单词以元音打头,有多少个单词以辅音打头,还有多少个单词不属于这两类。为此,方法之一是,使用isalpha()来区分以字母和其他字母打头的单词,然后对于通过isalpha()测试的单词,使用if或switch语句来确定哪些以元音打头。该程序的运行情况如下:

Enter words (q to quit):
The 12 awesome oxem ambled
quiety across 15 meters of lawn. q
5 words beginning with vowels
4 words beginning with consonants
2 others

代码实现:

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

int main()
{
    cout << "Enter words (q to quit) :" << endl;
    string word;
    int vowelNum = 0;
    int consonantNum = 0;
    int othersNum = 0;
    while(cin >> word)
    {
        if(word == "q")
        {
            break;
        }
        else
        {
            if(isalpha(word[0]))
            {
                switch(word[0])
                {
                    case 'a':
                    case 'e':
                    case 'i':
                    case 'o':
                    case 'u':
                    case 'A':
                    case 'E':
                    case 'I':
                    case 'O':
                    case 'U':
                        vowelNum++;
                        break;
                    default:
                        consonantNum++;
                }
            }
            else
            {
                othersNum++;
            }
        }
    }
    cout << vowelNum << " words beginning with vowels" << endl;
    cout << consonantNum << " words beginning with consonants" << endl;
    cout << othersNum << " others" <<endl;
    return 0;
}

8.编写一个程序,他打开一个文件,逐个字地读取该文件,直到到达文件末尾,然后指出该文件中包含多少个字符。

代码实现:

#include<iostream>
#include<fstream>

using namespace std;

int main()
{
    ifstream txtSource;
    txtSource.open("test.txt", ios::in);
    if(!txtSource.is_open())
    {
        cout << "File failed to open !" << endl;
        exit(EXIT_FAILURE);
    }
    char ch;
    int characterNum = 0;
    while(txtSource >> ch)
    {
        characterNum++;
    }
    cout << "The file contains " << characterNum << " characters" << endl;
    return 0;
}

9.完成编程练习6,但从文件中读取所需的信息。该文件的第一项应为捐款人数,余下的内容应为对的行。在每一对中,第一行为捐款人姓名,第二行为捐款数额。即该文件类似于下面:

代码实现:

#include<iostream>
#include<string>
#include<fstream>

using namespace std;

struct DonationInfo{
    string name;
    double amount;
};

void donationInfoDisplay(DonationInfo donationInfo[], int num, bool isGrandPatrons)
{
    int countNum = 0;
    for(int i = 0 ; i < num ; i++)
    {
        if(isGrandPatrons)
        {
            if(donationInfo[i].amount > 10000)
            {
                countNum++;
                cout << donationInfo[i].name  << endl;
            }
        }
        else
        {
            if(donationInfo[i].amount <= 10000)
            {
                countNum++;
                cout << donationInfo[i].name  << endl;
            }
        }
    }
    if(countNum == 0)
        cout << "none" << endl;
}

int main()
{
    cout << "Read file content..." << endl;
    ifstream txtDonationInfo;
    txtDonationInfo.open("test.txt", ios::in);
    if(!txtDonationInfo.is_open())
    {
        cout << "File failed to open !" << endl;
        exit(EXIT_FAILURE);
    }
    int num = 0;
    (txtDonationInfo >> num).get();
    DonationInfo* donationInfo = new DonationInfo[num];
    for(int i = 0; i < num; i++)
    {
        txtDonationInfo >> donationInfo[i].name;
        txtDonationInfo >> donationInfo[i].amount;
    }
    cout << "******Grand Partons******" << endl;
    donationInfoDisplay(donationInfo, num, true);
    cout << "******Partons******" << endl;
    donationInfoDisplay(donationInfo, num, false);
    return 0;
}

第七章课后习题答案 

复习题

1. 使用函数的3个步骤是什么?

定义函数、提供函数、调用函数。

2.请创建与下面的描述相匹配的函数原型。

a. igor()没有参数,且没有返回值
b. tofu()接受一个int参数,并返回一个float
c. mpg()接受两个double参数,并返回一个double
d. summation()将long数组名和数组长度作为参数,并返回一个long值
e. doctor()接受一个字符串参数(不能修改该字符串),并返回一个double值
f. ofcourse()将boss结构作为参数,并返回一个字符串
g. plot()将map结构的指针作为参数,并返回一个字符串

a. void igor(void);
b. float tofu(int n);
c. double mpg(double m, double n);
d. long summation(long arr[], int size);
e. double doctor(const char* str);
f. char* ofcourse(boss bs);
g. char* plot(map *mp);

3. 编写一个接受3个参数的函数:int 数组名、数组长度和一个int值,并将数组的所有元素设为该int值。

void setArrValue(int arr[], int size, int value)
{
    for(int i = 0, i < size; i++)
    {
        arr[i] = value;
    }
}

4. 编写一个接受3个参数的函数:指向数组区间中第一个元素的指针、指向数组最后一个了元素后面的指针以及一个int值,并将数组中的每个元素都设置为该int值。

void setArr(int* begin,int *end, int value)
{
    for(int* pt = begin; pt != end; pt++)
    {
        *pt = value;
    }
}

5. 编写将double数组名和数组长度作为参数,并返回该数组中最大值的函数。该函数不应该修改数组的内容。

double OutMaxValue(const double arr[], int size)
{
    double max;
    if(size < 1)
    {
        cout << "Array size is INVALID!" << endl;
        cout << "will return 0."
        return 0;
    }
    else
    {
        max = arr[0];
        for(int i =0; i < size; i++)
        {
            if(max < arr[i])
                max = arr[i];
        }
        return 0;
     }
 }

6. 为什么不对类型为基本类型的函数参数使用const限定符?

因为函数在调用参数时,使用的是参数的副本,不是原来的值,因此不会修改作为实参的基本类型的值,原数据就得到了保护。但是对于指针,需要使用const来防止指向的原始数据被修改。

7. C++程序可以使用哪三种C-风格的字符串格式?

字符串可以存储在char数组中,可以用带双引号的字符串来表示,也可以用指向字符串第一个字符的指针表示。

8. 编写一个函数,其原型如下:

int replace(char * str, char c1, char c2)

该函数将字符串中所c1都替换为c2,并返回替换次数。

int replance(char*str, char c1, char c2)
{
    int count = 0;
    while(*str)
    {
        if(*str == c1)
        {
            *str = c2;
            count++;
        }
        str++;
    }
    return count;
}

9.表达式*"pizza"的含义是什么?"taco"[2]呢?

c++将*"pizza"中"pizza"解释为其第一个元素的地址,在使用*运算符将得到第一个元素的值,即字符p。c++将"taco"解释为其第一个元素的地址,因此它将"taco[2]"解释为第2个元素的值,即字符c。(注:字符常量的行为与数组名相同)

10. C++允许按值传递结构,也允许传递结构的地址,如果glitz是一个结构变量,如何按值传递它?如何传递他的地址?这两种方法有什么利弊?

如果要按值传递,只需要传递结构名glitz即可。若传递地址,需要使用地址运算符&glitz。按值传递可以保护原始数据,但是牺牲内存和时间为代价。按地址传递可以节省时间和内存,但是不能保护原始数据,除非使用const限定符。(按值传递意味着可以使用常规的结构成员表示法,但传递指针必须使用间接成员运算符。)

11.函数judge()的返回类型为int,它将这样一个函数的地址作为参数 :将const char指针作为参数,并返回一个int值。请编写judge()函数原型。

int judge(int (*pf)(const char*))

12.假设有如下结构声明:

struct applicant
{
    char name[30];
    int credit_ratings[3];
}

a.编写一个函数,将它的applicant结构作为参数,并显示该结构的的内容。
b.编写一个函数,将applicant结构作的地址作为参数,并显示该结构的内容。

//a.applicant结构作为参数
void display(applicant ap)
{
    cout  <<  ap.name << endl;
    for(int i = 0; i < 3; i++)  
    {
         cout << ap.credit_ratings[i] << endl;
    }
}

//b.applicant结构的地址作为参数
void display(applicant *ap)
{
    cout  <<  ap->name << endl;
    for(int i = 0; i < 3; i++)  
    {
         cout << ap->credit_ratings[i] << endl;
    }
}

13.假设函数f1()和f2()的原型如下:

void f1(applicant *a)
const char * f2(const applicant *a1, const applicant *a2)

请将p1和p2分别声明指向f1和f2的指针;将ap声明为一个数组,它包含5个类型的与p1相同的指针;将pa声明为一个指针,它指向的数组包含10个类型与p2相同的指针。使用typedef来帮助完完成这项工作。

typedef void (* pf1) (applicant *a);
typedef void (* pf2) (const applicant *a1, const applicant *a2);
pf1 p1 = f1;
pf2 p2 = f2;
pf1 ap[5];
pf2 (*pa)[10];

编程练习

1.编写一个程序,不断要求用户输入两个数,直到其中一个为0。对于每两个数,程序将使用一个函数来计算它的调和平均数,并将结果返回给main(),而后者将报告结果。调和平均数指的是倒数平均值的倒数,计算公式如下:

调和平均数=2.0*x*y/(x+y)

代码实现:

#include<iostream>
using namespace std;

double calculateHarmonicMean(double x, double y);

int main()
{
    double a, b;
    cout << "Please enter two numbers (if one is zero, stop):";
    cin >> a;
    cin >> b;
    while (a && b)
    {
        cout << "Harmonic mean of " << a << " and " << b << " = " << calculateHarmonicMean(a, b) << endl;
        cout << "Enter agen(if one is zero, stop):";
        (cin >> a) >> b;
    }
    system("pause");
    return 0;
}

double calculateHarmonicMean(double x, double y)
{
    return 2.0 * x * y / (x + y);
}

2.编写一个程序,要求用户输入最多10个高尔夫成绩,并将其存入到一个数组中。程序允许用户提早结束输入,并在一行上显示所有成绩,然后报告平均成绩。请使用3个数组处理函数来分别进行输入、显示和计算平均成绩。

代码实现:

#include<iostream>
using namespace std;

double SCORES[10];
int fillScore(double* score);
void display(double* score, int n);
double getAverage(double* score, int n);

int main()
{
    double scores[10] = { 0 };
    int n = fillScore(scores);
    display(scores, n);
    cout << "AVERAGESCORE: " << getAverage(scores, n) << endl;
    system("pause");
    return 0;
}

int fillScore(double* score)
{
    cout << "Please enter the scores(maximum quantity=10),"<< endl;
    cout << "If you want to end the input, enter a letter!" << endl;
    double value;
    int i;
    for (i = 0; i < 10; i++)
    {
        cout << "enter the " << i + 1 << " Score:";
        if (i > 9)
            break;
        else
        {
            if (cin >> value)
                score[i] = value;
            else
                break;
        } 
    }
    cout << "QUANTITY: " << i << endl;
    return i;
}

void display(double* score, int n)
{
    cout << "SCORES: ";
    for (int i = 0; i < n; i++)
        cout << score[i] << " ";
    cout << endl;
}

double getAverage(double* score, int n)
{
    double sum=0;
    for (int i = 0; i < n; i++)
        sum += score[i];
    return sum / n;
}

3.下面是一个结构声明:

struct box
{
    char marker[40];
    float height;
    float width;
    float length;
    float volume;
};

a.编写一个函数,按值传递box结构,并显示每个成员的的值。

b.编写一个函数,传递box结构的地址,并将volume成员设置为其他三维长度的成绩。

c.编写一个使用这两个函数的简单程序。

代码实现:

#include<iostream>
using namespace std;

struct box
{
    char marker[40];
    float height;
    float width;
    float length;
    float volume;
};

void calculationBoxVolume(box* pbox);
void display(box bx);

int main()
{
    box bx = { "jianmo1993",1.0,1.0,1.0,0.0 };
    calculationBoxVolume(&bx);
    display(bx);
    system("pause");
    return 0;
}

void display(box bx)
{
    cout << "BOX'S INFORMATION:" << endl;
    cout << "maker : " << bx.marker << endl;
    cout << "height : " << bx.height << endl;
    cout << "width : " << bx.width << endl;
    cout << "length : " << bx.length << endl;
    cout << "volume : " << bx.volume << endl;
}

void calculationBoxVolume(box* pbox)
{
    pbox->volume = pbox->height * pbox->length * pbox->width;
}

4.许多州的彩票发行机构都使用如程序清单7.4所示的简单彩票玩法的变体。在这些玩法中,玩家从一组被称为域号码(field number)的号码中选择几个。例如,可以从域号码1~47中选择5个号码;还可以从第二个区间(如1~27)选择一个号码(成为特选号码)。要赢得头奖,必须正确猜中所有的号码。中头奖的几率是选中所有域号码的几率与选中特选号几率的乘积。例如,在这个例子中,中头奖的几率从47个号码中正确选取5个号码的几率与从27个号码中正确选择1个号码的几率的乘积。请修改程序清单7.4,以计算中得这中彩票头奖的几率。

代码实现:

#include<iostream>

using namespace std;

long double probability(unsigned numbers, unsigned picks);

int main()
{
    long double result1,result2, result;
    result1 = probability(47, 5);
    result2 = probability(27, 1);
    result = result1 * result2;
    cout << "Odds of lottery jackpot : " << result << endl;

    system("pause");
    return 0;
}

long double probability(unsigned numbers, unsigned picks)
{
    long double result = 1.0;
    unsigned n, p;
    for (n = numbers, p = picks; p > 0; n--, p--)
    {
        result = result * p / n;
    }
    return result;
}

5.定义一个递归函数,接受一个整数参数,并返回该参数的阶乘。前面讲过,3的阶乘写作3!,等于3*2!,以此类推;而0!的阶乘被定义为1。被定义为1.通用的计算公式是,如果n大于零 , 则n! = n * (n - 1)!。在程序中对该函数进行测试,程序使用循环让用户 输入不同的值,程序将报告这些值的阶乘。

代码实现:

#include<iostream>

using namespace std;

long factorial(long n);

int main()
{
    long n;
    cout << "CALCULATION OF FACTORIAL" << endl;
    cout << "Enter number : ";
    while (cin >> n)
    {
        long result = factorial(n);
        cout << n << "! = " << result << endl;
        cout << "Next number(q to quit):";
    }
    cout << "Bye!" << endl;
    system("pause");
    return 0;
}

long factorial(long n)
{
    if (n == 1 || n == 0)
        return 1;
    else
        return n * factorial(n - 1);
}

6.编写一个程序,它使用下列函数:

` Fill_array()`将一个double数组的名称和长度作为参数。它提示用户输入double值,并将这些值存储到数组中。当数组被填满或 用户输入了非数字时,输入将停止,并返回实际输入了多少个数字。

`Show_array()`将一个double数组的名称和长度作为参数,并显示该数组的内容。

`Reverse-array()`将一个double数组的名称和长度作为参数,并将存储在数组中的值的顺序反转。

程序将使用这些函数来填充数组,然后显示数组;反转数组,然后显示数组;反转数组中除第一个和最后一个元素之外的所有元素, 然后显示数组。

代码实现:

#include<iostream>

using namespace std;

const int n = 5;

int Fill_array(double* arr, int n);
void Show_array(double* arr, int n);
void Reverse_array(double* arr, int n);


int main()
{
    double arr[n] = { 0.0 };
    Fill_array(arr, n);
    Show_array(arr, n);
    Reverse_array(arr, n);
    Show_array(arr, n);

    system("pause");
    return 0;
}

int Fill_array(double* arr, int n)
{
    cout << "Please enter double number : ";
    int i;
    for (i = 0; i < n; i++)
    {
        if (cin >> arr[i])
        {
            cout << "Enter next number : ";
        }
        else
        {
            cout << "Type enter error!" << endl;
        }
    }
    return i;
}

void Show_array(double* arr, int n)
{
    cout << "ARRAY MEMBER : ";
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;
}

void Reverse_array(double* arr, int n)
{
    int med = n / 2;
    double temp;
    for (int i = 0; i < med; i++)
    {
        temp = arr[i];
        arr[i] = arr[n - 1 - i];
        arr[n - 1 - i] = temp;
    }
}

7.修改程序清单7.7中的3个数组处理函数,使之使用两个指针参数来表示区间。file_array()函数不返回实际读取了多少个数字,而是返回一个指针,该指针指向最后被填充的位置。其他的函数可以将该指针作为第二个参数,以标识数据结尾。

清单7.7:

/*******************************-清单7.7********************************/


// arrfun3.cpp -- array functions and const
#include <iostream>
const int Max = 5;

// function prototypes
int fill_array(double ar[], int limit);
void show_array(const double ar[], int n);  // don't change data
void revalue(double r, double ar[], int n);

int main()
{
    using namespace std;
    double properties[Max];

    int size = fill_array(properties, Max);
    show_array(properties, size);
    if (size > 0)
    {
        cout << "Enter revaluation factor: ";
        double factor;
        while (!(cin >> factor))    // bad input
        {
            cin.clear();
            while (cin.get() != '\n')
                continue;
           cout << "Bad input; Please enter a number: ";
        }
        revalue(factor, properties, size);
        show_array(properties, size);
    }
    cout << "Done.\n";
    // cin.get();
    // cin.get();
    return 0;
}

int fill_array(double ar[], int limit)
{
    using namespace std;
    double temp;
    int i;
    for (i = 0; i < limit; i++)
    {
        cout << "Enter value #" << (i + 1) << ": ";
        cin >> temp;
        if (!cin)    // bad input
        {
            cin.clear();
            while (cin.get() != '\n')
                continue;
           cout << "Bad input; input process terminated.\n";
           break;
        }
        else if (temp < 0)     // signal to terminate
            break;
        ar[i] = temp;
    }
    return i;
}

// the following function can use, but not alter,
// the array whose address is ar
void show_array(const double ar[], int n)
{
    using namespace std;
    for (int i = 0; i < n; i++)
    {
        cout << "Property #" << (i + 1) << ": $";
        cout << ar[i] << endl;
    }
}

// multiplies each element of ar[] by r
void revalue(double r, double ar[], int n)
{
    for (int i = 0; i < n; i++)
        ar[i] *= r;
}

/**********************************************************************/

代码实现:

/*******************************-清单7.7********************************/

#include <iostream>
const int Max = 5;

// function prototypes
double* fill_array(double* begin, double* end);
void show_array(double* begin, double* end);  // don't change data
void revalue(double r, double* start, double* end);

int main()
{
    using namespace std;
    double properties[Max];

    double* end = fill_array(properties, properties + Max - 1);
    show_array(properties, end);
    if ((end - properties) > 0)
    {
        cout << "Enter revaluation factor: ";
        double factor;
        while (!(cin >> factor))    // bad input
        {
            cin.clear();
            while (cin.get() != '\n')
                continue;
            cout << "Bad input; Please enter a number: ";
        }
        revalue(factor, properties, end);
        show_array(properties, end);
    }
    cout << "Done.\n";
    // cin.get();
    // cin.get();
    return 0;
}

double* fill_array(double* begin, double* end)
{
    using namespace std;
    double* temp;
    int i = 0;
    for (temp = begin; temp <= end; temp++)
    {
        cout << "Enter value #" << (i + 1) << ": ";
        cin >> *temp;
        if (!cin)    // bad input
        {
            cin.clear();
            while (cin.get() != '\n')
                continue;
            cout << "Bad input; input process terminated.\n";
            break;
        }
        else if (*temp < 0)     // signal to terminate
            break;
    }
    return temp - 1;
}

void show_array(double* begin, double* end)
{
    using namespace std;
    double* p;
    int i = 0;
    for (p = begin; p <= end; p++)
    {
        cout << "Property #" << (i + 1) << ": $";
        cout << *p << endl;
    }
}1

void revalue(double r, double* start, double* end)
{
    double* p;
    for (p = start; p <= end; p++)
        *p *= r;
}

8.在不使用array类的情况下完成程序清单7.15所做的工作。编写两个这样的版本:

a.使用const char *数组存储表示季度名称的字符串,并使用double数组存储开支。

b.使用const char *数组存储表示季度名称的字符串,并使用一个结构,该结构只有一个成员——一个用于存储开支的double数组。这种设计与使用array类基本设计类似。

清单7.15:

//arrobj.cpp -- functions with array objects
#include <iostream>
#include <array>
#include <string>
const int Seasons = 4;
const std::array<std::string, Seasons> Snames =
    {"Spring", "Summer", "Fall", "Winter"};

void fill(std::array<double, Seasons> * pa);
void show(std::array<double, Seasons> da);
int main()
{
    std::array<double, 4> expenses;
    fill(&expenses);
    show(expenses);
    // std::cin.get();
    // std::cin.get();
    return 0;
}

void fill(std::array<double, Seasons> * pa)
{
    for (int i = 0; i < Seasons; i++)
    {
        std::cout << "Enter " << Snames[i] << " expenses: ";
        std::cin >> (*pa)[i];
    }
}

void show(std::array<double, Seasons> da)
{
    double total = 0.0;
    std::cout << "\nEXPENSES\n";
    for (int i = 0; i < Seasons; i++)
    {
        std::cout << Snames[i] << ": $" << da[i] << '\n';
        total += da[i];
    }
    std::cout << "Total: $" << total << '\n';
}

/********************************************************************/

代码实现:

a.

#include <iostream>
#include <array>
#include <string>
const int Seasons = 4;
const char* Snames[Seasons] =
{ "Spring", "Summer", "Fall", "Winter" };

void fill(double* pa, int n);
void show(double* da, int n);
int main()
{
    double expenses[Seasons];
    fill(expenses, Seasons);
    show(expenses, Seasons);

    return 0;
}

void fill(double* pa, int n)
{
    for (int i = 0; i < n; i++)
    {
        std::cout << "Enter " << Snames[i] << " expenses: ";
        std::cin >> pa[i];
    }
}

void show(double* da, int n)
{
    double total = 0.0;
    std::cout << "\nEXPENSES\n";
    for (int i = 0; i < n; i++)
    {
        std::cout << Snames[i] << ": $" << da[i] << '\n';
        total += da[i];
    }
    std::cout << "Total: $" << total << '\n';
}

b.

#include <iostream>
#include <array>
#include <string>
const int Seasons = 4;
const char* Snames[Seasons] =
{ "Spring", "Summer", "Fall", "Winter" };

struct Expenses
{
    double expenses[Seasons];
};
void fill(Expenses* exp, int n);
void show(Expenses* exp, int n);
int main()
{
    Expenses expenses;
    fill(&expenses, Seasons);
    show(&expenses, Seasons);

    return 0;
}

void fill(Expenses* exp, int n)
{
    double* pa = exp->expenses;
    for (int i = 0; i < n; i++)
    {
        std::cout << "Enter " << Snames[i] << " expenses: ";
        std::cin >> pa[i];
    }
}

void show(Expenses* exp, int n)
{
    double* da = exp->expenses;
    double total = 0.0;
    std::cout << "\nEXPENSES\n";
    for (int i = 0; i < n; i++)
    {
        std::cout << Snames[i] << ": $" << da[i] << '\n';
        total += da[i];
    }
    std::cout << "Total: $" << total << '\n';
}

9.这个练习让您编写处理数组和结构的函数。下面是程序的框架,请提供其中描述的函数,以完成该程序。

#include <iostream>
using namespace std;

const int SLEN = 30;
struct student {
    char fullname[SLEN];
    char hobby[SLEN];
    int ooplevel;
};
// getinfo() has two arguments: a pointer to the first element of
// an array of student structures and an int representing the
// number of elements of the array. The function solicits and
// stores data about students. It terminates input upon filling
// the array or upon encountering a blank line for the student
// name. The function returns the actual number of array elements
// filled.
int getinfo(student pa[], int n);
// display1() takes a student structure as an argument
// and displays its contents
void display1(student st);
// display2() takes the address of student structure as an
// argument and displays the structure’s contents
void display2(const student* ps);
// display3() takes the address of the first element of an array
// of student structures and the number of array elements as
// arguments and displays the contents of the structures
void display3(const student pa[], int n);
int main()
{
    cout << "Enter class size : ";
    int class_size;
    cin >> class_size;
    while (cin.get() != '\n')
        continue;
    student* ptr_stu = new student[class_size];
    int entered = getinfo(ptr_stu, class_size);
    for (int i = 0; i < entered; i++)
    {
        display1(ptr_stu[i]);
        display2(&ptr_stu[i]);
    }
    display3(ptr_stu, entered);
    delete[] ptr_stu;
    cout << "Done\n";
    return 0;
}

代码实现:

#include <iostream>
using namespace std;

const int SLEN = 30;
struct student {
    char fullname[SLEN];
    char hobby[SLEN];
    int ooplevel;
};

int getinfo(student pa[], int n);
void display1(student st);
void display2(const student* ps);
void display3(const student pa[], int n);

int main()
{
    cout << "Enter class size : ";
    int class_size;
    cin >> class_size;
    while (cin.get() != '\n')
        continue;
    student* ptr_stu = new student[class_size];
    int entered = getinfo(ptr_stu, class_size);
    for (int i = 0; i < entered; i++)
    {
        display1(ptr_stu[i]);
        display2(&ptr_stu[i]);
    }
    display3(ptr_stu, entered);
    delete[] ptr_stu;
    cout << "Done\n";
    return 0;
}

int getinfo(student pa[], int n)
{
    int num = 0;
    for (int i = 0; i < n; i++)
    {
        cout << "Enter #" << i + 1 << " student' info:" << endl;
        cout << "fullname : ";
        cin.getline(pa[i].fullname, SLEN);
        if (pa[i].fullname[0] == '\0')
            break;
        cout << "hobby : ";
        cin.getline(pa[i].hobby, SLEN);
        cout << "ooplevel : ";
        (cin >> pa[i].ooplevel).get();

        num++;
    }
    return num;
}
void display1(student st)
{
    cout << "name: " << st.fullname << endl;
    cout << "hobby: " << st.hobby << endl;
    cout << "ooplevel: " << st.ooplevel << endl;
}
void display2(const student* ps)
{
    cout << "name: " << ps->fullname << endl;
    cout << "hobby: " << ps->hobby << endl;
    cout << "ooplevel: " << ps->ooplevel << endl;
}
void display3(const student pa[], int n)
{
    for(int i = 0; i < n; i++)
    {
        display2(&pa[i]);
    } 
}

10.设计一个名为calculate()的函数,它接受两个double值和一个指向函数的指针,而被指向的函数接受两个double参数,并返回一个double值。calculate()函数的类型也是double,并返回被指向的函数使用calculate()的两个double参数计算得到的值。例如,假设add()函数的定义如下:

double add (double x, double y)
{
    return x + y;
}

则下述代码中的函数调用将导致calculate()把2.5和10.4传递给add()函数,并返回add()的返回值(12.9):

double q = calculate (2.5, 10.4, add);

请编写一个程序,它调用上述两个函数和至少另一个与add()类似的函数。该程序使用循环来让用户成对地输入数字。对于每对数字,程序都使用calculate()来调用add()和至少一个其他的函数。如果读者爱冒险,可以尝试创建一个指针数组,其中的指针指向add()样式的函数,并编写一个循环,使用这些指针连续让calculate()调用这些函数。提示:下面是声明这种指针数组的方式,其中包含三个指针:

double (*pf[3]) (double, double);

可以采用数组初始化语法,并将函数名作为地址来初始化这样的数组。

代码实现:

#include <iostream>
using namespace std;

typedef double (*pfunc)(double x, double y);
double add(double x, double y);
double multiply(double x, double y);
double calculate(double x, double y, pfunc pf);

int main()
{
    pfunc pf[2] = {add, multiply};
    cout << "Please enter two numbers : ";
    double a, b;
    while ((cin >> a) >> b)
    {
        for (int i = 0; i < 2; i++)
        {
            cout << a;
            if(i == 0)
                cout << " + ";
            else
                cout << " * ";
            cout << b << " = " << calculate(a, b, pf[i]) << endl;
        }
        cout << "Next two numbers(q to quit) : ";
    }

    return 0;
}

double add(double x , double y)
{
    return x + y;
}
double multiply(double x, double y)
{
    return x * y;
}
double calculate(double x, double y, pfunc pf)
{
    return pf(x, y);
}

第八章课后习题答案 

复习题

1.哪种函数适合定义为内联函数?

只有一行代码的小型、非递归的函数适合作为内联函数。

2假设song()函数的原形如下:

void song(const char * name, int times);

a.如何修改原形,使times的默认值为1?

b.函数定义需要做哪些修改?

c.能否为name提供默认值"O,My Papa"?

a.void song(const char * name, int times = 1);

b.函数定义不需要修改,只有函数原型包含默认信息。

c.可以,void song(char * name ="O,My Papa", int times = 1);

3.编写iquote()的重载版本--显示其用双引号括起的参数,编写3个版本:一个用于int参数,一个用于double参数,另一个用于string参数。

//用于 int 参数
void iquote(int n)
{
    cout << "\"" << n << "\"" << endl;
}
//用于 double 参数
void iquote(couble n)
{
    cout << "\"" << n << "\"" << endl;
}
//用于 string 参数
void iquote(char * str)
{
    cout << "\"" << str << "\"" << endl;
}

4.下面是一个结构模板:

struct box
{
    char maker[40];
    float height;
    float width;
    float length;
    float volume;
}

a.请编写一个函数,他将box结构体的引用作为形参,并显示每个成员的值。

b.请编写一个函数,他将box结构的引用作为行参,并将volume成员设置为其他3边的乘积。

a.

void showBox(const box & b)
{
    cout << "maker : " << b.maker << endl;
    cout << "height : " << b.height <<endl;
    cout << "width : " << b.width << endl;
    cout << "length : " << b.length <<endl;
    cout << "volume : " << b.volume << endl;
}

b.

void setVolume(box & b)
{
    b.volume = b.height * b.width * b.length;
}

5.为让函数fill()和show()使用引用参数,需要对程序清单7.15做哪些修改?

修改后的代码:

#include <iostream>
#include <array>
#include <string>
const int Seasons = 4;
const std::array<std::string, Seasons> Snames =
    {"Spring", "Summer", "Fall", "Winter"};

void fill(std::array<double, Seasons> &pa);
void show(const std::array<double, Seasons> &da);
int main()
{
    std::array<double, 4> expenses;
    fill(expenses);
    show(expenses);
    return 0;
}

void fill(std::array<double, Seasons> &pa)
{
    for (int i = 0; i < Seasons; i++)
    {
        std::cout << "Enter " << Snames[i] << " expenses: ";
        std::cin >> pa[i];
    }
}

void show(const std::array<double, Seasons> &da)
{
    double total = 0.0;
    std::cout << "\nEXPENSES\n";
    for (int i = 0; i < Seasons; i++)
    {
        std::cout << Snames[i] << ": $" << da[i] << '\n';
        total += da[i];
    }
    std::cout << "Total: $" << total << '\n';
}

6.指出下面每个目标是否可以使用默认参数或函数重载完成,或者这两种方法都无法完成,并提供合适的原型。

a. mass(density,volume)返回密度为density、体积为volume的物体的质量,而mass(density)返回密度为density、体积为1.0立法米的物体的质量。这些值的类型都为double。

b. repeat(10,"I'm OK")将指定的字符串显示10次,而repeat("But you're kind of stupid")将指定的字符串显示5次。

c. average(3,6)返回两个int参数的平均值(int类型),而average(3.0,6.0)返回两个double值的平均值(double类型)。

d. mangle("I'm glad to meet you")根据是将值赋给char变量还是char*变量,分别返回字符1和指向字符串“I'm glad to meet you”的指针。

a.

//既可以使用默认参数,又可以使用函数重载
//1.默认参数
double mass(double density, double volume = 1.0);

//2.函数重载
double mass(double density, double volume);
double mass(double density);

b.

//不能使用默认参数,因为使用默认值必须从右到左提供默认值
//函数重载
void repeat(int times, const char* str);
void repeat(const char* str);

c.

//函数重载
int average(int a, int b);
double average(double a, double b);

d.两种方法都不能完成,需分成两个不同的函数实现。

7.编写返回两个参数中较大值的函数模板。

代码实现:

template<class T>
T max(T t1, T t2)
{
    return t1 > t2 ? t1 : t2;
}

8.给定复习题6的模板和复习题4的box结构,提供一个模板具体化,它接受两个box参数,并返回体积较大的一个。

代码实现:

template<>
box max(box b1, box b2)
{
    return b1.volume > b2.volume ? b1 : b2;
}

9.在下述代码(假定这些代码是一个完整程序的一部分)中,v1、v2、v3、v4和v5分别是哪种类型?

int g(int x);

....

float m = 5.5f;

float &rm = m;

decltype(m)v1 = m;

decltype(rm)v2 = m;

decltype((m)) v3 = m;

decltype(g(100))v4;

decltype(2.0*m)v5;

decltype(m)v1 = m;     //类型为float
decltype(rm)v2 = m;    //类型为float &
decltype((m)) v3 = m;  //类型为float &
decltype(g(100))v4;    //类型为int
decltype(2.0*m)v5;     //类型为double

编程练习

1. 编写通常接受一个参数(字符串的地址),并打印该字符串的函数。然而,如果提供了第二个参数(int类型),且该参数不为0,则该函数打印字符串的次数将为该函数被调用的次数(注意,字符串的打印次数不等于第二个参数的值,而等于函数被调用的次数)。是的,这是一个非常可笑的函数,但它让您能够使用本章介绍的一些技术。在一个简单的程序中使用该函数,以演示该函数是如何工作的。

代码实现:

#include<iostream>

using namespace std;

int myShowStr(char* str, int printTimes);

int main()
{
    char mystr[50] = "Hello,world!";
    myShowStr(mystr, 5);
    return 0;
}

int myShowStr(char* str, int printTimes)
{
    if(printTimes > 1)
    {
        cout << str << endl;
        printTimes--;
        myShowStr(str, printTimes);
    }
    else
    {
        cout << str << endl;
    }
    return printTimes;
}

2. CandyBar结构包含3个成员,第一个成员存储candy bar的品牌名称;第二个成员存储candy bar的重量(可能有小数);第三个成员存储candy bar的热量(整数)。请编写一个程序,它使用一个这样的函数,即将CandyBar的引用、char指针、double和int作为参数,并用最后3个值设置相应的结构成员。最后3个参数的默认值分别为“Millennium Munch”、2.85和350。另外,该程序还包含一个以CandyBar的引用为参数,并显示结构内容的函数。请尽可能使用const。

代码实现:

#include<iostream>
using namespace std;
#define DEFAULT_BRAND  (char*)"Millennium Munch"
struct CandyBar{
    char* brand;
    double weight;
    int heat;
};
void setCandyBar(CandyBar& candyBar, char* brand = DEFAULT_BRAND, double weight = 2.85, int heat = 350);
void display(const CandyBar& candyBar);

int main()
{
    CandyBar cb,cb1;
    setCandyBar(cb1);
    setCandyBar(cb, (char*)"MJJ", 3.55, 120);
    display(cb);
    display(cb1);
    return 0;
}

void setCandyBar(CandyBar& candyBar, char *brand, double weight, int heat)
{
    candyBar.brand = brand;
    candyBar.weight = weight;
    candyBar.heat = heat;
}

void display(const CandyBar& candyBar)
{
    cout << "BRAND : " << candyBar.brand << endl;
    cout << "WEIGHT : " << candyBar.weight << endl;
    cout << "HEAT : " << candyBar.heat << endl;
}

3. 编写一个函数,它接受一个指向string对象的引用作为参数,并将该string对象的内容转化成大写,为此可以使用表6.4描述的函数toupper()。然后编写一个程序,它通过使用一个循环让您能够用不同的输入来测试这个函数,该程序的运行如下:

Enter a string (q to quit):go away
GO AWAY
Enter a string (q to quit):good grief!
GOOD GRIEF!
Enter a string (q to quit):q
Bye.

代码实现:

#include<iostream>
#include<string>
using namespace std;
void Conversion(string& str);
int main()
{
    string str;
    cout<<"Enter a string(q to quit): ";
    while(getline(cin,str) && str != "q")
    {
        Conversion(str);
        cout << str << endl;
        cout << "Next string(q to quit): ";
    }
    cout << "Bye." << endl;
    return 0;
}

void Conversion(string& str)
{
    int size = str.size();
    for(int i =0; i < size; i++)
    {
        str[i] = toupper(str[i]);
    }
}

4.下面是一个程序框架:

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

struct stringy{
    char * str;
    int ct;
};

int main()
{
    stringy beany;
    char testing[] = "Reality isn't what it used to be.";
    set(beany, testing);
    show(beany);
    show(beany, 2);
    testing[0] = 'D';
    testing[1] = 'u';
    show(testing);
    show(testing, 3);
    show("Done!");

    return 0;
}

请提供其中描述的函数和原型,从而完成该程序。注意,应有两个show()函数,每个都使用默认参数。请尽可能使用const参数。set()使用new分配足够的空间来存储指定的字符串。这里使用的技术与设计和实现类时使用的相似。(可能还必须修改头文件的名称,删除using编译指令,这取决于所用的编译器)。

代码实现:

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

struct stringy{
    char * str;
    int ct;
};

void set(stringy& stry, const char* test);
void show(const stringy& stry, int showTimes = 1);
void show(const char* ch, int showTimes = 1);
int main()
{
    stringy beany;
    char testing[] = "Reality isn't what it used to be.";
    set(beany, testing);
    show(beany);
    show(beany, 2);
    testing[0] = 'D';
    testing[1] = 'u';
    show(testing);
    show(testing, 3);
    show("Done!");

    return 0;
}

void set(stringy& stry, const char* test)
{
    stry.ct = strlen(test);
    stry.str = new char[stry.ct];
    strcpy(stry.str, test);
}

void show(const stringy& stry, int showTimes)
{
    for(int i =0; i < showTimes; i++)
    {
        cout << stry.str <<endl;
    }
}

void show(const char* ch, int showTimes)
{
    for(int i =0; i < showTimes; i++)
    {
        cout << ch <<endl;
    }
}

5.编写模板函数max5(),它将一个包含5个T类型元素的数组作为参数,并返回数组中最大的元素(由于长度固定,因此可以在循环中使用硬编码,而不必通过参数来传递)。在一个程序使用该函数,将T替换为一个包含5个int值的数组和一个包含5个double值的数组,以测试该函数。

代码实现:

#include<iostream>

using namespace std;

template<typename T>
T max5(T *t);

int main()
{
    int arr1[5] = {5, 3, 5, 9, 6};
    double arr2[5] = {5.2, 3.1, 6.8, 10.8, 7.1};
    cout << "arr1 max num : " << max5(arr1) << endl;
    cout << "arr2 max num : " << max5(arr2) << endl;
    return 0;
}

template<typename T>
T max5(T* t)
{
    T maxValue = t[0];
    for(int i = 1; i < 5; i++)
    {
        if(maxValue < t[i])
        {
            maxValue = t[i];
        }
    }
    return maxValue;
}

6.编写模板函数maxn(),他将由一个T类型元素组成的数组和一个表示数组元素数目的整数作为参数,并返回数组中最大的元素。在程序对它进行测试,该程序使用一个包含6个int元素的数组和一个包含4个都不了元素的数组来调用该函数。程序还包含一个具体化,他将char指针数组和数组中的指针数量作为参数,并返回最长的字符串的地址。如果有多个这样的字符串,则返回其中第一个字符串的地址。使用由5个字符串指针组成的数组来测试该具体化。

代码实现:

#include<iostream>
#include<cstring>

using namespace std;

template<typename T>
T maxn(T* t, int n);

template<>
char* maxn(char* pch[], int n);

int main()
{
    int arr1[6] = {5, 3, 5, 9, 6, 11};
    double arr2[4] = {5.2, 3.1, 2.8, 4.8};
    char const * arr3[5] = {
        "abcde",
        "abcdef",
        "abc",
        "ab",
        "abcdefg"
    };
    cout << "arr1 max num : " << maxn(arr1, 6) << endl;
    cout << "arr2 max num : " << maxn(arr2, 4) << endl;
    cout << "arr3 max len : " << maxn(arr3, 5) << endl;
    return 0;
}

template<typename T>
T maxn(T* t, int n)
{
    T maxValue = t[0];
    for(int i = 1; i < n; i++)
    {
        if(maxValue < t[i])
        {
            maxValue = t[i];
        }
    }
    return maxValue;
}

template<>
char* maxn(char* pch[], int n)
{
    auto maxLen = strlen(pch[0]);
    int index = 0;
    for(int i = 1; i < n; i++)
    {
        if(maxLen < strlen(pch[i]))
        {
            maxLen = strlen(pch[i]);
            index = i;
        }
    }
    return pch[index];
}

7.修改程序清单8.14,使其使用两个名为SumArray()的模板函数来返回数组元素的总和,而不是显示数组的内容。程序应显示thing的总和以及所有debt的总和。

/******************程序清单8.14******************/
// tempover.cpp --- template overloading
#include <iostream>

template <typename T>            // template A
void ShowArray(T arr[], int n);

template <typename T>            // template B
void ShowArray(T * arr[], int n);

struct debts
{
    char name[50];
    double amount;
};

int main()
{
    using namespace std;
    int things[6] = {13, 31, 103, 301, 310, 130};
    struct debts mr_E[3] =
    {
        {"Ima Wolfe", 2400.0},
        {"Ura Foxe", 1300.0},
        {"Iby Stout", 1800.0}
    };
    double * pd[3]; 

// set pointers to the amount members of the structures in mr_E
    for (int i = 0; i < 3; i++)
        pd[i] = &mr_E[i].amount;

    cout << "Listing Mr. E's counts of things:\n";
// things is an array of int
    ShowArray(things, 6);  // uses template A
    cout << "Listing Mr. E's debts:\n";
// pd is an array of pointers to double
    ShowArray(pd, 3);      // uses template B (more specialized)
    // cin.get();
    return 0;
}

template <typename T>
void ShowArray(T arr[], int n)
{
    using namespace std;
    cout << "template A\n";
    for (int i = 0; i < n; i++)
        cout << arr[i] << ' ';
    cout << endl;
}

template <typename T>
void ShowArray(T * arr[], int n)
{
    using namespace std;
    cout << "template B\n";
    for (int i = 0; i < n; i++)
        cout << *arr[i] << ' ';
    cout << endl; 
}

代码实现:

#include <iostream>

template <typename T>  
T SumArray(T arr[], int n);

template <typename T>   
T SumArray(T * arr[], int n);

struct debts
{
    char name[50];
    double amount;
};

int main()
{
    using namespace std;
    int things[6] = {13, 31, 103, 301, 310, 130};
    struct debts mr_E[3] =
    {
        {"Ima Wolfe", 2400.0},
        {"Ura Foxe", 1300.0},
        {"Iby Stout", 1800.0}
    };
    double * pd[3];

    for (int i = 0; i < 3; i++)
        pd[i] = &mr_E[i].amount;

    cout << "sum of things : " << SumArray(things, 6) << endl;
    cout << "sum of debts :" << SumArray(pd, 3) << endl;;

    return 0;
}

template <typename T>
T SumArray(T arr[], int n)
{
    T sum = 0;
    for(int i =0; i < n; i++)
    {
        sum = sum + arr[i];
    }
    return sum;
}

template <typename T>
T SumArray(T * arr[], int n)
{
    T sum = 0;
    for(int i =0; i < n; i++)
    {
        sum = sum + *arr[i];
    }
    return sum;
}

第九章课后习题答案 

复习题

1. 对于下面的情况,应使用哪种存储方案?

  • a. homer是函数的形参。

  • b. secret变量由两个文件共享。

  • c. topsecret变量由一个文件中的所有函数共享,但对于其他文件来说是隐蔽的。

  • d. beencalled记录包含它的函数被调用的次数

a. home将自动成为自动变量。

b. secret在一个文件应该定义为一个外部变量,在第二个文件用extern声明。

c. 在topsecret前面添加关键字static,将topsecret定义为一个有内部链接的静态变量。或者将其在一个未命名的的名称空间中进行定义。

d. 在beencalled前面添加关键字static,将其定义为一个本地静态变量。

2.using声明和using编译指令有何区别?

using声明使得名称空间中的单个名称可用,其作用域与using所在的声明区域相同。using编译指令使名称空间中的所有名称可用。使用using编译指令时,就像在一个包含using声明和名称空间本身的最小声明区域中声明了这些名称一样。

3.重新编写下面的代码,使其不使用using声明和using编译指令。

#include <iostream>
using namespace std;

int main()
{
       double x;
       cout << "Enter value: ";
       while (!(cin >> x))
       {
            cout << "Bad input. Please enter a number: ";
            cin.clear();
            while (cin.get() != '\n')
                continue;
       }

       cout << "Value = " << x << endl;
       return 0;
}

不使用using声明和using编译指令:

#include <iostream>

int main()
{
    double x;
    std::cout << "Enter value: ";
    while (!(std::cin >> x))
    {
        std::cout << "Bad input. Please enter a number: ";
        std::cin.clear();
        while (std::cin.get() != '\n')
            continue;
    }

    std::cout << "Value = " << x << std::endl;
    return 0;
}  

4.重新编写下面的代码,使之使用using声明,而不是using编译指令。

#include <iostream>

using namespace std;
int main()
{
       double x;
       cout << "Enter value: ";
       while (!(cin >> x))
       {
           cout << "Bad input. Please enter a number: ";
           cin.clear();
           while (cin.get() != '\n')
               continue;
       }
       cout << "Value = " << x << endl;
       return 0;
}

使用using声明:

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

int main()
{
    double x;
    cout << "Enter value: ";
    while (!(cin >> x))
    {
        cout << "Bad input. Please enter a number: ";
        cin.clear();
        while (cin.get() != '\n')
            continue;
    }
    cout << "Value = " << x << endl;
    return 0;
}

5.在一个文件中调用average(3,6)函数时,它返回两个int参数平均值,在同一个程序的另一个文件中调用时,它返回两个int参数的double平均值。应如何实现?

在每个文件中使用静态函数定义。或者每个文件都在未命名空间中定义一个合适的average函数。

6.下面的程序由两个文件组成,该程序显示什么内容?

//file1.cpp
#include <iostream>

using namespace std;
void other();
void another();
int x = 10;
int y;
int main()
{
       cout << x << endl;
       {
           int x = 4;
           cout << x << endl;
           cout << y << endl;
       }
       other();
       another();
       return 0;
}

void other()
{
       int y = 1;
       cout << "Other: " << x << ", " << y << endl;
}
//file2.cpp
#include <iostream>

using namespace std;
extern int x;

namespace
{
       int y = -4;
}

void another()
{
       cout << "another() " << x << ", " << y << endl;
}
10
4
0
Other:: 10, 1
another() 10, -4

7.下面的代码将显示什么内容?

#include <iostream>

using namespace std;

void other();
namespace n1
{
       int x = 1;
}

namespace n2
{
       int x = 2;
}

int main()
{
       using namespace n1;
       cout << x << endl;
       {
           int x = 4;
           cout << x << ", " << n1::x << ", " << n2::x << endl;
       }
       using n2::x;
       cout << x << endl;
       other();
       return 0;
}
void other()
{
       using namespace n2;
       cout << x << endl;
       {
           int x = 4;
           cout << x << ", " << n1::x << ", " << n2::x << endl;
       }
       using n2::x;
       cout << x << endl;
}
1
4, 1, 2
2
2
4, 1, 2
2

编程题

1.根据这个头文件:

// golf.h -- for pe9-1.cpp
const int Len = 40;
struct golf
{
       char fullname(Len);
       int handicap;
};
// non-interactive version:
// function sets golf structure to provided name, handicap
// using values passed as arguments to the function
void setgolf(golf & g, const char * name, int hc);
// interactive version:
// function solicits name and handicap from uaer
// and sets the members of g to the valus entered
// returns 1 if name is entered, 0 if name is empty string
int setgolf(golf & g);
// function resets handicap to new value
void handicap(golf & g, int hc);
// function displays  contents of golf structure
void showgolf(const golf &g);

注意到setgolf()被重载,可以这样使用其第一个版本:

golf ann;
setgolf(ann, "Ann Birdfree", 24);

上述函数调用提供了存储在ann结构中的信息。可以这样使用其第二个版本:

golf andy;
setgolf(andy);

上述函数将提示用户输入姓名和等级,并将它们存储在andy结构中。这个函数可以(但是不一定必须)在内部使用第一个版本。

根据这个头文件,创建一个多文件程序。其中的一个文件名为golf.cpp,它提供了与头文件中的原型匹配的函数定义;另一个文件应包含main(),并演示原型化函数的所有特性。例如,包含一个让用户输入的循环,并使用输入的数据来填充一个由golf结构组成的数组,数组被填满或用户将高尔夫选手的姓名设置为空字符串时,循环将结束。main()函数只使用头文件中原型化的函数来访问golf结构。

golf.cpp:

#include "golf.h"
#include <iostream>

using namespace std;

void setgolf(golf &g, const char *name, int hc)
{
    strcpy(g.fullname, name);
    g.handicap = hc;
}

int setgolf(golf &g)
{
    cout << "please enter fullname : ";
    cin.getline(g.fullname, Len);
    if (strlen(g.fullname) == 0)
        return 0;
    else
    {
        cout << "please enter handicap : ";
        cin >> g.handicap;
        cin.get();
        return 1;
    }
}

void handicap(golf &g, int hc)
{
    g.handicap = hc;
}

void showgolf(golf &g)
{
    cout << "fullname : " << g.fullname << ", handicap : " << g.handicap << endl;
}

main.cpp:

#include "golf.h"
#include <iostream>

using namespace std;

int main()
{
    golf ann, andy, arrGolf[3];
    setgolf(ann, "Ann Birdfree", 24);
    showgolf(ann);

    if (setgolf(andy) == 1)
        showgolf(andy);
    handicap(andy, 20);
    showgolf(andy);

    int i = 0;
    while (i < 3 && setgolf(arrGolf[i]))
    {
        showgolf(arrGolf[i]);
        i++;
        if(i<3)
        cout << "next one: " << endl;
    }
    return 0;
}

2.修改程序清单9.9:

//Listing 9.9 static.cpp
// static.cpp -- using a static local variable
#include <iostream>
// constants
const int ArSize = 10;
// function prototype˜
void strcount(const char *str);
int main()
{
    using namespace std;
    char input[ArSize];
    char next;
    cout << "Enter a line:\n";
    cin.get(input, ArSize);
    while (cin)
    {

        cin.get(next);
        while (next != '\n') // string didn't fit!
            cin.get(next);   // dispose of remainder strcount(input);
        cout << "Enter next line (empty line to quit):\n";
        cin.get(input, ArSize);
    }
    cout << "Bye\n";
    return 0;
}
void strcount(const char *str)
{
    using namespace std;
    static int total = 0;
    int count = 0;
    // static local variable // automatic local variable
    cout << "\"" << str << "\" contains ";
    while (*str++) // go to end of string
        count++;
    total += count;
    cout << count << " characters\n";
    cout << total << " characters total\n";
}

用string对象代替字符数组。这样,该程序将不再需要检查输入的字符串是否过长,同时可以将输入字符串同字符串“”进行比较,以判断是否为空行。

#include <iostream>
#include <string>
void strcount(const std::string &str);

int main()
{
    using namespace std;
    string input;
    cout << "Enter a line:\n";
    getline(cin, input);
    while (input.size())
    {
        strcount(input);
        cout << "Enter next line (empty line to quit):\n";
        getline(cin, input);
    }
    cout << "Bye\n";
    return 0;
}
void strcount(const std::string &str)
{
    using namespace std;
    static int total = 0;
    int count = str.size();
    cout << "\"" << str << "\" contains ";
    total += count;
    cout << count << " characters\n";
    cout << total << " characters total\n";
}

3.下面是一个结构声明:

struct chaff
{
     char dross[20];
     int slag;
};

编写一个程序,使用定位new运算符将一个包含两个这种结构的数组放在一个缓冲区中。然后,给结构的成员赋值(对于char数组,使用函数strcpy()),并使用一个循环来显示内容。一种方法是像程序清单9.10那样将一个静态数组用作缓冲区;另一种方法是使用常规new运算符来分配缓冲。

#include <iostream>
using namespace std;

const int LEN = 512;
const int N = 3;
char buff[LEN];

struct chaff
{
    char dross[20];
    int slag;
};

int main()
{
    chaff *cf1 = new chaff[N];
    chaff *cf2 = new (buff) chaff[N];
    string temp;
    for (int i = 0; i < N; i++)
    {
        cout << "Please enter dross of #" << i + 1 << " chaff :";
        cin.getline(cf1[i].dross, 20);
        strcpy(cf2[i].dross, cf1[i].dross);
        cout << "enter slag :";
        cin >> cf1[i].slag;
        cf2[i].slag = cf1[i].slag;
        cin.ignore();
    }
    for (int i = 0; i < N; i++)
    {
        cout << "#" << i + 1 << " chaff:" << endl;
        cout << "cf1[" << i << "].dross : " << cf1[i].dross << ", slag :"
             << "cf1[" << i << "].slag : " << cf1[i].slag << endl;
        cout << "cf2[" << i << "].dross : " << cf2[i].dross << ", slag :"
             << "cf2[" << i << "].slag : " << cf2[i].slag << endl;
    }
    return 0;
}

4。请基于下面这个名称空间编写一个由3个文件组成的程序:

namespace SALES
{
    const int QUARTERS = 4;
    struct Sales
    {
        double sales [QUARTERS];
        double average;
        double max;
        double min;
    };
    // copies the lesser of 4 or n items from the array ar
    // to the sales member of s and computes and stores the 
    // average, maximum, and minimum values of the entered items;
    // remaining elements of sales ,if any, set to 0
    void setSales(Sales & s,const double ar[],int n);
    // gathers sales for 4 quarters interactively,stores them
    // in the sales member of s and computes and stores the
    // average,maximum,and minimum values
    void setSales (Sales & s);
    // display all information in structure s
    void showSales(const Sales & s);
}

第一个文件是一个头文件,其中包含名称空间:第二个文件是一个源代码文件,它对这个名称空间进行扩展,以提供这三个函数的定义;第三个文件声明两个Sales对象,并使用setSales()的交互式版本为一个结构提供值,然后使用setSales()的非交互式版本为另一个结构提供值。另外它还使用showSales()来显示这两个结构的内容。

1.sales.h

//sales.h-----头文件
namespace SALES
{
    const int QUARTERS = 4;
    struct Sales
    {
        double sales [QUARTERS];
        double average;
        double max;
        double min;
    };
    void setSales(Sales & s,const double ar[],int n);
    void setSales (Sales & s);
    void showSales(const Sales & s);
}

2.sales.cpp

//sales.cpp-----源代码文件
#include "sales.h"

using namespace std;
namespace SALES
{
    void setSales(Sales &s, const double ar[], int n)
    {
        double min = 0, max = 0, sum = 0;
        s.min = s.max = ar[0];
        for (int i = 0; i < n; i++)
        {
            s.sales[i] = ar[i];
            sum += ar[i];
            if (ar[i] > max)
            {
                max = ar[i];
            }
            if (ar[i] < min)
            {
                min = ar[i];
            }
        }
        s.average = sum / n;
    }

    void setSales(Sales &s)
    {
        cout << "Please enter 4 quarters for sales:" << endl;
        cout << "the 1 quarter :";
        cin >> s.sales[0];
        s.min = s.max = s.sales[0];
        for (int i = 1; i < 4; i++)
        {
            cout << "the " << i << " quarter :";
            cin >> s.sales[i];
            if (s.max < s.sales[i])
            {
                s.max = s.sales[i];
            }
            if (s.min > s.sales[i])
            {
                s.min = s.sales[i];
            }
        }
        s.average = (s.sales[0] + s.sales[1] + s.sales[2] + s.sales[3]) / 4;
    }

    void showSales(const Sales &s)
    {
        cout << "Display all information in sales : " << endl;
        cout << "The 4 quarters are $" << s.sales[0] << ", $" << s.sales[1] << ", $" << s.sales[2] << ", $" << s.sales[3] << endl;
        cout << "The average income is $" << s.average << endl;
        cout << "The maximum income is $" << s.max << endl;
        cout << "The minimum income is $" << s.min << endl;
    }
}

3.main.cpp

#include "sales.h"
#include <iostream>

using namespace SALES;
int main()
{
    double arr[4] = {3.4, 5.6, 2.5, 6.1};
    Sales s1, s2;
    setSales(s1, arr, 4);
    showSales(s1);
    setSales(s2);
    showSales(s2);
    return 0;
}

 

1. iostream文件在C++ I/O中扮演何种角色?

iostream文件定义了用于管理输入和输出的类、常量和操作符,这些对象用于I/O的流和缓冲区。该文件还创建了一些用于处理标准输入输出流的标准对象(如cin、cout、cerr和clog以及对应的宽字符对象)。

2. 为什么键入数字(如121)作为输入要求程序进行转换?

键盘输入会生成一系列字符,输入121将会生成3个字符,每个字符都由一个字节的二进制码表示。要将这个值存储为int类型,则必须将这3个字符转换为121值的二进制表示。

3. 标准输出与标准错误之间有什么区别?

默认情况下两者都将输出发给标准输出设备(通常为显示器)。然而,如果要求操作系统操作系统将输出重定向到文件,则标准输出将与文件相连,但标准错误仍与显示器相连。

4. 为什么在不为每个类型提供明确指示的情况下,cout仍能够显示不同的C++类型?

ostream类为每种C++基本类型定义了一个operator <<()函数的版本。编译器将类似cout << spot的表达式解释为cout.operator<<(spot),这样,它便能够将该方法调用与具有相同参数类型的函数原型匹配。

5. 输出方法的定义的哪一特征让您能够拼接输出?

返回ostream &类型的输出方法能够拼接输出。通过一个对象调用方法时,将返回该对象。然后,返回对象将可以调用序列中的下一个方法

6. 编写一个程序,要求用户输入一个整数,然后以十进制、八进制和十六进制显示该整数。在宽度为15个字符的字段中显示每种形式,并将它们显示在同一行上,同时使用C++数基前缀。

#include <iomanip>
#include <iostream>

int main() {
  using namespace std;
  cout << "Enter an interger: ";
  int n;
  cin >> n;
  cout << setw(15) << "base ten" << setw(15) << "base sixteen" << setw(15)
       << "base eight"
       << "\n";
  cout.setf(ios::showbase);
  cout << setw(15) << n << hex << setw(15) << n << oct << setw(15) << n << "\n";
  return 0;
}

7. 编写一个程序,请求用户输入下面的信息,并按下面的格式显示它们:

Enter your name: Billy Gruff
Enter your hourly wages: 12
Enter number of hours worked: 7.5
First format:
             Billy Gruff: $ 12.00: 7.5
Second format:
Billy Gruff             : $12.00 :7.5

main.cpp:

#include <iomanip>
#include <iostream>
int main() {
    using namespace std;
    char name[20];
    float hourly;
    float hours;
    cout << "Enter your name: ";
    cin.get(name, 20).get();
    cout << "Enter your hourly wages: ";
    cin >> hourly;
    cout << "Enter number of hours worked: ";
    cin >> hours;
    cout.setf(ios::showpoint);
    cout.setf(ios::fixed, ios::floatfield);
    cout.setf(ios::right, ios::adjustfield);
    // or cout << showpoint << fixed << right;
    cout << "First format:\n";
    cout << setw(30) << name << ": $" << setprecision(2) << setw(10) << hourly
        << ":" << setprecision(1) << setw(5) << hours << "\n";
    cout << "Second format:\n";
    cout.setf(ios::left, ios::adjustfield);
    cout << setw(30) << name << ": $" << setprecision(2) << setw(10) << hourly
        << ":" << setprecision(1) << setw(5) << hours << "\n";
    return 0;
}

8. 对于下面的程序:

//rq17-8.cpp
#include <iostream>
int main()
{
    using namespace std;
    char ch;
    int ct1 = 0;
    cin >> ch;
    while (ch != 'q')
    {
        ct1++;
        cin >> ch;
    }
    int ct2 = 0;
    cin.get(ch);
    while (ch != 'q')
    {
        ct2++;
        cin.get(ch);
    }
    cout << "ct1 = " << ct1 << "; ct2 = " << ct2 << "\n";
    return 0;
}

如果输入如下,该程序将打印什么内容?

I see a q<Enter>
I see a q<Enter>

其中,表示按回车键。

使用cin >> ch;会自动忽略空格和换行符,因此ct1的值应为5。而cin.get(ch);不忽略空格和换行符,且第一次输入的回车键,也会被cin.get(ch);捕捉到,因此ct2的值应为9。打印内容如下:

ct1 = 5; ct2 = 9

9. 下面的两条语句都读取并丢弃行尾之前的所有字符(包括行尾)。这两条语句的行为在哪方面不同?

while (cin.get() != '\n')
    continue;
cin.ignore(80, '\n');

如果输入超过80个字符,且这80个字符中没有出现'\n',则ignore()会将前80个字符都会抛弃掉,然后再开始执行后面的语句。也就是说当输入超过80个字符,且这80个字符中没有出现'\n'cin.ignore(80, '\n');读取并丢弃行尾之前的所有字符(包括行尾)的作用可能会不符合预期。而第一条语句没有该限制。【注:可以将第二个语句中80改为numeric_limits<streamsize>::max()来解除该限制】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值