目录
第2章 开始学习C++
1.编写一个C++程序,它显示您的姓名和地址。
#include<iostream>
using namespace std;
int main(void)
{
string name;
string address;
cout << "请输入您的姓名:" << endl;
cin >> name;
cout << "请输入您的地址:" << endl;
cin >> address;
cout << "您的姓名是:" <<name<< endl;
cout << "您的地址是:" <<address<<endl;
system("pause");
return 0;
}
2.编写一个C++程序,它要求用户输入一个以long为单位的距离,然后将它转换为码(一long 等于220码)。
#include <iostream>
using namespace std;
int main(void)
{
double distence;
cout << "请输入一个距离(单位:long):" << endl;
cin >> distence;
cout << "您输入的距离为 " << distence << " long," << "即 " << 220 * distence << " 码" << endl;
system("pause");
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 print1(void)
{
cout << "Three blind mice" << endl;
}
void print2(void)
{
cout << "See how they run" << endl;
}
int main(void)
{
print1();
print1();
print2();
print2();
system("pause");
return 0;
}
4.编写一个程序,让用户输入其年龄然后显示该年龄包含多少个月,如下所示:
Enter your age:29
#include <iostream>
using namespace std;
int main(void)
{
int age;
cout << "Enter your age:" << endl;
cin >> age;
cout << "your age cintains " << age * 12 << "months" << endl;
system("pause");
return 0;
}
5."编写”个程序;其中的main()调用一个用户定义的函数(以摄氏温度值为参数,并返回相应的华氏温度值)。该程序按下面的格式要求用户输入摄氏温度值,并显示结果:
please, enter a Celsius value: 20
20 degrees Celsius is 68 degrees Fahrenheit
下面是转换公式:
华氏温度=1.8X 摄氏温度+ 32.0
#include <iostream>
using namespace std;
int main(void)
{
double value;
cout << "please, enter a Celsius value :" << endl;
cin >> value;
cout << value << " degrees Celsius is " << 1.8 * value + 32.0 << " degrees Fahrenheit" << endl;
system("pause");
return 0;
}
6.编写一个程序,其main( )调用一个用户定义的函数(以光年值为参数,并返回对应天文单位的值)。该程序按下面的格式要求用户输入光年值,并显示结果:
Enter the number of light years: 4.2
4.2 light years = 265608 astronomical units.
天文单位是从地球到太阳的平均距离(约1000000公里或9300000英里),光年是光一年走的距离
(约10万亿公里或6万亿英里) (除太阳外,最近的恒星大约离地球4.2光年)。请使用double类型(参见
程序清单2.4),转换公式为:
1光年=63240天文单位
#include <iostream>
using namespace std;
double convert(double L_Y)
{
return L_Y * 63240;
}
int main(void)
{
double L_Y = 0;//光年值
cout << "Enter the number of light years :";
cin >> L_Y;
int ast = convert(L_Y);
cout << L_Y << " light years = " <<ast << " astronomical units." << endl;
system("pause");
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 print(int hours, int minutes)
{
cout <<"Time: "<< hours<<":"<<minutes << endl;
}
int main(void)
{
int hours = 0;
int minutes = 0;
cout << "Enter the number of hours :";
cin >> hours;
cout << "Enter the number of minutes :";
cin >> minutes;
print(hours, minutes);
system("pause");
return 0;
}
第3章 处理数据
1.编写一个小程序,要求用户使用一个整数指出自己的身高(单位为英寸),然后将身高转换为英尺和英寸。该程序使用下划线字符来指示输入位置。另外,使用一个const符号常量来表示转换因子。
#include <iostream>
using namespace std;
int main(void)
{
//1 英尺=12 英寸
const int convert_factor = 12;
int height_inches = 0;
cout << "Please enter your height (in inches):";
cin >> height_inches;
cout << "your height is " << height_inches / 12 << " foot and " << height_inches % 12 << " inches" << endl;
system("pause");
return 0;
}
2.编写一个小程序,要求以几英尺几英寸的方式输入其身高,并以磅为单位输入其体重。(使用3个变量来存储这些信息。)该程序报告其BMI(Body Mass Index,体重指数)。为了计算BMI,该程序以英寸的方式指出用户的身高(1英尺为12英寸),并将以英寸为单位的身高转换为以米为单位的身高(1英寸=0.0254米)。然后,将以磅为单位的体重转换为以千克为单位的体重(1千克=2.2磅)。最后,计算相应的BMI——体重(千克)除以身高(米)的平方。用符号常量表示各种转换因子。
#include <iostream>
using namespace std;
int main(void)
{
//以几英尺几英寸的方式输入其身高,并以磅为单位输入其体重。
int height_foot;
float height_inches, weight_pounds;
cout << "Enter your height (in foot):";
cin >> height_foot;
cout << "And enter your height (in inches):";
cin >> height_inches;
cout << "Enter your weight(in pound):";
cin >> weight_pounds;
cout << "So you are " << height_foot << " foot and " << height_inches
<< " inches height and " << weight_pounds << " pounds weight." << endl;
//以英寸的方式指出用户的身高(1英尺为12英寸)
const int foot_inches = 12;
float convert_to_inches;
convert_to_inches = 12 * height_foot + height_inches;
cout << "Your height is " << convert_to_inches << " inches" << endl;
//以英寸为单位的身高转换为以米为单位的身高(1英寸 = 0.0254米)
const float inches_to_meters = 0.0254;
float height_meters = convert_to_inches * inches_to_meters;
cout << "Your height is " << height_meters << " meters" << endl;
//将以磅为单位的体重转换为以千克为单位的体重(1千克 = 2.2磅)
const float kg_to_pounds = 2.2;
float weight_kg = weight_pounds / kg_to_pounds;
cout << "Your weight is " << weight_kg << " kg." << endl;
//计算相应的BMI——体重(千克)除以身高(米)的平方。
float BMI = weight_kg / pow(height_meters, 2);
cout << "Your BMI is " << 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
//1度为60分,1分等于60秒,请以符号常量的方式表示这些值。
//对于每个输入值, 应使用一个独立的变量存储它。下面是该程序运行时的情况:
//
//
// 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;
int main(void)
{
//要求用户以度、分、秒的方式输入一个纬度
int degrees, minutes, seconds;
float convert_to_degrees;
cout << "Enter a latitude in degrees, minutes, and seconds :" << endl;
cout << "First, enter the degrees :";
cin >> degrees;
cout << "Next, enter the minutes of arc :";
cin >> minutes;
cout << "Finally, enter the seconds of arc :";
cin >> seconds;
//以度为单位显示该纬度。
const int degrees_minutes = 60;
const int degrees_seconds = 360;
convert_to_degrees = degrees + (minutes / degrees_minutes) + (seconds / degrees_seconds);
cout << degrees << " degrees, " << minutes << " minutes, " << seconds << " seconds = " <<
convert_to_degrees << " degrees" << endl;
system("pause");
return 0;
}
4.编写一个程序,要求用户以整数方式输入秒数(使用long或long long变量存储),然后以天、小时、分钟和秒的方式显示这段时间。使用符号常量来表示每天有多少小时、每小时有多少分钟以及每分钟有多少秒。该程序的输出应与下面类似:
Enter the number of seconds: 31600000
31600000 seconds = 365 days,17 hours,46 minutes,40 seconds.
#include <iostream>
using namespace std;
int main(void)
{
//要求用户以整数方式输入秒数
long long before_seconds = 0;
cout << "Enter the number of seconds :";
cin >> before_seconds;
//使用符号常量来表示每天有多少小时、每小时有多少分钟以及每分钟有多少秒
const int day_hour = 24;
const int hour_minute = 60;
const int minute_second = 60;
//以天、小时、分钟和秒的方式显示这段时间
int days,hours,minutes,seconds;
days = before_seconds / (day_hour * hour_minute * minute_second);
hours = (before_seconds % (day_hour * hour_minute * minute_second)) / (hour_minute * minute_second);
minutes = (before_seconds - days * day_hour * hour_minute * minute_second - hours * hour_minute * minute_second) / minute_second;
seconds = (before_seconds - days * day_hour * hour_minute * minute_second - hours * hour_minute * minute_second) % minute_second;
cout << before_seconds << " seconds " << "= " << days << " days,"<<
hours << " hours, " << minutes << " minutes," << seconds << " seconds" << endl;
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;
int main(void)
{
//要求用户输入全球当前的人口和美国当前的人口
long long population_world,population_US;
cout << "Enter the world's population:";
cin >> population_world;
cout << "Enter the population of the US :";
cin >> population_US;
//显示美国的人口占全球人口的百分比
double percent = 100*((double)population_US / (double)population_world);
cout << "The population of the US is " << percent<< "% of the world population." << endl;
system("pause");
return 0;
}
总结:刚开始没有对population_US 和population_world进行类型转换,导致结果不正确,应该注意先进行类型转换。100*((double)population_US / (double)population_world);
6.编写一个程序,要求用户输入驱车里程(英里)和使用汽油量(加仑),然后指出汽车耗油量为一加仑的里程。如果愿意,也可以让程序要求用户以公里为单位输入距离,并以升为单位输入汽油量,然后指出欧洲风格的结果—-—即每100公里的耗油量(升)。
#include <iostream>
using namespace std;
int main(void)
{
double miles, gal;
cout << "Please enter the mileage(miles):";
cin >> miles;
cout << "Please enter the amount of gasoline used(Gal):";
cin >> gal;
cout<<"The fuel consumption of the car is "<<miles/gal<<" miles/gallon"<<endl;
system("pause");
return 0;
}
7.编写一个程序,要求用户按欧洲风格输入汽车的耗油量(每100公里消耗的汽油量(升)),然后将其转换为美国风格的耗油量―—每加仑多少英里。注意,除了使用不同的单位计量外,美国方法(距离/燃料)与欧洲方法(燃料/距离)相反。100公里等于62.14英里,1加仑等于3.875升。因此,19mpg大约合12.41/100km,127mpg大约合8.71/100km。(此处有误,应该是27而不是127)
#include <iostream>
using namespace std;
int main(void)
{
//用户按欧洲风格输入汽车的耗油量(每100公里消耗的汽油量(升))
double consumption_Eur;
int mpg;
cout << "Enter the fuel consumption of the vehicle (per 100 km):";
cin >> consumption_Eur;
//将其转换为美国风格的耗油量―每加仑多少英里
const double _100km_mile = 62.14;
const double gai_L = 3.875;
mpg = _100km_mile/(consumption_Eur / gai_L) ;
cout << "So your fuel consumption of the vehicle is " << mpg << "mpg" << endl;
system("pause");
return 0;
}
第4章 复合类型
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之间的空档。
解答:该程序应该接受的名字包含多个单词。所以应该使用cin.getline()而非cin();
#include <iostream>
using namespace std;
#define MaxSize 80
int main(void)
{
char firstName[MaxSize];
char lastName[MaxSize];
char Grade;
int Age;
cout << "What is your first name?";
cin.getline(firstName, MaxSize);
cout << "What is your last name?";
cin.getline(lastName, MaxSize);
cout << "what letter grade do you deserve?";
cin >> Grade;
cout << "what is your age?";
cin >> Age;
Grade = Grade + 1;
cout << "Name: " << lastName << ", " << firstName << endl;
cout << "Grade: " << Grade << endl;
cout << "Age: " << Age << endl;
system("pause");
return 0;
}
2.修改程序清单4.4,使用C++ string类而不是char数组。
解答:将一行输入读到string对象中的代码:getline(cin,str);(书p87)
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string name;
string desert;
cout << "Enter your name:" << endl;
getline(cin, name);
cout << "Enter your favorite desert:" << endl;
getline(cin, desert);
cout << "I have some delicious " << desert << " for you, " << name << endl;
system("pause");
return 0;
}
3.编写一个程序,它要求用户首先输入其名,然后输入其姓;然后程序使用一个逗号和空格将姓和名组合起来,并在储和显示组合结果。请使用char数组和头文件cstring中的函数。下面是该程序运行时的情形:
Enter your first name: Flip
Enter your last name: Fleming
Here's the information in a single string:Fleming,Flip
解答:strcat()函数可以用来将两个char类型变量连接起来形成新的char类型变量的函数,该函数在头文件cstring中被定义,比如
char a[20] = "abcd";
char b[20] = "cba";
strcat(a, b);
cout << a;
以上代码输出“abcdcba”,中间不会有间隔,将b连接到a的后面,形成新的char数组赋给a。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
const int ArSize = 80;
char firstname[ArSize];
char lastname[ArSize];
cout << "Enter your first name:" << endl;
cin.getline(firstname, ArSize);
cout << "Enter your last name:" << endl;
cin.getline(lastname, ArSize);
strcat(lastname, ", "); //把一个逗号和空格与lastname组合起来并赋给数组lastname
strcat(lastname, firstname);//将firstname与lastname数组结合起来赋给lastname数组
cout << "Here's the information in a single string:" << lastname << endl;
system("pause");
return 0;
}
4.编写一个程序,它要求用户首先输入其名,再输入其姓;然后程序使用一个逗号和空格将姓和名组合起来,并存储和显示组合结果。请使用string对象和头文件 string 中的函数。下面是该程序运行时的情形:
Enter your first name: Flip
Enter your last name: Fleming
Here's the information in a single string: Fleming,Flip.
解答:与上题不同,string对象的字符串拼接使用运算符即可完成。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string firstname;
string lastname;
cout << "Enter your first name:" << endl;
getline(cin, firstname);
cout << "Enter your last name:" << endl;
getline(cin, lastname);
string str = lastname + ", " + firstname;
cout << "Here's the information in a single string:" << str << endl;
system("pause");
return 0;
}
5.结构CandyBar包含3个成员。第一个成员存储了糖块的品牌;第二个成员存储糖块的重量(可以有小数)、第三个成员存储了糖块的卡路里含量(整数)。请编写一个程序,声明这个结构创建一个名为snack 的 CandyBar变量,并将其成员分别初始化为“Mocha Munch”、2.3和350。初始化应在声明snack时进行。最后,程序显示 snack变量的内容。
#include <iostream>
using namespace std;
//定义结构
struct CandyBar
{
string brand;
float weight;
int calorie;
};
int main(void)
{
CandyBar snack =
{
"Mocha Munch",
2.3,
350
};
cout << "Brand: " << snack.brand << "\tweight: " << snack.weight << "\tcalorie: " << snack.calorie << endl;
system("pause");
return 0;
}
6.结构 CandyBar包含3个成员。如编程练习5所示。请编写一个程序,创建一个包含3个元素的CandyBar数维,并将它们初始化为所选择的值,然后显示每个结构的内容。.
#include <iostream>
using namespace std;
//定义结构
struct CandyBar
{
string brand;
float weight;
int calorie;
};
int main(void)
{
CandyBar snack[3] =
{
{"Mocha Munch",2.3,350},
{"Fruit Salad",5.2,200},
{"hamburger",2.6,1000}
};
cout << "Brand: " << snack[0].brand << "\tweight: " << snack[0].weight
<< "\tcalorie: " << snack[0].calorie << endl;
cout << "Brand: " << snack[1].brand << "\tweight: " << snack[1].weight
<< "\tcalorie: " << snack[1].calorie << endl;
cout << "Brand: " << snack[2].brand << "\tweight: " << snack[2].weight
<< "\tcalorie: " << snack[2].calorie << endl;
system("pause");
return 0;
}
7.William Wingate从事披萨饼分析服务。对于每个披萨饼,他都需要记录下列信息:
1.披萨饼公司的名称,可以有多个单词组成。
2.披萨饼的直径。
3.披萨饼的重量。
请设计一个能够存储这些信息的结构,并编写一个使用这种结构变量的程序。程序将请求用户输入上述信息;然后显示这些信息。请使用_cin(或其它的方法)和 cout。
#include <iostream>
#include <string>
using namespace std;
//定义结构
struct Pizza
{
string Name;
float diameter;
float weight;
};
int main(void)
{
Pizza a;
cout << "Enter the name of commpany:";
getline(cin, a.Name);
cout << "Enter the diameter of Pizza:";
cin >> a.diameter;
cout << "Enter the weight of Pizza:";
cin>>a.weight;
cout << "Name: " << a.Name<< "\tweight: " << a.weight
<< "\tdiameter: " << a.diameter << endl;
system("pause");
return 0;
}
8.完成编程练习7,但使用new来为结构分配内存,而不是声明一个结构变量。另外,让程序在请求输入比萨饼公司名称之前输入比萨饼的直径。
解答:
- 使用new为结构分配内存;注意:用指针去接,以及访问结构成员的时候用箭头访问。
- (书p81)先输直径后输入文字,考察怎么处理遗留在输入序列中的换行符问题。如果直接cin读取直径,将会把回车键生成的换行符留在输入队列中,后面的cin.getline()看到换行符后,将会认为是一个空行,并把空行赋给Name字符串。随意需要在读入公司名称前丢弃换行符。解决方式如下:
#include <iostream>
#include <string>
using namespace std;
//定义结构
struct Pizza
{
string Name;
float diameter;
float weight;
};
int main(void)
{
Pizza* a = new Pizza;
cout << "Enter the diameter of Pizza:";
(cin >> a->diameter).get(); //or cin>>a->diameter; cin.get();
cout << "Enter the name of commpany:";
getline(cin, a->Name);
cout << "Enter the weight of Pizza:";
cin >> a->weight;
cout << "Name: " << a->Name << "\tweight: " << a->weight
<< "\tdiameter: " << a->diameter << endl;
delete a;
system("pause");
return 0;
}
9.完成编程练习6,但使用new来动态分配数组,而不是声明一个包含3个元素的CandyBar 数组。
#include <iostream>
using namespace std;
//定义结构
struct CandyBar
{
string brand;
float weight;
int calorie;
};
int main(void)
{
const int Size = 3;
CandyBar* snack = new CandyBar[Size];
snack[0] = { "Mocha Munch",2.3,350 };
snack[1] = { "Fruit Salad",5.2,200 };
snack[2] = { "hamburger",2.6,1000 };
for (int i = 0; i < Size; i++)
{
cout << "Brand:" << snack[i].brand << " weight:" << snack[i].weight
<< " calorie:" << snack[i].calorie << endl;
}
delete[] snack;
system("pause");
return 0;
}
10:编写一个程序,让用户输入三次40码跑的成绩(如果您愿意,也可让用户输入40米跑的成绩),并显示次数和平均成绩。请使用一个array对象来存储数据(如果编译器不支持array 类,请使用数组)。
解答:array<typeName,n_elem> arr;
代码写的不好,写成函数应该更好。不懂模板类数组的调用,后续有时间再改;
#include <iostream>
#include <array>
using namespace std;
int main(void)
{
const int num = 3;
array<double, num> score;
//输入成绩
cout << "Please enter the result of your first 40 yard run:";
cin >> score[0];
cout << "Please enter the result of your second 40 yard run:";
cin >> score[1];
cout << "Please enter the result of your third 40 yard run:";
cin >> score[2];
//输出成绩
for (int i = 0; i < num; i++)
{
cout << "第" << i+1 << "次成绩:" << score[i] << endl;
}
//平均成绩
double sum = 0;
for (int i = 0; i < num; i++)
{
sum += score[i];
}
cout << "your average score is:" << sum / num << endl;
system("pause");
return 0;
}
第5章 循环和关系表达式
1.编写一个要求用户输入两个整数的程序。该程序将计算并输出这两个整数之间(包括这两个整数)所有整数的和。这里假设先输入较小的整数。例如,如果用户输入的是2和9,则程序将指出2~9之间所有整数的和为44。
//编写一个要求用户输入两个整数的程序。
//该程序将计算并输出这两个整数之间(包括这两个整数)所有整数的和。
//这里假设先输入较小的整数。
//例如,如果用户输入的是2和9,则程序将指出2~9之间所有整数的和为44。
#include <iostream>
using namespace std;
int main(void)
{
int a;
int b;
int sum1 = 0;
int sum2 = 0;
int sum3 = 0;
cout << "请输入第一个整数:";
cin >> a;
cout << "请输入第二个整数:";
cin >> b;
法一:for循环
//for (; a <= b; a++)
// sum1 += a;
//cout << "您输入的两个整数之间所有整数的和为:" << sum1 << endl;
//法二:while循环
while (a <= b)
{
sum2 += a;
a++;
}
cout << "您输入的两个整数之间所有整数的和为:"<< sum2 << endl;
法三:do while循环
//do
//{
// sum3 += a;
// a++;
//} while (a <= b);
//cout << "您输入的两个整数之间所有整数的和为:" << sum3 << endl;
system("pause");
return 0;
}
2.使用 array对象(而不是数组)和 long double(而不是long long)重新编写程序清单5.4,并计算100!的值。
//使用 array对象(而不是数组)和 long double(而不是long long)重新编写程序清单5.4,
//并计算100!的值。
//array在书p120 array<typeName,n_elm>arr;
#include <iostream>
#include <array>
using namespace std;
int main(void)
{
const int arrSize = 101;
array<long double, arrSize> arr;
arr[0] = arr[1] = 1;
for (int i = 2; i < arrSize; i++)
{
arr[i] = i * arr[i - 1];
}
cout << "100! = " << arr[100] << endl;
system("pause");
return 0;
}
3.编写一个要求用户输入数字的程序。每次输入后,程序都将报告到目前为止,所有输入的累计和。当用户输入0时,程序结束。
//编写一个要求用户输入数字的程序。每次输入后,
//程序都将报告到目前为止,所有输入的累计和。
//当用户输入0时, 程序结束。
#include <iostream>
using namespace std;
int main(void)
{
double a;
double sum = 0;
cout << "请输入一个数字(输入0程序结束):" ;
while (cin >> a && a)
{
sum += a;
cout << "目前为止,所有输入的和为:" << sum << endl;
cout << "请输入一个数字(输入0程序结束):" ;
}
system("pause");
return 0;
}
4.Daphne 以10%的单利投资了100美元。也就是说,每一年的利润都是投资额的10%,即每年10美元:利息=0.10×原始存款
而Cleo以5%的复利投资了100美元。也就是说,利息是当前存款(包括获得的利息的5%,:
利息=0.05×当前存款
Cleo在第一年投资100美元的盈利是5%——得到了105美元。下一年的盈利是105美元的5%—--即5.25美元,依此类推。请编写一个程序,计算多少年后,Cleo 的投资价值才能超过Daphne的投资价值,并显示此时两个人的投资价值。
//4.Daphne 以10 % 的单利投资了100美元。
//也就是说,每一年的利润都是投资额的10 % ,即每年10美元:利息 = 0.10×原始存款
//而Cleo以5 % 的复利投资了100美元。也就是说,利息是当前存款(包括获得的利息的5%, :
// 利息 = 0.05×当前
//Cleo在第一年投资100美元的盈利是5 % ——得到了105美元。
//下一年的盈利是105美元的5 % —即5.25美元,依此类推。
//请编写一个程序,计算多少年后,Cleo 的投资价值才能超过Daphne的投资价值,
//并显示此时两个人的投资价值。
#include <iostream>
using namespace std;
int main(void)
{
double Cleo = 100;
double Daph = 100;
int year_count = 0;
do
{
Daph += 100 * 0.1;
Cleo += Cleo * 0.05;
year_count++;
} while (Cleo < Daph);
cout << year_count << "年后, Cleo投资价值超过Daph."<<endl;
cout<<"Daphene:" << Daph << "\tCleo:" << Cleo << endl;
system("pause");
return 0;
}
5.假设要销售《C++ For Fools》一书。请编写一个程序,输入全年中每个月的销售量(图书数量,而不是销售额)。程序通过循环,使用初始化为月份字符串的char*数组(或string对象数组逐月进行提示,并将输入的数据储存在一个int数组中。然后,程序计算数组中各元素的总数,并报告这一年的销售情况。
//假设要销售《C++ For Fools》一书。
//请编写一个程序,输入全年中每个月的销售量(图书数量,而不是销售额)。
//程序通过循环,使用初始化为月份字符串的char* 数组
//(或string对象数组逐月进行提示, 并将输入的数据储存在一个int数组中。
//然后,程序计算数组中各元素的总数,并报告这一年的销售情况。
#include <iostream>
using namespace std;
int main(void)
{
//初始化为月份字符串的string对象数组
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] << " :";
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>
using namespace std;
int main(void)
{
//初始化为月份字符串的string对象数组
string months[12] = {
"January", "February", "March",
"April", "May", "June","July",
"August", "September", "October",
"November","December"
};
int sales[3][12]; //二维数组存储三年每个月的销量
int sum[3] = {0};
for (int i = 0; i < 3; i++)
{
cout << "Year" << i + 1 << ":" << endl;
for (int j = 0; j < 12; j++)
{
cout << "Please enter the sales volume for " << months[j] << " :";
cin >> sales[i][j];
sum[i] += sales[i][j];
}
cout << (i + 1) << " year sales:" << sum[i] << endl;
}
cout << "The saLes of three year is " << sum[0] + sum[1] + sum[2] << endl;
system("pause");
return 0;
}
7.设计一个名为car的结构,用它存储下述有关汽车的信息:生产商(存储在字符数组或string对象中的字符串)、生产年份(整数) 编写一个程序,向用户询问有多少辆汽车。随后,程序使用new来创建一个由相应数量的car结构组成的动态数组。接下来,程序提示用户输入每辆车的生产商(可能由多个单词组成)和年份信息。请注意,这需要特别小心,因为它将交替读取数值和字符串(参见第4章)。最后,程序将显示每个结构的内容。该程序的运行情况如下:
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 efter themake: Kaiser
please enter the year made:1951
Here is your colrection :
1952 Hudson Hornet
1951 Kaiser
//设计一个名为car的结构,用它存储下述有关汽车的信息:
//生产商(存储在字符数组或string对象中的字符串)、
//生产年份(整数)
//编写一个程序,向用户询问有多少辆汽车。
//随后,程序使用new来创建一个由相应数量的car结构组成的动态数组。
//接下来,程序提示用户输入每辆车的生产商(可能由多个单词组成)和年份信息。
//请注意,这需要特别小心,因为它将交替读取数值和字符串(参见第4章)。
//最后,程序将显示每个结构的内容。
#include <iostream>
#include <string>
using namespace std;
//设计一个名为car的结构
struct Car
{
string producer; //生产商
int MadeYear; //生产年份
};
int main(void)
{
int Num; //汽车数量
//向用户询问有多少辆汽车。
cout << "How many cars do you wish to catalog?" ;
cin >> Num;
cin.get();
Car* pt = new Car[Num];
for (int i = 0; i < Num; i++)
{
cout << "car #" << i+1 << ":" << endl;
cout << "Please enter the make:";
getline(cin, pt[i].producer);
cout << "please enter the year made:";
cin >> pt[i].MadeYear;
cin.get();
}
cout << "Here is your colrection :" << endl;
for (int i = 0; i < Num; i++)
{
cout << pt[i].MadeYear << " " << pt[i].producer << endl;
}
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 7 words.
您应在程序中包含头文件cstring,并使用函数strcmp()来进行比较测试。
解:书p143
#include <iostream>
#include <cstring>
using namespace std;
#define MaxSize 30
int main(void)
{
char word[MaxSize];
int count = 0;
cout << "Enter words (to stop, type the word done):" << endl;
cin >> word;
while (strcmp(word, "done"))
{
count++;
cin >> word;
}
cout<<"You entered a total of "<<count<<" words."<<endl;
system("pause");
return 0;
}
9.编写一个满足前一个练习中描述的程序,但使用string对象而不是字符数组。请在程序中包含头文件string并使用关系运算符来进行比较测试。
#include <iostream>
#include <cstring>
using namespace std;
int main(void)
{
string word;
int count = 0;
cout << "Enter words (to stop, type the word done):" << endl;
cin >> word;
while (word != "done")
{
count++;
cin >> word;
}
cout << "You entered a total of " << count << " words." << endl;
system("pause");
return 0;
}
10.编写一个使用嵌套循环的程序,要求用户输入一个值,指出要显示多少行。然后,程序将显示相应行数的星号,其中第一行包括一个星号,第二行包括两个星号,依此类推。每一行包含的字符数等于用户指定的行数,在星号不够的情况下,在星号前面加上句点。该程序的运行情况如下:
Enter number of rows :5
....*
...**
..***
.****
*****
#include <iostream>
using namespace std;
int main(void)
{
int Num = 0;
cout << "Enter number of rows :";
cin >> Num;
for (int i = 1; i <= Num; i++)
{
for (int j = i; j < Num; j++)
{
cout << ".";
}
for (int j = 0; j < i; j++)
{
cout << "*";
}
cout << endl;
}
system("pause");
return 0;
}
第6章 分支语句和逻辑运算符
1.编写一个程序,读取键盘输入,直到遇到@符号为止,并回显输入(数字除外),同时将大写字符转换为小写,将小写字符转换为大写(别忘了cctype函数系列)。
//1.读取键盘输入,直到遇到@
//2.回显除了数字以外的输入 isdigit
//3.大写转小写 tolower() 小写转大写toupper()
#include <iostream>
#include <cctype>
using namespace std;
int main(void)
{
char ch;
cout << "Enter text for analysis, and type @ to terminate input:"<<endl;
cin.get(ch);
while ((ch != '@'))
{
if (islower(ch))
{
ch = toupper(ch);
}
else if (isupper(ch))
{
ch = tolower(ch);
}
if (isdigit(ch) == false)
{
cout << ch;
}
cin.get(ch);
}
system("pause");
return 0;
}
2.编写一个程序,最多将10个donation值读入到一个double数组中(如果您愿意,也可使用模板类array)。程序遇到非数字输入时将结束输入,并报告这些数字的平均值以及数组中有多少个数字大于平均值。
//编写一个程序,最多将10个donation值读入到一个double数组中
//(如果您愿意,也可使用模板类array)。
//程序遇到非数字输入时将结束输入,
//并报告这些数字的平均值以及数组中有多少个数字大于平均值
//6.7读取数字的循环 p187 程序清单6.13
#include <iostream>
#include <array>
using namespace std;
#define max 10
int main(void)
{
array<double, max> donation;
cout << "Enter the elements you want to exist in the array "
<<"( a non number input to terminate):"<<endl;
int i = 0;
double sum = 0;
int n_elem = 0;
int n_above = 0;
while (i < max && cin >> donation[i])
{
n_elem++;
sum += donation[i];
}
double average = sum / n_elem;
for (i = 0; i < max; i++)
{
if (donation[i] > average)
n_above++;
}
cout << "average = " << average << endl;
cout << n_above << " numbers greater than average" << endl;
system("pause");
return 0;
}
3.编写一个菜单驱动程序的雏形。该程序显示一个提供4个选项的菜单——每个选项用一个字母标记。如果用户使用有效选项之外的字母进行响应,程序将提示用户输入一个有效的字母,直到用户这样做为止。然后,该程序使用一条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(void)
{
char ch;
cout << "Please enter one of the following choices :" << endl;
cout << "c) carnivore " << "\t p) pianist" << endl;
cout<< " t) tree" << " \tg) game" << endl;
while (cin >> ch)
{
switch (ch)
{
case 'c':
cout << "tiger is a carnivore." << endl;
break;
case 'p':
cout << "Xiaoming is a pianist." << endl;
break;
case 't':
cout << "A maple is a tree." << endl;
break;
case 'g':
cout << "Golf is a game." << endl;
break;
default:
cout << "Please enter a c, p, t, or g: ";
}
}
system("pause");
return 0;
}
4.加入 Benevolent Order of Programmer后,在 BOP大会上,人们便可以通过加入者的真实姓名、头衔或秘密BOP姓名来了解他(她)。请编写一个程序,可以使用真实姓名、头衔、秘密姓名或成员偏好来列出成员。编写该程序时,请使用下面的结构:
// Benevolent Order of Programmers name structure
struct bop {
char fullname [strsize] ;// real name
char title[strsize] ; // job title
char bopname [strsize] ; //secret BOP name
int preference; //0 = fullname,1 = title, 2 = bopname);
该程序创建一个由上述结构组成的小型数组,并将其初始化为适当的值。另外,该程序使用一个循环,让用户在下面的选项中进行选择:
a. display by name b. display 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 bop
name 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
LOOFY
Next choice: q
Bye!
#include <iostream>
using namespace std;
const int strsize = 20;
const int n_elm = 5;
// Benevolent Order of Programmers name structure
struct bop
{
char fullname[strsize];// real name
char title[strsize]; // job title
char bopname[strsize]; //secret BOP name
int preference; //0 = fullname,1 = title, 2 = bopname);
};
bop exampel[n_elm] =
{
{ "Wimp Mache", "BOSS", "AS", 0 },
{ "Raki Rhodes", "Junior Programmer", "MA", 1 },
{ "Celia Laiter", "Manager", "MIPS", 2 },
{ "Hoppy Hipman", "Analyst Trainee", "CL", 1 },
{ "Pat Hand", "Student", "LOOPY", 2 }
};
void display_name(void)
{
for (int j = 0; j < n_elm; j++)
cout << exampel[j].fullname<< endl;
}
void display_title(void)
{
for (int j = 0; j < n_elm; j++)
cout << exampel[j].title << endl;
}
void display_bopname(void)
{
for (int j = 0; j < n_elm; j++)
cout << exampel[j].bopname<< endl;
}
void display_perference(void)
{
for (int j = 0; j < n_elm; j++)
{
if (exampel[j].preference == 0)
cout << exampel[j].fullname << endl;
else if (exampel[j].preference == 1)
cout << exampel[j].title << endl;
else
cout << exampel[j].bopname << endl;
}
}
int main(void)
{
char ch;
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 chlice:";
while (cin >> ch && ch !='q')
{
switch (ch)
{
case 'a':
display_name();
break;
case 'b':
display_title();
break;
case 'c':
display_bopname();
break;
case 'd':
display_perference();
break;
}
cout << "Next choice:";
}
cout << "Bye!" << endl;
system("pause");
return 0;
}
5.在 Ncutronia王国,货币单位是tvarp,收入所得税的计算方式如下:
5000 tvarps:不收税
5001~15000 tvarps:10%
15001~35000 tvarps:15%
35000 tvarps 以上:20%
例如,收入为38000 tvarps 时,所得税为5000 × 0.00 + 10000 × 0.10 +20000 × 0.15 + 3000 × 0.20,即4600 tvarps。请编写一个程序,使用循环来要求用户输入收入,并报告所得税。当用户输入负数或非数字时,循环将结束。
#include <iostream>
using namespace std;
int main(void)
{
int income;
cout << "Enter your income:";
while (cin >> income && income >= 0)
{
if (income <= 5000)
{
cout << "tax = 0" << endl;
}
else if (income > 5000 && income <= 15000)
{
cout << "tax = " << (double)(income - 5000) * 0.1<<"tvarps"<< endl;
}
else if (income > 15000 && income < 35000)
{
cout << "tax = " << 0 + (15000 - 5000) * 0.1 + (double)(income - 15000) * 0.15 << "tvarps" << endl;
}
else
{
cout << "tax = " << 0 + (15000 - 5000) * 0.1 + (35000 - 15000) * 0.15+(double)(income - 35000)*0.2 << "tvarps" << endl;
}
cout << "Enter your income:";
}
system("pause");
return 0;
}
6.编写一个程序,记录捐助给“维护合法权利团体”的资金。该程序要求用户输入捐献者数目,然后要求用户输入每一个捐献者的姓名和款项。这些信息被储存在一个动态分配的结构数组中。每个结构有两个成员:用来储存姓名的字符数组(或string对象)和用来存储款项的double成员。读取所有的数据后,程序将显示所有捐款超过10000的捐款者的姓名及其捐款数额。该列表前应包含一个标题,指出下面的捐款者是重要捐款人(Grand Patrons)。然后,程序将列出其他的捐款者,该列表要以Patrons开头。如果某种类别没有捐款者,则程序将打印单词“none”。该程序只显示这两种类别,而不进行排序。
#include <iostream>
#include <string>
using namespace std;
//用来储存姓名的字符数组(或string对象)和用来存储款项的double成员
struct information
{
string name;
double money;
};
//显示所有捐款超过10000的捐款者的姓名及其捐款数额。
void show_Grand(information* info, int num)
{
cout << "Grand Patrons:" << endl;
int n_Grand = 0;
for (int j = 0; j < num; j++)
{
if (info[j].money> 10000)
{
cout << info[j].name << "\t" << info[j].money << endl;
n_Grand++;
}
}
if (n_Grand == 0)
{
cout << "none" << endl;
}
}
//程序将列出其他的捐款者,该列表要以Patrons开头。
void show_other(information* info, int num)
{
cout << "Patrons:" << endl;
int n_other = 0;
for (int j = 0; j < num; j++)
{
if (info[j].money <= 10000)
{
cout << info[j].name << "\t" << info[j].money << endl;
n_other++;
}
}
if (n_other == 0)
{
cout << "none" << endl;
}
}
int main(void)
{
int num; //捐献者数目
cout << "Pleser enter the number of donors: ";
cin >> num;
cin.get(); //清除缓存 后面还要输入字母
information* info = new information[num]; //这些信息被储存在一个动态分配的结构数组中。
//要求用户输入每一个捐献者的姓名和款项。
for (int i = 0; i < num; i++)
{
cout << "Please enter the " << i + 1 << "-th name: ";
getline(cin, info[i].name);
cout << "Please enter the " << i + 1 << "-th money:";
cin >> info[i].money;
cin.get();
}
show_Grand(info, num);
show_other(info, num);
system("pause");
return 0;
}
7.编写一个程序,它每次读取一个单词,直到用户只输入q。然后,该程序指出有多少个单词以元音打头,有多少个单词以辅音打头,还有多少个单词不属于这两类。为此,方法之一是,使用isalpha( )来区分以字母和其他字符打头的单词,然后对于通过了isalpha()测试的单词,使用if或switch语句来确定哪些以元音打头。该程序的运行情况如下:
Enter words (q to quit) :
The 12 awesome oxen ambled
quietly across 15 meters of lawn. q
5 words beginning with vowels
4 words beginning with consonants
2 others
//单词 == 字符数组
#include <iostream>
#include <cctype>
using namespace std;
const int ArrSize = 30;
int main(void)
{
char ch;
char str[ArrSize];
int count_other = 0;
int count_vowel = 0;
int count_consonant = 0;
cout << "Enter words(q to quit) :" << endl;
while (cin >> str)
{
if (strcmp(str, "q") == 0) //单独一个字母q就退出
break;
ch = str[0];
if (isalpha(ch))
{
switch (ch)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
count_vowel++;
break;
default:
count_consonant++;
}
}
else
count_other++;
}
cout << count_vowel << " words beginning with vowels\n";
cout << count_consonant << " words beginning with consonants\n";
cout << count_other << " others\n";
system("pause");
return 0;
}
8.编写一个程序,它打开一个文件文件,逐个字符地读取该文件,直到到达文件末尾,然后指出该文件中包含多少个字符。
解:参考书p195
//8.编写一个程序,它打开一个文件文件,逐个字符地读取该文件,
//直到到达文件末尾,然后指出该文件中包含多少个字符。
#include<iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
const int SIZE = 60;
int main(void)
{
char filename[SIZE];
ifstream inFile;
cout << "Enter name of data file:";
cin.getline(filename, SIZE);
inFile.open(filename);
if (!inFile.is_open())
{
cout << "Could not open the file " << filename << endl;
cout << "Program terminating." << endl;
exit(EXIT_FAILURE);
}
int count = 0;
char ch;
inFile >> ch;
while (inFile.good())
{
count++;
inFile >> ch;
}
if (inFile.eof())
cout << "End of file reached." << endl;
else if (inFile.fail())
{
cout << "Input terminated by data mismatch." << endl;
}
else
cout << "Input terminated for unknown reason." << endl;
cout << "A total of " << count << " characters were read." << endl;
inFile.close();
system("pause");
return 0;
}
9.完成编程练习6,但从文件中读取所需的信息。该文件的第一项应为捐款人数,余下的内容应为成对的行。在每一对中,第一行为捐款人姓名,第二行为捐款数额。即该文件类似于下面;
4
sam stone
2000
Freida Flass
100500
Tammy Tubbs
5000
Rich Raptor
55000
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
const int size = 20;
//用来储存姓名的字符数组(或string对象)和用来存储款项的double成员
struct information
{
string name;
double money;
};
//显示所有捐款超过10000的捐款者的姓名及其捐款数额。
void show_grand(information* info, int num)
{
cout << "grand patrons:" << endl;
int n_grand = 0;
for (int j = 0; j < num; j++)
{
if (info[j].money> 10000)
{
cout << info[j].name << "\t" << info[j].money << endl;
n_grand++;
}
}
if (n_grand == 0)
{
cout << "none" << endl;
}
}
//程序将列出其他的捐款者,该列表要以patrons开头。
void show_other(information* info, int num)
{
cout << "patrons:" << endl;
int n_other = 0;
for (int j = 0; j < num; j++)
{
if (info[j].money <= 10000)
{
cout << info[j].name << "\t" << info[j].money << endl;
n_other++;
}
}
if (n_other == 0)
{
cout << "none" << endl;
}
}
int main(void)
{
char filename[size];
ifstream infile;
cout << "enter name of data file:";
cin.getline(filename, size);
infile.open(filename);
if (!infile.is_open())
{
cout << "could not open the file " << filename << endl;
cout << "program terminating." << endl;
exit(exit_failure);
}
int num;
int i;
infile>>num;
infile.get(); //清除缓存 后面还要输入字母
information* info = new information[num]; //这些信息被储存在一个动态分配的结构数组中。
for (i = 0; i < num; i++)
{
getline(infile, info[i].name);
infile >> info[i].money;
infile.get();
}
show_grand(info, num);
show_other(info, num);
system("pause");
return 0;
}
第7章 函数C++编程模块
1.编写一个程序,不断要求用户输入两个数,直到其中的一个为0。对于每两个数,程序将使用一个函数来计算它们的调和平均数,并将结果返回给main(),而后者将报告结果。调和平均数指的是倒数平均值的倒数,计算公式如下:
调和平均数=2.0 * x * y / (x+ y)
#include <iostream>
using namespace std;
double Harmonic_mean(double x, double y)
{
return 2.0 * x * y / (x + y);
}
int main(void)
{
double x;
double y;
cout << "Please input two numbers x and y:(x>0&&y>0):" << endl;
while (cin >> x >> y && ((x > 0) && (y > 0)))
{
double result = Harmonic_mean(x, y);
cout << x << " and " << y << ":" << result << endl;
cout << "Input two numbers x and y:(x>0&&y>0):" << endl;
}
cout << "Done!" << endl;
system("pause");
return 0;
}
2.编写一个程序,要求用户输入最多10个高尔夫成绩,并将其存储在一个数组中。程序允许用户提早结束输入,并在一行上显示所有成绩,然后报告平均成绩。请使用3个数组处理函数来分别进行输入、显示和计算平均成绩。
#include <iostream>
using namespace std;
const int ArrSize = 10;
int True_Size = 0;
//输入
void Input(double *Golf_scores)
{
cout << "If you want to end the input, press the letter!" << endl;
for (int i = 0; i < ArrSize; i++)
{
cout << "Input the " << i + 1 << "_th Score:" << endl;
if (cin >> Golf_scores[i])
{
}
else
{
True_Size = i;
break;
}
True_Size = i;
}
cout << "Enter end!" << endl;
}
//显示
void Display(const double* Golf_scores)
{
cout << "All Scores:";
for (int i = 0; i < True_Size; i++)
{
cout << Golf_scores[i] << " ";
}
cout << endl;
}
//计算平均成绩
void Caculate(double* Golf_scores)
{
double sum = 0;
cout << "Average score:";
for (int i = 0; i < True_Size; i++)
{
sum += Golf_scores[i];
}
cout << (double)sum/True_Size << endl;
}
int main(void)
{
double Golf_scores[ArrSize];
Input(Golf_scores);
Display(Golf_scores);
Caculate(Golf_scores);
system("pause");
return 0;
}
3.下面是一个结构声明:
struct box
{
char maker [40];
float height ;
float width;
float length;
float volume ;
};
a.编写一个函数,按值传递box结构,并显示每个成员的值。
b.编写一个函数,传递box结构的地址,并将volume成员设置为其他三维长度的乘积。
c.编写一个使用这两个函数的简单程序。
#include <iostream>
using namespace std;
struct box
{
char maker[40];
float height;
float width;
float length;
float volume;
};
//b.编写一个函数,传递box结构的地址,并将volume成员设置为其他三维长度的乘积。
void Caculate_volume(box* example)
{
example->volume = example->length * example->width * example->height;
}
//a.编写一个函数,按值传递box结构,并显示每个成员的值。
void Display(box example)
{
cout << "maker: " << example.maker << endl;
cout << "height: " << example.height << endl;
cout << "width: " << example.width << endl;
cout << "length: " << example.length << endl;
cout << "volume: " << example.volume << endl;
}
int main(void)
{
box example;
cout << "Enter the name of maker:";
cin.getline(example.maker, 40);
cout << "Enter the height:";
cin >> example.height;
cout << "Enter the width:";
cin >> example.width;
cout << "Enter the length:";
cin >> example.length;
Caculate_volume(&example);
Display(example);
system("pause");
return 0;
}
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)
{
long double result = 1.0;
long double n;
unsigned p;
for (n = numbers, p = picks; p > 0; n--, p--)
{
result = result * n / p;
}
return result;
}
int main(void)
{
double field_number = 47, field_pick = 5;
double special_number = 27, special_pick = 1;
cout << "You have one chance in "<<
probability(field_number,field_pick)*probability(special_number,special_pick)<<
" of winning." << endl;
system("pause");
return 0;
}
5.定义一个递归函数,接受一个整数参数,并返回该参数的阶乘。前面讲过,3的阶乘写作3!,等于3*2!,依此类推;而0!被定义为1。通用的计算公式是,如果n大于零,则n!=n*(n-l)!。在程序中对该函数进行测试,程序使用循环让用户输入不同的值,程序将报告这些值的阶乘。
#include <iostream>
using namespace std;
long Factorial(int n)
{
if(n == 0)
return 1;
else
return Factorial(n - 1) * n;
}
int main(void)
{
int n;
cout << "Enter a number n(n>0)(q to quit):";
while (cin>>n)
{
cout << n << "! = " << Factorial(n) << endl;
cout << "Next number(q to quit): ";
}
system("pause");
return 0;
}
6.编写一个程序,它使用下列函数:
Fill_array()将一个double数组的名称和长度作为参数。它提示用户输入double值,并将这些值存储到数组中。当数组被填满或用户输入了非数字时,输入将停止,并返回实际输入了多少个数字。
Show_array()将一个double数组的名称和长度作为参数,并显示该数组的内容。
Reverse-array()将一个double数组的名称和长度作为参数,并将存储在数组中的值的顺序反转。程序将使用这些函数来填充数组,然后显示数组;反转数组,然后显示数组;反转数组中除第一个和最后一个元素之外的所有元素,然后显示数组。
#include <iostream>
using namespace std;
const unsigned int ArrSize = 20;
//填充数组
int Fill_array(double Array[],unsigned int ArrSize)
{
int i = 0;
cout << "If you want to end the input, press the letter!" << endl;
while (cin >> Array[i] && i < ArrSize)
{
i++;
}
return i;
}
//显示数组
void Show_array(const double Array[], int Length)
{
for (int i = 0; i < Length; i++)
cout << Array[i] << " ";
cout << endl;
}
//反转数组
void Reverse_array(double Array[], int Length)
{
double temp;
for (int i = 1,j = Length - 2; i < j; i++, j--)
{
temp = Array[i];
Array[i] = Array[j];
Array[j] = temp;
}
}
int main(void)
{
double Array[ArrSize];
//填充数组,然后显示数组
int Length = Fill_array(Array, ArrSize);
Show_array(Array, Length);
//反转数组中除第一个和最后一个元素之外的所有元素,然后显示数组。
cout << "---------------------------------------------------" << endl;
Reverse_array(Array, Length);
Show_array(Array, Length);
system("pause");
return 0;
}
7.修改程序清单7.7中的3个数组处理函数,使之使用两个指针参数来表示区间。fill_array()函数不返回实际读取了多少个数字,而是返回一个指针,该指针指向最后被填充的位置;其他的函数可以将该指针作为第二个参数,以标识数据结尾。
#include <iostream>
using namespace std;
const int Max = 5;
double* fill_array(double* Beign, double* End);
void show_array(const double* Beign, const double* End);
void revalue(double r, double* Beign, double* End);
int main(void)
{
double propreties[Max];
double * End = fill_array(propreties,propreties+Max);
show_array(propreties,End);
if (End != propreties)
{
cout << "Enter revaluation factor:";
double factor;
while (!(cin >> factor))
{
cin.clear();
while (cin.get() != '\n')
{
continue;
}
cout << "Bad input;Please enter a number:";
}
revalue(factor, propreties, End);
show_array(propreties, End);
}
cout << "Done!" << endl;
system("pause");
return 0;
}
double * fill_array(double* Beign, double *End)
{
double *temp = Beign;
int i = 0;
for (; temp != End; temp++)
{
cout << "Enter value #" << (i + 1) << ":";
cin >> *temp;
if (!cin)
{
cin.clear();
while (cin.get() != '\n')
{
continue;
}
cout << "Bad input;Please enter a number:";
break;
}
else if (*temp < 0)
{
break;
}
i++;
}
return temp;
}
void show_array(const double* Beign, const double* End)
{
int i = 0;
for (; Beign != End; Beign++)
{
cout << "Property #" << (i + 1) << ": $";
cout << *Beign << endl;
i++;
}
}
void revalue(double r, double* Beign, double* End)
{
for (double* temp = Beign; temp != End; temp++)
*temp *= r;
}
8.在不使用array类的情况下完成程序清单7.15所做的工作。编写两个这样的版本:
a.使用const char *数组存储表示季度名称的字符串,并使用double数组存储开支。
b.使用const char*数组存储表示季度名称的字符串,并使用一个结构,该结构只有一个成员———个用于存储开支的double数组。这种设计与使用array类的基本设计类似。
#include <iostream>
#include <array>
#include <string>
using namespace std;
const int Seasons = 4;
const char* Snames[4] = { "Sppring","Summer","Fall","Winter" };
void fill(double *expenses);
void show(const double expenses[], int Length);
int main(void)
{
double expenses[Seasons];
fill(expenses);
show(expenses,Seasons);
system("pause");
return 0;
}
void fill(double* expenses)
{
for (int i = 0; i < Seasons; i++)
{
cout << "Enter " << Snames[i] << " expenses:";
cin >> expenses[i];
}
}
void show(const double expenses[], int Length)
{
double total = 0.0;
cout << "\nEXPENSES\n";
for (int i = 0; i < Seasons; i++)
{
cout << Snames[i] << ": $" << expenses[i] << endl;
total += expenses[i];
}
cout << "Total Expenses: $" << total << endl;
}
#include <iostream>
#include <array>
#include <string>
using namespace std;
const int Seasons = 4;
struct Expenses
{
double expenses[Seasons];
};
const char* Snames[4] = { "Sppring","Summer","Fall","Winter" };
void fill(struct Expenses * e);
void show(const Expenses *ptr);
int main(void)
{
Expenses e;
fill(&e);
show(&e);
system("pause");
return 0;
}
void fill(struct Expenses* ptr)
{
for (int i = 0; i < Seasons; i++)
{
cout << "Enter " << Snames[i] << " expenses:";
cin >> ptr->expenses[i];
}
}
void show(const Expenses *ptr)
{
double total = 0.0;
cout << "\nEXPENSES\n";
for (int i = 0; i < Seasons; i++)
{
cout << Snames[i] << ": $" << ptr->expenses[i] << endl;
total += ptr->expenses[i];
}
cout << "Total Expenses: $" << total << endl;
}
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)
{
cout << "Please input the students information:" << endl;
int i;
for (i = 0; i < n; i++)
{
cout << "Student #" << i + 1 << ": " << endl;
cout << "Fullname: ";
cin.getline(pa[i].fullname, SLEN);
if (pa[i].fullname[0] == '\0')
break;
cout << "Hobby: ";
if (pa[i].hobby[0] == '\0')
break;
cin.getline(pa[i].hobby, SLEN);
cout << "Ooplevel: ";
if (!(cin >> pa[i].ooplevel))
break;
cin.get();
}
cout <<"Enter End!"<< endl;
return i; //返回实际获取到的元素的数量
}
void display1(student st)
{
cout << "fullname:" << st.fullname << " hobby:" << st.hobby <<
" opplevel:" << st.ooplevel << endl;
}
// display2 () takes the address of student structure as an
//argument and displays the structure's contents
void display2(const student* ps)
{
cout << "fullname:" << ps->fullname << " hobby:" << ps->hobby <<
" opplevel:" << ps->ooplevel << endl;
}
//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)
{
for (int i = 0; i < n; i++)
{
cout << "Student #" << i + 1 << endl;
cout << "fullname:" << pa[i].fullname << " hobby:" << pa[i].hobby <<
" opplevel:" << pa[i].ooplevel << endl;
}
}
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;
}
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;
double add(double x, double y);
double subtract(double x, double y);
double multiply(double x, double y);
double caculate(double x, double y, double (*func)(double, double));
int main(void)
{
double x;
double y;
double (*pf[3])(double, double) = {add,subtract,multiply};//指针数组
cout << "Enter two numbers(q to quit):" ;
while (cin >> x >> y)
{
for (int i = 0; i < 3; i++)
{
cout << "The result #" << i + 1 << ":" << caculate(x, y,pf[i]) << endl;
}
cout << "Enter two numbers(q to quit):" << endl;
}
system("pause");
return 0;
}
double add(double x, double y)
{
return x + y;
}
double subtract(double x, double y)
{
return x - y;
}
double multiply(double x, double y)
{
return x * y;
}
double caculate(double x, double y, double (*func)(double, double))
{
return (*func)(x, y);
}
第8章 函数探幽
1.编写通常接受一个参数(字符串的地址),并打印该字符串的函数。然而,如果提供了第二个参数(int类型),且该参数不为0,则该函数打印字符串的次数将为该函数被调用的次数(注意,字符串的打印次数不等于第二个参数的值而等于函数被调用的次数)。是的,这是一个非常可笑的函数,但它让您能够使用本章介绍的一些技术。在一个简单的程序中使用该函数,以演示该函数是如何工作的。
解:使用默认参数。
#include <iostream>
const int Len = 20;
void print(char* str, int a = 0);
using namespace std;
int main(void)
{
char str[Len] = "abcdefg" ;
print(str);
cout << endl;
print(str);
cout << endl;
print(str,10);
cout << endl;
print(str,30);
cout << endl;
system("pause");
return 0;
}
void print(char* str, int n)
{
static int count = 0;
count++;
while (n >= 0)
{
if (n == 0)
{
cout << str << endl;
return;
}
else
{
for (int i = 0; i < count; i++)
{
cout << str << endl;
}
return;
}
}
}
2. CandyBar结构包含3个成员。第一个成员存储candy bar的品牌名称;第二个成员存储candy bar的重量(可能有小数);第三个成员存储candy bar的热量(整数)。 请编写一个程序,它使用一个这样的函数,即将CandyBar的引用、char指针、double和int作为参数,并用最后3个值设置相应的结构成员,最后3个参数的默认值分别为“Millennijum Munch "、2.85和350。另外,该程序还包含一个以 CandyBar 的引用为参数,并显示结构内容的函数。请尽可能使用const。
答:笔记://x.brand = a; //如果brand是string,这里可以直接赋值
strcpy_s(x.brand,a); //如果brand是char[],字符串不能直接赋值,需要进行strcpy拷贝
这里出错好久才明白。
#include <iostream>
#include <string>
using namespace std;
const int Len = 30;
struct CandyBar
{
char brand[Len];
double weight;
int calories;
};
void fill_candybar(CandyBar& x, const char* a= "Millennijum Munch ", const double b = 2.85, const int c = 350);
void Display(const CandyBar& s);
int main(void)
{
CandyBar candy1, candy2,candy3;
fill_candybar(candy1);
cout << "candy1: "<< endl;
Display(candy1);
const char* m = new char[Len];
m= "Dove";
fill_candybar(candy2, m, 3.30, 300); //baby使用自定义参
cout << "candy2: " << endl;
Display(candy2);
const char* s = new char[Len];
s = "Margaret";
fill_candybar(candy3, s, 4.28, 900); //baby使用自定义参
cout << "candy3: " << endl;
Display(candy3);
system("pause");
return 0;
}
void fill_candybar(CandyBar &x,const char* a,const double b,const int c)
{
//x.brand = a; //如果brand是string,这里可以直接赋值
strcpy_s(x.brand,a); //如果brand是char[],字符串不能直接赋值,需要进行strcpy拷贝
x.weight = b;
x.calories = c;
}
void Display(const CandyBar& s)
{
cout << "Brand:" << s.brand << endl;
cout << "Weight:" << s.weight << endl;
cout << "Calories:" << s.calories << endl;
}
3. 编写一个函数,它接受一个指向string对象的引用作为参数“并将该string对象的内容转换为大写,为此可使用表6.4描述的函数 toupper()。然后编写一个程序,它通过使用一个循环让您能够用不同的输入来测试这个函数,该程序的运行情况如下:
Enter a string (q to quit) : go away
GO AWAY
Next string (q to quit) : good grief!
GOOD GRIEF!
Next string (q to quit): q
Bye.
笔记:a.size()可以得到string类字符串a的长度。sizeof()只能得到字符数组长度。
#include <iostream>
#include <cctype>
#include <string>
using namespace std;
string upper(string& a);
int main(void)
{
string a;
cout << "Enter a string (q to quit) :";
getline(cin, a);
while (a != "q")
{
cout << upper(a) << endl;
cout << "Next string (q to quit) :";
getline(cin, a);
}
cout << "Bye." << endl;
system("pause");
return 0;
}
string upper(string &a)
{
for (int i = 0; i < a.size(); i++)
{
a[i] = toupper(a[i]);
}
return a;
}
4.下面是一个程序框架
#include<iostream>
using namespace std;
#include<cstring> //for strlen(),strcpy()
struct stringy {
char * str; //points to a string
int ct; //length of string (not couting '\0')
};
// prototypes for set(), show(), and show() go here
int main()
{
stringy beany;
char testing[]="Reality isn't what it used to be.";
set(beany,testing); //first argument is a reference,
//allocates space to hold copy of testing
//sets str member of beany to point to the
//new block, copies testing to new block,
//and sets ct member of beany
show(beany); //prints member string once
show(beany, 2); //prints member string twice
testing[0]= 'D';
testing[1] = 'u';
show(testing); //prints testing string once
show(testing, 3); //prints testing string thrice
show("Done!");
return 0;
}
请提供其中描述的函数和原型,从而完成该程序。注意,应有两个 show ()函数,每个都使用默认参数。请尽可能的使用 const 参数。 set() 使用 new 分配足够的空间来存储定指的字符串。这里使用的技术与设计和实现类使用的相似。(可能还必须修改头文件的名称,删除 using 编译指令,这取决于所用的编译器。)
笔记://三个参数时:strcpy_s( strDestination,size_t numberOfElements,const char* strSource);
//两个参数时:strcpy (char(&strDestination)[size],const char* strSource);
//使用3个参数的版本时,一般的做法就是将长度定为被复制的字符串长度 + 1
形参是指针,直接打印名称就能打印出字符串。
void show(const stringy& a ){
cout << a.str << endl;}
}
void show(const char* a, int b){
cout << a<<endl;}
#include<iostream>
using namespace std;
#include<string> //for strlen(),strcpy()
struct stringy
{
char* str; //points to a string
int ct; //length of string (not couting '\0')
};
// prototypes for set(), show(), and show() go here
void set(stringy &beany, const char * testing);
void show(const stringy &a, int b = 1);
void show(const char* a, int b = 1);
int main()
{
stringy beany;
char testing[] = "Reality isn't what it used to be.";
set(beany, testing); //first argument is a reference,allocates space to hold copy of testing
//sets str member of beany to point to the new block,
//copies testing to new block,and sets ct member of beany
show(beany); //prints member string once
show(beany, 2); //prints member string twice
testing[0] = 'D';
testing[1] = 'u';
show(testing); //prints testing string once
show(testing, 3); //prints testing string thrice
show("Done!");
return 0;
}
void set(stringy& beany, const char* testing)
{
beany.ct = strlen(testing) + 1;
beany.str = new char[beany.ct];
strcpy_s(beany.str,beany.ct,testing); //这里编译器要求strcpy_s版本
//三个参数时:strcpy_s( strDestination,size_t numberOfElements,const char* strSource);
//两个参数时:strcpy (char(&strDestination)[size],const char* strSource);
//使用3个参数的版本时,一般的做法就是将长度定为被复制的字符串长度 + 1
}
void show(const stringy& a, int b )
{
for (int i = 0; i < b; i++)
{
cout << a.str << endl;
}
}
void show(const char* a, int b)
{
for (int i = 0; i < b; i++)
{
cout << a<<endl;
}
}
5. 编写模板函数 max5 (),它将一个包含 5 个 T 类型元素的数组作为参数,并返回数组中最大的元素(由于长度固定,因此可以在循环中使用硬编码,而不必通过参数来传递)。在一个程序中使用该函数,将 T 替换为一个包含 5 个 int 值的数组和一个包含 5 个 double 值的数组,以测试该函数。
#include <iostream>
using namespace std;
template <typename T>
T max5(T arr[]);
int main(void)
{
int a[5] = { 1,6,3,2,5 };
double b[5] = { 1.20,2.30,5.2,1.4,2.7 };
int c = max5(a);
double d = max5(b);
cout << "int数组中最大值为:" << c << endl;
cout << "double数组中最大值为:" << d << endl;
system("pause");
return 0;
}
template <typename T>
T max5(T arr[])
{
T temp = arr[0];
for (int i = 1; i < 5; i++)
{
if (arr[i] > temp)
temp = arr[i];
}
return temp;
}
6. 编写模板函数 maxn (),它将由一个 T 类型元素组成的数组和一个表示数组元素数目的整数作为参数,并返回数组中最大的元素。在程序对它进行测试,该程序使用一个包含 6 个 int 元素的数组和一个包含 4 个 double 元素的数组来调用该函数。程序还包含一个具体化,它将 char 指针数组和数组中的指针数量作为参数,并返回最长的字符串的地址。如果有多个这样的字符串,则返回其中第一个字符串的地址。使用由 5 个字符串指针组成的数组来测试该具体化。
#include <iostream>
#include <string>
using namespace std;
template <typename T>
T maxn(T* arr, const int n);
//具体化
template<> const char* maxn(const char* arr[], const int n);
int main(void)
{
int a[6] = { 4,6,3,5,8,2 };
double b[4] = { 2.3,5.4,1.3,6.2 };
int c = maxn(a,sizeof(a)/sizeof(int));
double d = maxn(b, sizeof(b) / sizeof(double));
cout << "int数组中最大值为:" << c << endl;
cout << "double数组中最大值为:" << d << endl;
const char* arr[7] = { "absaihc","chuahuiap","asjch cnck c","csamkc casj","fwef","a","bc" };
const char* f = maxn(arr, 7) ;
cout << f << endl;
system("pause");
return 0;
}
template <typename T>
T maxn(T* arr, const int n)
{
T temp = arr[0];
for (int i = 1; i < n; i++)
{
if (arr[i] > temp)
{
temp = arr[i];
}
}
return temp;
}
template<> const char* maxn(const char* arr[], const int n)
{
const char* temp = arr[0];
for (int i = 1; i < n; i++)
{
if (strlen(arr[i]) > strlen(temp))
temp = arr[i];
}
;
return temp;
}
7. 修改程序清单 8.14 ,使其使用两个名为 SumArray ()的模板函数来返回数组元素的总和,而不是显示数组的内容。程序应显示thing的总和以及所有 debt 的总和。
#include <iostream>
using namespace std;
template<typename T>
T SumArray(T arr[], int n); //template A
template<typename T> //template B
T SumArray(T* arr[], int n);
struct debts
{
char name[50];
double amouunt;
};
int main(void)
{
int things[6] = { 13,31,103,301,310,130 };
struct debts me_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] = &me_E->amouunt;
cout << "Listing Mr.E's counts:" << endl;
cout << SumArray(things, 6) << endl;
cout << "Listing Mr.E's debts:" << endl;
cout << SumArray(pd, 3) << endl;
system("pause");
return 0;
}
template<typename T>
T SumArray(T arr[], int n)
{
T sum = 0;
cout << "template A" << endl;
for (int i = 0; i < n; i++)
sum += arr[i];
return sum;
}
template<typename T> //template B
T SumArray(T* arr[], int n)
{
T sum = 0;
cout << "template B" << endl;
for (int i = 0; i < n; i++)
sum += *arr[i];
return sum;
}
第9章 内存模型和名称空间
1. 下面是一个头文件:
(…………)
注意到setgolf()被重载,可以这样使用其第一个版本:
golf ann;
setgolf(ann, "Ann Birdfree", 24);
上述函数调用提供了存储在ann结构中的信息。可以这样使用其第二个版本:
golf andy;
setgolf(andy);
上述函数将提示用户输入姓名和等级,并将它们存储在andy结构中。这个函数可以(但是不一定必须)在内部使用第一个版本。
根据这个头文件,创建一个多文件程序。其中的一个文件名为golf.cpp,它提供了与头文件中的原型匹配的函数定义;另一个文件应包含main(),并演示原型化函数的所有特性。例如,包含一个让用户输入的循环,并使用输入的数据来填充一个由golf结构组成的数组,数组被填满或用户将高尔夫选手的姓名设置为空字符串时,循环将结束。main()函数只使用头文件中原型化的函数来访问golf结构。
头文件 golf.h
#include <iostream>
using namespace std;
const int Len = 40;
struct golf
{
char fullname[Len];
int handicap;
};
void setgolf(golf& g, const char* name, int hc);
int setgolf(golf& g);
void handicap(golf& g, int hc);
void showgolf(const golf& g);
golf.cpp(函数定义)
#include "golf.h"
#include <iostream>
#include <cstring>
using namespace std;
void setgolf(golf &g, const char* name, int hc)
{
strcpy_s(g.fullname, name);
g.handicap = hc;
}
int setgolf(golf& g)
{
cout << "Please enter the full name of player:";
cin.getline(g.fullname, Len);
if (strcmp(g.fullname, "") == 0)
{
return 0;
}
cout << "Please enter the handicap of player:";
cin >> g.handicap;
cin.get();
return 1;
}
void handicap(golf& g, int hc)
{
g.handicap = hc;
}
void showgolf(const golf& g)
{
cout << "Information:" << endl;
cout << "Name: " << g.fullname << endl;
cout << "handicap: " << g.handicap << endl;
}
main.cpp主函数
#include "golf.h"
#include <iostream>
using namespace std;
int main(void)
{
golf ann;
setgolf(ann, "Ann Birdfree", 24);
showgolf(ann);
golf andy;
setgolf(andy);
showgolf(andy);
handicap(andy, 30);
showgolf(andy);
system("pause");
return 0;
}
测试结果
2. 修改程序清单9.9:用string对象代替字符数组。这样,该程序将不再需要检查输入的字符串是否过长,同时可以将输入字符串同字符串“”进行比较,以判断是否为空行。
#include <iostream>
#include <string>
using namespace std;
void strcount(const string str);
int main(void)
{
string input;
cout << "Enter a line:" << endl;
getline(cin, input);
while (cin)
{
strcount(input);
cout << "Enter next line (empty line to quit):\n";
getline(cin, input);
if (input == "")
break;
}
cout << "Bye." << endl;
system("pause");
return 0;
}
void strcount(const string str)
{
static int total = 0;
int count = 0;
cout << "\"" << str << "\" contains ";
while (str[count])
count++;
total += count;
cout << count << " characters\n";
cout << total << " characters in total\n";
}
3. 下面是一个结构声明:
struct chaff
{
char dross[20];
int slag;
};
编写一个程序,使用定位new运算符将一组放个包含两个这种结构的数组在一个缓冲区中。然后,给结构的成员赋值(对于char数组,使用函数strcpy()),并使用一个循环来显示内容。一种方法是像程序清单9.10那样将一个静态数组用作缓冲区;另一种方法是使用常规new运算符来分配缓冲区。
方法一:定位运算符
#include <iostream>
#include <string>
#include <new>
using namespace std;
const int BUF = 512;
char buffer[BUF];
struct chaff
{
char dross[20];
int slag;
};
int main(void)
{
chaff * p = new(buffer) chaff[2];
char dross[20];
for (int i = 0; i < 2; i++)
{
cout << "Enter dross of #" << i + 1 << " chaff:\n";
cin.getline(dross, 20);
strcpy_s(p[i].dross, dross);
cout << "Enter slag of #" << i + 1 << " chaff:\n";
cin >> p[i].slag;
cin.get();
}
for (int i = 0; i < 2; i++)
{
cout << "chaff #" << i + 1 << ":\n";
cout << "dross: " << p[i].dross << " slag: " << p[i].slag << endl;
}
system("pause");
return 0;
}
方法二:常规new运算符
#include <iostream>
#include <string>
using namespace std;
struct chaff
{
char dross[20];
int slag;
};
int main(void)
{
chaff* p = new chaff[2];
char dross[20];
for (int i = 0; i < 2; i++)
{
cout << "Enter dross of #" << i + 1 << " chaff:\n";
cin.getline(dross, 20);
strcpy_s(p[i].dross, dross);
cout << "Enter slag of #" << i + 1 << " chaff:\n";
cin >> p[i].slag;
cin.get();
}
for (int i = 0; i < 2; i++)
{
cout << "chaff #" << i + 1 << ":\n";
cout << "dross: " << p[i].dross << " slag: " << p[i].slag << endl;
}
delete []p;
system("pause");
return 0;
}
4. 请基于下面这个名称空间编写一个由3个文件组成的程序:
(…………)
第一个文件是一个头文件,其中包含名称空间;第二个文件是一个源代码文件,它对这个名称空间进行扩展,以提供这三个函数的定义;第三个文件声明两个Sales对象,并使用setSales()的交互式版本为一个结构提供值,然后使用setSales()的非交互式版本为另一个结构提供值。另外它还使用showSales()来显示这两个结构的内容。
解答:
- 对名称空间进行扩展,以提供三个函数的定义。(书p332)在名称空间中声明的函数名的作用域为整个名称空间,因此定义和声明必须位于同一名称空间中。通过包含头文件可以导入原来的名称空间。然后在文件中将函数定义添加到名称空间中。
- 在main函数中包含名称空间使用using编译指令即可。using namespace SALES;
头文件9.4.h
#include <iostream>
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);
}
函数定义.cpp
#include "9.4.h"
#include <iostream>
using namespace std;
namespace SALES
{
void setSales(Sales& s, const double ar[], int n) //非交互式版本
{
if (n < 4)
{
for (int i = 0; i < n; i++)
{
s.sales[i] = ar[i];
}
for (int j = n; j < 4; j++)
{
s.sales[j] = 0;
}
}
else
{
for (int i = 0; i < 4; i++)
{
s.sales[i] = ar[i];
}
}
s.average = (s.sales[0] + s.sales[1] + s.sales[2] + s.sales[3]) / 4;
double max = 0.0;
double min = 1000000;
for (int i = 0; i < 4; i++)
{
if (s.sales[i] > max)
{
max = s.sales[i];
}
if (s.sales[i] < min)
{
min = s.sales[i];
}
}
s.max = max;
s.min = min;
}
void setSales(Sales& s)
{
cout << "Please enter sales:\n";
for (int i = 0; i < 4; i++)
{
cout << "The #" << i + 1 << " quarter is: ";
cin >> s.sales[i];
}
s.average = (s.sales[0] + s.sales[1] + s.sales[2] + s.sales[3]) / 4;
double max = 0.0;
double min = 1000000;
for (int i = 0; i < 4; i++)
{
if (s.sales[i] > max)
{
max = s.sales[i];
}
if (s.sales[i] < min)
{
min = s.sales[i];
}
}
s.max = max;
s.min = min;
}
void showSales(const Sales& s)
{
cout << "The sales of 4 quarters are $" << s.sales[0] << ", $" << s.sales[1] << ", $" << s.sales[2] << ", $" << s.sales[3] << endl;
cout << "Average:" << s.average << endl;
cout << "Max:" << s.max << endl;
cout << "Min:" << s.min << endl;
}
}
main函数.cpp
#include "9.4.h"
#include <iostream>
using namespace std;
using namespace SALES;
int main(void)
{
Sales s1, s2;
cout << "#1:" << endl;
setSales(s1);
showSales(s1);
cout << "--------------------------------------------------" << endl;
cout << "#2"<<endl;
double ar[3] = { 10,20,30 };
setSales(s2, ar, 3);
showSales(s2);
cout << "Bye\n";
system("pause");
return 0;
}
第10章 对象和类
(为节约时间,使用类的程序只写了简单的测试,未循环写入、未考虑交互性等)
1. 为复习题5描述的类提供方法定义,并编写一个小程序来演示所有的特性。
复习题5:
定义一个类来表示银行账户。数据成员包括储户姓名、账号(使用字符串)和存款。成员函数执行如下操作:
·创建一个对象并将其初始化
·显示储户姓名、账号和存款
·存入参数指定的存款
·取出参数指定的款项
1.1. 头文件bank.h
#ifndef BANK_H_
#define BANK_H_
#include <iostream>
#include <string>
using namespace std;
class BankAccount
{
private:
string m_name;
string m_acctnum;
double m_balance;
public:
BankAccount(); //默认构造函数
BankAccount(const string &cilent, const string & num, double bal );
void show(void) const; //显示
void deposit(double crash); //存
void withdraw(double crash); //取
};
#endif // !10.1_H_s
1.2.定义成员函数.cpp
#include "bank.h"
#include <iostream>
#include <string>
using namespace std;
BankAccount::BankAccount()
{
m_name = "None";
m_acctnum = "None";
m_balance = 0.0;
}
BankAccount::BankAccount(const string &cilent, const string &num, double bal )
{
m_name = cilent;
m_acctnum = num;
m_balance = bal;
}
void BankAccount::show(void) const
{
cout << "Account information:" << endl;
cout << "Name: " << m_name << endl;
cout << "Account number: " << m_acctnum << endl;
cout << "Balance: " << m_balance << endl;
}
void BankAccount::deposit(double crash)
{
m_balance += crash;
}
void BankAccount::withdraw(double crash)
{
m_balance -= crash;
}
1.3.使用类.cpp
#include "bank.h"
#include <iostream>
#include <string>
int main(void)
{
//使用默认构造函数创建账户bank1
string name1;
string accountnum1;
double bal1;
double add, minus;
BankAccount bank1 = BankAccount(); //使用默认构造函数
bank1.show();
cout << "Enter name:";
getline(cin, name1);
cout << "Enter the number of account:";
getline(cin, accountnum1);
cout << "Enter balance:";
cin >> bal1;
cin.get();
bank1 = BankAccount(name1, accountnum1, bal1); //使用构造函数
bank1.show();
cout << "Please enter the amount to deposit:";
cin >> add;
bank1.deposit(add);
bank1.show();
cout << "Please input the amount to be withdrawn:";
cin >> minus;
bank1.withdraw(minus);
bank1.show();
system("pause");
return 0;
}
总结:我把头文件命名成10.1.h会出错 ,换成英文命名就正常了。
2. 下面是一个非常简单的类定义
class Person
{
private:
static const int LIMIT = 25;
string lname; // Person’s last name
char fname[LIMIT]; // Person’s first name
public:
Person() {lname = ""; fname[0] = '\0';} // #1
Person(const string & ln, const char * fn = "Heyyou"); // #2
// the following methods display lname and fname
void Show() const; // firstname lastname format
void FormalShow() const; // lastname, firstname format
};
它使用了一个string对象和一个字符数组,让您能够比较它们的用法。请提供未定义的方法的代码,以完成这个类的实现。
再编写一个使用这个类的程序,它使用了三种可能的构造函数的调用(没有参数、一个参数和两个参数)以及两种显示方法。
下面是一个使用这些构造函数和方法的例子:
Person one; // use default constructor
Person two("Smythecraft"); // use #2 with one default argument
Person three("Dimwiddy", "Sam"); // use #2, no defaults one.Show();
cout << endl;
one.FormalShow();
// etc. for two and three
2.1.头文件person.h
#ifndef PERSON_H_
#define PERSON_H_
#include <iostream>
using namespace std;
class Person
{
private:
static const int LIMIT = 25;
string lname;
char fname[LIMIT];
public:
Person() { lname = ""; fname[0] = '\0'; };
Person(const string& ln, const char* fn = "Heyyou");
void Show()const;
void FormalShow()const;
};
#endif // !10.2_H_
2.2.成员函数.cpp
#include "person.h"
#include <iostream>
using namespace std;
Person::Person(const string& ln, const char* fn ) //默认参数在原型时有即可,定义时不需要有
{
lname = ln;
strcpy_s(fname, LIMIT, fn);
}
void Person::Show()const
{
cout << fname << " " << lname << endl;
}
void Person::FormalShow()const
{
cout << lname << " , " << fname << endl;
}
2.3.使用类.cpp
#include "person.h"
#include <iostream>
int main(void)
{
Person one;
cout << "默认构造one:" << endl;
one.Show();
one.FormalShow();
Person two("Smythecraft");
cout << "two显示如下:" << endl;
two.Show();
two.FormalShow();
Person three("Dimwiddy", "Sam");
cout << "three显示如下:" << endl;
three.Show();
three.FormalShow();
system("pause");
return 0;
}
总结:含有默认参数的函数只有在函数原型时写,函数定义时不用,会出错。
3. 完成第9章的编程练习1,但要用正确的golf类声明替换那里的代码。用带合适参数的构造函数替换setgolf(golf&, const char*, int),以提供初始值。保留setgolf()的交互版本,但要用构造函数来实现它(例如,setgolf()的代码应该获得数据,将数据传递给构造函数来创建一个临时对象,并将其赋给调用对象,即*this)。
3.1.头文件golf10.h
#ifndef GOLF_H_
#define GOLF_H_
#include <iostream>
using namespace std;
class Golf
{
private:
static const int Len = 40;
char m_fullname[Len];
int m_handicap;
public:
Golf(const char* name, int hc);
Golf();
void sethandicap(int hc);
void showgolf( );
};
#endif // !GOLF_H_
3.2.成员函数定义.cpp
#include "golf10.h"
#include <iostream>
#include <cstring>
using namespace std;
Golf::Golf(const char* name, int hc)
{
strcpy_s(m_fullname, name);
m_handicap = hc;
}
Golf::Golf()
{
char t_name[Len];
int t_handicap;
cout << "Please enter the fullname of player:";
cin.getline(t_name, Len);
cout << "Please enter the handicap of player:";
cin >> t_handicap;
cin.get();
*this = Golf(t_name, t_handicap);
}
void Golf::sethandicap(int hc)
{
m_handicap = hc;
}
void Golf::showgolf()
{
cout << "Information:" << endl;
cout << "Name: " << m_fullname << endl;
cout << "handicap: " << m_handicap << endl;
}
3.3.使用类.cpp
#include "golf10.h"
#include <iostream>
using namespace std;
int main(void)
{
golf g1;
g1.showgolf();
g1.sethandicap(100);
g1.showgolf();
golf g2("li hua", 99);
g2.showgolf();
g2.sethandicap(100);
g2.showgolf();
system("pause");
return 0;
}
4.完成第九章编程练习4,但将Sales结构及相关的函数转换为一个类及其方法。用构造函数替换setSales(sales&, double[], int)函数。 用构造函数实现setSales(Sales&)方法的交互版本。将类保留在名称空间SALES中。
4.1.头文件sales.h
#ifndef SALES10_H_
#define SALES_H_
#include <iostream>
namespace SALES
{
class Sales
{
private:
static const int QUARTERS = 4;
double m_sales[QUARTERS];
double m_average;
double m_max;
double m_min;
public:
Sales(const double ar[], int n);
Sales();
void showSales();
};
}
#endif // !SALES10_H_
4.2.成员函数定义.cpp
#include "sales10.h"
#include <iostream>
using namespace std;
namespace SALES
{
Sales::Sales(const double ar[], int n)
{
if (n < 4)
{
for (int i = 0; i < n; i++)
{
m_sales[i] = ar[i];
}
for (int j = n; j < 4; j++)
{
m_sales[j] = 0;
}
}
else
{
for (int i = 0; i < 4; i++)
{
m_sales[i] = ar[i];
}
}
m_average = (m_sales[0] + m_sales[1] + m_sales[2] + m_sales[3]) / 4;
double max = 0.0;
double min = 1000000;
for (int i = 0; i < 4; i++)
{
if (m_sales[i] > max)
{
max = m_sales[i];
}
if (m_sales[i] < min)
{
min = m_sales[i];
}
}
m_max = max;
m_min = min;
}
Sales::Sales()
{
cout << "Please enter sales:\n";
for (int i = 0; i < 4; i++)
{
cout << "The #" << i + 1 << " quarter is: ";
cin >> m_sales[i];
}
m_average = (m_sales[0] + m_sales[1] + m_sales[2] + m_sales[3]) / 4;
double max = 0.0;
double min = 1000000;
for (int i = 0; i < 4; i++)
{
if (m_sales[i] > max)
{
max = m_sales[i];
}
if (m_sales[i] < min)
{
min = m_sales[i];
}
}
m_max = max;
m_min = min;
}
void Sales::showSales()
{
cout << "The sales of 4 quarters are $" << m_sales[0] << ", $" << m_sales[1] << ", $" << m_sales[2] << ", $" << m_sales[3] << endl;
cout << "Average:" << m_average << endl;
cout << "Max:" << m_max << endl;
cout << "Min:" << m_min << endl;
}
}
4.3.使用类.cpp
#include "sales10.h"
#include <iostream>
using namespace std;
using namespace SALES;
int main(void)
{
Sales s1;
cout << "#1:" << endl;
s1.showSales();
cout << "--------------------------------------------------" << endl;
cout << "#2"<<endl;
double ar[3] = { 10,20,30 };
Sales s2 = Sales( ar, 3);
s2.showSales();
cout << "Bye\n";
system("pause");
return 0;
}
5. 考虑下面的结构声明:
struct customer{
char fullname[35];
double payment;
};
编写一个程序,它从栈中添加和删除customer结构(栈用Stack类声明表示)。每次customer结构被删除时,其payment的值都将被加入到总数中,并报告总数。
注意:应该可以直接使用Stack类而不作修改;只需修改typedef声明,使Item的类型为customer,而不是unsigned long即可。
5.1.头文件stack.h
#ifndef STACK10_H_
#define STACK10_H_
#include <iostream>
struct customer
{
char fullname[35];
double payment;
};
typedef customer Item;
class Stack
{
private:
enum{MAX = 10};
Item items[MAX];
int top;
public:
Stack();
bool isempty() const;
bool isfull() const;
bool push(const Item& item);
bool pop(Item& item);
};
#endif // !STACK_H_
5.2.成员函数定义.cpp
#include "stack10.h"
Stack::Stack()
{
top = 0;
}
bool Stack::isempty() const
{
return top == 0;
}
bool Stack::isfull() const
{
return top == MAX;
}
bool Stack::push(const Item& item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}
bool Stack::pop(Item& item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
5.3使用类.cpp
#include <iostream>
#include <cctype>
#include "stack10.h"
using namespace std;
int main(void)
{
Stack st;
char ch;
customer po;
double totalpayment = 0.0;
cout << "Please enter A to add a purchase order," << endl;
cout << "P to process a PO,or Q to quit." << endl;
while (cin >> ch && toupper(ch) != 'Q')
{
while (cin.get() != '\n')
continue;
if (!isalpha(ch))
{
cout << "\a";
continue;
}
switch (ch)
{
case'A':
case 'a':
cout << "Enter the name of customer:";
cin.getline(po.fullname,30);
cout << "Enter the payment: ";
cin >> po.payment;
cin.get();
if (st.isfull())
cout << "Stack aleady full" << endl;
else
st.push(po);
break;
case 'P':
case 'p':
if (st.isempty())
cout << "stack aleady empty" << endl;
else
{
totalpayment += po.payment;
st.pop(po);
cout << "PO #" << po .fullname<< " popped" << endl;
}
break;
}
cout << "Please enter A to add a purchase order," << endl;
cout << "P to Process a PO,or Q to quit." << endl;
}
cout << "Bye!" << endl;
return 0;
}
6. 下面是一个类声明:
class Move
{
private:
double x;
double y;
public:
Move(double a = 0, double b = 0); // sets x, y to a, b
showmove() const; // shows current x,y values
Move add(const Move & m) const;
// this function adds x of m to x of invoking object to get new x,
// adds y of m to y of invoking object to get new y, creates a new
// move object initialized to new x, y values and returns it
//此函数将m的x加到调用对象的x以获取新的x,将m的y添加到调用对象的y中以获得新的y,
//创建一个新的对象,并将对象初始化为新的x,y值并返回它
reset(double a = 0, double b = 0); // resets x,y to a, b
};
请提供成员函数的定义和测试这个类的程序。
6.1头文件move10.h
#ifndef MOVE_H_
#define MOVE_H_
#include <iostream>
class Move
{
private:
double x;
double y;
public:
Move(double a = 0, double b = 0);
void showmove()const;
Move& add(const Move& m)const;
void reset(double a = 0, double b = 0);
};
#endif // !MOVE_H_
6.2成员函数.cpp
#include "move10.h"
#include <iostream>
using namespace std;
Move::Move(double a , double b)
{
x = a;
y = b;
}
void Move::showmove()const
{
cout << "x = " << x << endl;
cout << "y = " << y << endl;
}
Move& Move::add(const Move& m)const
{
Move new_m;
new_m.x = m.x + this->x;
new_m.y = m.y + this->y;
return new_m;
}
void Move::reset(double a , double b )
{
x = a;
y = b;
}
6.3使用类.cpp
#include "move10.h"
#include <iostream>
using namespace std;
int main(void)
{
Move a;
Move b = Move(120, 60);
a.showmove();
b.showmove();
Move c = a.add(b);
c.showmove();
a = b.add(c);
a.showmove();
a.reset();
a.showmove();
system("pasue");
return 0;
}
7. Betelgeusean plorg有这些特征。
数据:
·plorg的名称不超过19个字符
·plorg的满意指数(CI),这是一个整数
操作:
·新的plorg将有名称,其CI值为50
·plorg的CI可以修改
·plorg可以报告其名称和CI
请编写一个Plorg类声明(包括数据成员和成员函数原型)来表示plorg,并编写成员函数的函数定义。然后编写一个小程序,以演示Plorg类的所有特性。
7.1.头文件plorg10.h
#ifndef PLORG_H_
#include <iostream>
class Plorg
{
private:
static const int Len = 20;
char m_name[Len];
int m_CI;
public:
Plorg();
void SetName(const char* name);
void SetCI(int CI);
void showPlorg();
};
#endif // !PLORGA_H_
7.2.成员函数定义.cpp
#include "plorg10.h"
#include <iostream>
#include <string>
using namespace std;
Plorg::Plorg()
{
strcpy_s(m_name,Len, "Plorga");
m_CI = 0;
}
void Plorg::SetName(const char *name)
{
strcpy_s(m_name,Len, name);
m_CI = 50;
}
void Plorg::SetCI(int CI)
{
m_CI = CI;
}
void Plorg::showPlorg()
{
cout << "The current information is as follows:" << endl;
cout << "Name: " << m_name << endl;
cout << "CI: " << m_CI << endl;
}
7.3.使用类.cpp
#include "plorg10.h"
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
Plorg p;
p.showPlorg();
p.SetName("LI Hua");
p.showPlorg();
p.SetCI(20);
p.showPlorg();
system("pause");
return 0;
}
8. 可以将简单列表描述成下面这样
·可存储0或多个某种类型的列表
·可创建空列表
·可在列表中添加数据项
·可确定列表是否为空
·可确定列表是否为满
·可访问列表中的每一个数据项,并对它执行某种操作
可以看到,这个列表确实很简单,例如,它不允许插入或删除数据项
请设计一个List类来表示这种抽象类型。您应提供头文件list.h和实现文件list.cpp,前者包含类定义,后者包含类方法的实现。您还应该创建一个简短的程序来使用这个类
该列表的规范很简单,这个主要旨在简化这个编程练习。可以选择使用数组或链表来实现该列表,但公有接口不应依赖于所做的选择。也就是说,公有接口不应有数组索引、节点指针等。
应使用通用概念来表达创建列表、在列表中添加数据项等操作。对于访问数据项以及执行操作,通常应使用将函数指针作为参数的函数来处理:void visit(void (*pf)(Item &));
其中。pf指向一个将Item引用作为参数的函数(而不是成员函数),Item是列表中数据项的类型。visit()函数将该函数用于列表中的每个数据项。
8.1头文件list.h
#ifndef LIST_H_
#define LIST_H_
#include <iostream>
#include <string>
using namespace std;
struct customer
{
string name;
double consumption;
};
typedef customer Item;
class List
{
private:
static const int Len = 20;
Item items[Len];
int top = 0;
public:
List();
bool isempty() const;
bool isfull() const;
bool add(const Item& item);
void visit(void(*pf)(Item& item));
void showitem() const;
};
void turnover(Item& item); //计算总营业额(列表中所有顾客消费额相加)
#endif // !LIST_H_
8.2list.cpp
#include "list10.h"
#include <iostream>
#include <string>
using namespace std;
double Sum = 0.0;
List::List()
{
top = 0;
}
bool List::isempty() const
{
return top == 0;
}
bool List::isfull() const
{
return top == Len;
}
bool List::add(const Item& item)
{
if (top < Len)
{
items[top++] = item;
return true;
}
else
return false;
}
void List::showitem() const
{
for (int i = 0; i < top; i++)
{
cout << "#" << i + 1 <<":"<< endl;
cout << "Name: " << items[i].name << endl;
cout << "Consumption: " << items[i].consumption << endl;
}
}
void List::visit(void(*pf)(Item& item))
{
for (int i = 0; i < top; i++)
{
pf(items[i]);
}
}
void turnover(Item& item)
{
Sum += item.consumption;
}
8.3使用类.cpp
#include "list10.h"
#include <iostream>
using namespace std;
extern double Sum;
int main(void)
{
List st;
char ch;
customer po;
cout << "Please enter A to add a purchase order,V to caculate the turnover,S to show the items,or Q to quit." << endl;
while (cin >> ch && toupper(ch) != 'Q')
{
while (cin.get() != '\n')
continue;
if (!isalpha(ch))
{
cout << "\a";
continue;
}
switch (ch)
{
case'A':
case 'a':
cout << "Enter the name of customer:";
getline(cin, po.name);
cout << "Enter the payment: ";
cin >> po.consumption;
cin.get();
if (st.isfull())
cout << "List aleady full" << endl;
else
st.add(po);
break;
case 'S':
case 's':
st.showitem();
break;
case 'V':
case 'v':
if (st.isempty())
{
cout << "List is empty." << endl;
cout << "Sum = 0" << endl;
}
else
{
st.visit(turnover);
cout <<"Sum = "<< Sum << endl;
}
}
cout << "Please enter A to add a purchase order,V to caculate the turnover,S to show the items,or Q to quit." << endl;
}
cout << "Bye!" << endl;
system("pause");
return 0;
}
总结(注意事项):
- 文件间通用一个变量的方法是在一个文件中将其定义为全局变量后,其他文件使用关键字extern。
- 注意使用函数指针做参数的用法。
第11章 使用类
1.修改程序清单11.5,使之将一系列连续的随机漫步者位置写入到文件中。对于每个位置,用步号进行标志。另外,让该程序将初始条件(目标距离和步长)以及结果小结写入到该文件中。该文件的内容与下面类似:
Target Distance: 100, Step Size: 20
0: (x,y) = (0, 0)
1: (x,y) = (-11.4715, 16.383)
2: (x,y) = (-868807, -3.42232)
....
26: (x,y) = (42.2919, -78.2594)
27: (x,y) = (58.6749, -89.7309)
After 27 steps, the subject has the following location:
(x,y) = (58.6749, -89.7309)
or
(m,a) = (107.212, -56.8194)Average outward distance per step = 3.97081
答:与源程序相比,头文件以及成员函数定义无需改动,仅在主函数程序文件做改动,如下所示。
1.1.头文件vector11.h
#ifndef VECTOR_H_
#define VECTOR_H_
#include <iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode{RECT,POL};
private:
double x;
double y;
double mag;
double ang;
Mode mode;
void set_mag();
void set_ang();
void set_x();
void set_y();
public:
Vector();
Vector(double n1, double n2, Mode from = RECT);
void reset(double n1, double n2, Mode from = RECT);
~Vector();
double xval()const { return x; };
double yval()const { return y; };
double magval() const { return mag; };
double angval()const { return ang; };
void polar_mode();
void rect_mode();
Vector operator+(const Vector& b)const;
Vector operator-(const Vector& b)const;
Vector operator-()const;
Vector operator*(double n)const;
friend Vector operator*(double n, const Vector& a);
friend std::ostream& operator<<(std::ostream& os, const Vector& v);
};
}
#endif // !VECTOR_H_
1.2成员函数定义.cpp
#include "vector11.h"
#include <iostream>
#include <cmath>
using namespace std;
namespace VECTOR
{
const double Rad_to_deg = 45.0 / atan(1.0);
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if (x == 0 && y == 0)
{
ang = 0.0;
}
else
ang = atan2(y, x);
}
void Vector::set_x()
{
x = mag * cos(ang);
}
void Vector::set_y()
{
y = mag * sin(ang);
}
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = RECT;
}
Vector::Vector(double n1, double n2, Mode from)
{
mode = from;
if (from == RECT)
{
x = n1;
y = n2;
set_ang();
set_mag();
}
else if(from == POL)
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector()--";
cout << "vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode from)
{
mode = from;
if (from == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (from == POL)
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector()--";
cout << "vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
}
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
Vector Vector::operator+(const Vector& b)const
{
return Vector(x + b.x, y + b.y);
}
Vector Vector::operator-(const Vector& b)const
{
return Vector(x - b.x, y - b.y);
}
Vector Vector::operator-()const
{
return Vector(-x, -y);
}
Vector Vector::operator*(double n)const
{
return Vector(n * x, n * y);
}
Vector operator*(double n, const Vector& a)
{
return a * n;
}
ostream& operator<<(ostream& os, const Vector& v)
{
if (v.mode == Vector::RECT)
os << "(x,y) = (" << v.x << "," << v.y << ")";
else if (v.mode == Vector::POL)
os << "(m,a) = (" << v.mag << "," << v.ang << ")";
else
os << "Vector object mode is invalid";
return os;
}
}
1.3使用类.cpp
#include <iostream>
#include <cstdlib> //rand()、srand()
#include <ctime> //time()
#include "vector11.h"
#include <fstream>
using namespace std;
int main()
{
using VECTOR::Vector;
ofstream outFile;
outFile.open("11.1randwalker.txt");
srand(time(0));
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
cout << "Enter target distance:(q to quit)";
while (cin >> target)
{
cout << "Enter step length:";
if (!(cin >> dstep))
break;
outFile<< "Target Distance: " << target << ", " << "Step Size: " << dstep << endl;
while (result.magval() < target)
{
outFile << steps << ": " << result << endl;
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
}
cout << "After " << steps << " steps,the subject ""has the following location:" << endl;
outFile << "After " << steps << " steps,the subject ""has the following location:" << endl;
cout << result << endl;
outFile << result << endl;
result.polar_mode();
cout << " or\n" << result << endl;
cout << "Average outward distance per step = " << result.magval() / steps << endl;
outFile << " or\n" << result << endl;
outFile << "Average outward distance per step = " << result.magval() / steps << endl;
steps = 0;
result.reset(0.0, 0.0);
cout << "Enter target distance(q to quit):";
}
cout << "Bye!" << endl;
cin.clear();
while (cin.get() != '\n')
continue;
outFile.close();
system("pause");
return 0;
}
结果展示:
2.对于Vector类的头文件(程序清单11.13)和实现文件(程序清单11.14)进行修改,使其不再储存矢量的长度和角度,而是在magval()和angval()被调用时计算它们。
应保留公有接口不变(公有方法及其参数不变),但对私有部分(包括一些私有方法)和方法实现进行修改。然后,使用程序清单11.15对修改后的版本进行测试,结果应该与以前相同,因为Vecotr类的公有接口与原来相同。
2.1头文件vector112.h有修改,删除了两个私有变量,修改了两个私有成员函数。
#ifndef VECTOR112_H_
#define VECTOR112_H_
#include <iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode { RECT, POL };
private:
double x;
double y;
Mode mode;
double set_mag();
double set_ang();
void set_x(double mag, double ang);
void set_y(double mag, double ang);
public:
Vector();
Vector(double n1, double n2, Mode from = RECT);
void reset(double n1, double n2, Mode from = RECT);
~Vector();
double xval()const { return x; };
double yval()const { return y; };
double magval() const;
double angval()const;
void polar_mode();
void rect_mode();
Vector operator+(const Vector& b)const;
Vector operator-(const Vector& b)const;
Vector operator-()const;
Vector operator*(double n)const;
friend Vector operator*(double n, const Vector& a);
friend std::ostream& operator<<(std::ostream& os, const Vector& v);
};
}
#endif // !VECTOR_H_
2.2成员函数定义.cpp (有修改)
#include "vector112.h"
#include <iostream>
#include <cmath>
using namespace std;
namespace VECTOR
{
const double Rad_to_deg = 45.0 / atan(1.0);
double Vector::set_mag()
{
double mag;
mag = sqrt(x * x + y * y);
return mag;
}
double Vector::set_ang()
{
double ang;
if (x == 0 && y == 0)
{
ang = 0.0;
}
else
ang = atan2(y, x);
return ang;
}
void Vector::set_x(double mag,double ang)
{
x = mag * cos(ang);
}
void Vector::set_y(double mag,double ang)
{
y = mag * sin(ang);
}
Vector::Vector()
{
x = y = 0;
mode = RECT;
}
Vector::Vector(double n1, double n2, Mode from)
{
mode = from;
if (from == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if(from == POL)
{
double mag, ang;
mag = n1;
ang = n2 / Rad_to_deg;
set_x(mag,ang);
set_y(mag,ang);
}
else
{
cout << "Incorrect 3rd argument to Vector()--";
cout << "vector set to 0" << endl;
x = y = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode from)
{
mode = from;
if (from == RECT)
{
x = n1;
y = n2;
}
else if (from == POL)
{
double mag, ang;
mag = n1;
ang = n2 / Rad_to_deg;
set_x(mag,ang);
set_y(mag,ang);
}
else
{
cout << "Incorrect 3rd argument to Vector()--";
cout << "vector set to 0" << endl;
x = y = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
}
double Vector::magval() const
{
double mag;
mag = sqrt(x * x + y * y);
return mag;
}
double Vector::angval() const
{
double ang;
if (x == 0.0 && y == 0.0)
ang = 0.0;
else
ang = atan2(y, x);
return ang;
}
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
Vector Vector::operator+(const Vector& b)const
{
return Vector(x + b.x, y + b.y);
}
Vector Vector::operator-(const Vector& b)const
{
return Vector(x - b.x, y - b.y);
}
Vector Vector::operator-()const
{
return Vector(-x, -y);
}
Vector Vector::operator*(double n)const
{
return Vector(n * x, n * y);
}
Vector operator*(double n, const Vector& a)
{
return a * n;
}
ostream& operator<<(ostream& os, const Vector& v)
{
if (v.mode == Vector::RECT)
os << "(x,y) = (" << v.x << "," << v.y << ")";
else if (v.mode == Vector::POL)
os << "(m,a) = (" << v.magval()<< "," << v.angval() << ")";
else
os << "Vector object mode is invalid";
return os;
}
}
2.3使用类main函数(无修改)
#include <iostream>
#include <cstdlib> //rand()、srand()
#include <ctime> //time()
#include "vector112.h"
using namespace std;
int main()
{
using VECTOR::Vector;
srand(time(0));
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
cout << "Enter target distance:(q to quit)";
while (cin >> target)
{
cout << "Enter step length:";
if (!(cin >> dstep))
break;
while (result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
}
cout << "After " << steps << " steps,the subject ""has the following location:" << endl;
cout << result << endl;
result.polar_mode();
cout << " or\n" << result << endl;
cout << "Average outward distance per step = " << result.magval() / steps << endl;
steps = 0;
result.reset(0.0, 0.0);
cout << "Enter target distance(q to quit):";
}
cout << "Bye!" << endl;
cin.clear();
while (cin.get() != '\n')
continue;
system("pause");
return 0;
}
3. 修改程序清单11.15,使之报告N次测试中的最高、最低和平均步数(其中N是用户输入的整数),而不是报告每次测试的结果。
3.1头文件vector113.h同上题
#ifndef VECTOR112_H_
#define VECTOR112_H_
#include <iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode { RECT, POL };
private:
double x;
double y;
Mode mode;
double set_mag();
double set_ang();
void set_x(double mag, double ang);
void set_y(double mag, double ang);
public:
Vector();
Vector(double n1, double n2, Mode from = RECT);
void reset(double n1, double n2, Mode from = RECT);
~Vector();
double xval()const { return x; };
double yval()const { return y; };
double magval() const;
double angval()const;
void polar_mode();
void rect_mode();
Vector operator+(const Vector& b)const;
Vector operator-(const Vector& b)const;
Vector operator-()const;
Vector operator*(double n)const;
friend Vector operator*(double n, const Vector& a);
friend std::ostream& operator<<(std::ostream& os, const Vector& v);
};
}
#endif // !VECTOR_H_
3.2成员函数定义.cpp同上题
#include "vector113.h"
#include <iostream>
#include <cmath>
using namespace std;
namespace VECTOR
{
const double Rad_to_deg = 45.0 / atan(1.0);
double Vector::set_mag()
{
double mag;
mag = sqrt(x * x + y * y);
return mag;
}
double Vector::set_ang()
{
double ang;
if (x == 0 && y == 0)
{
ang = 0.0;
}
else
ang = atan2(y, x);
return ang;
}
void Vector::set_x(double mag,double ang)
{
x = mag * cos(ang);
}
void Vector::set_y(double mag,double ang)
{
y = mag * sin(ang);
}
Vector::Vector()
{
x = y = 0;
mode = RECT;
}
Vector::Vector(double n1, double n2, Mode from)
{
mode = from;
if (from == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if(from == POL)
{
double mag, ang;
mag = n1;
ang = n2 / Rad_to_deg;
set_x(mag,ang);
set_y(mag,ang);
}
else
{
cout << "Incorrect 3rd argument to Vector()--";
cout << "vector set to 0" << endl;
x = y = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode from)
{
mode = from;
if (from == RECT)
{
x = n1;
y = n2;
}
else if (from == POL)
{
double mag, ang;
mag = n1;
ang = n2 / Rad_to_deg;
set_x(mag,ang);
set_y(mag,ang);
}
else
{
cout << "Incorrect 3rd argument to Vector()--";
cout << "vector set to 0" << endl;
x = y = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
}
double Vector::magval() const
{
double mag;
mag = sqrt(x * x + y * y);
return mag;
}
double Vector::angval() const
{
double ang;
if (x == 0.0 && y == 0.0)
ang = 0.0;
else
ang = atan2(y, x);
return ang;
}
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
Vector Vector::operator+(const Vector& b)const
{
return Vector(x + b.x, y + b.y);
}
Vector Vector::operator-(const Vector& b)const
{
return Vector(x - b.x, y - b.y);
}
Vector Vector::operator-()const
{
return Vector(-x, -y);
}
Vector Vector::operator*(double n)const
{
return Vector(n * x, n * y);
}
Vector operator*(double n, const Vector& a)
{
return a * n;
}
ostream& operator<<(ostream& os, const Vector& v)
{
if (v.mode == Vector::RECT)
os << "(x,y) = (" << v.x << "," << v.y << ")";
else if (v.mode == Vector::POL)
os << "(m,a) = (" << v.magval()<< "," << v.angval() << ")";
else
os << "Vector object mode is invalid";
return os;
}
}
3.3使用类.cpp做修改
#include <iostream>
#include <cstdlib> //rand()、srand()
#include <ctime> //time()
#include "vector113.h"
using namespace std;
int main()
{
using VECTOR::Vector;
srand(time(0));
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
int max = 0;
int min = 100000;
int sum = 0;
double average = 0.0;
int N;
cout << "Test times:";
cin >> N;
for (int i = 0; i < N; i++)
{
cout << "Enter target distance:(q to quit)";
cin >> target;
cout << "Enter step length:";
cin >> dstep;
while (result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
}
cout << "# "<<i+1<<":"<<"After " << steps << " the subject reach destination." << endl;
max = max > steps ? max : steps;
min = min < steps ? min : steps;
sum += steps;
steps = 0;
result.reset(0.0, 0.0);
}
average = double(sum) / N;
cout << "The max steps is: " << max << endl;
cout << "The min steps is: " << min << endl;
cout << "The average steps is: " << average << endl;
cout << "Bye!" << endl;
cin.clear();
system("pause");
return 0;
}
4.重新编写最后的Time类示例(程序清单11.10、程序清单11.11和程序清单11.12),使用友元函数来实现所有的重载运算符。
4.1头文件mytime114.h
#ifndef MYTIME114_H_
#define MYTIME114_H_
#include <iostream>
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m = 0);
void AddMin(int m);
void AddHr(int h);
void Reset(int h = 0, int m = 0);
friend Time operator+(const Time& t1,const Time &t2);
friend Time operator-(const Time& t1,const Time &t2);
friend Time operator*(const Time & t,double mult);
friend Time operator* (double m, const Time& t) { return t * m; }
friend std::ostream& operator<< (std::ostream & os, const Time & t);
};
#endif
4.2成员函数定义.cpp
#include "mytime114.h"
#include <iostream>
Time::Time()
{
hours = minutes = 0;
}
Time::Time(int h, int m)
{
hours = h;
minutes = m;
}
void Time::AddMin(int m)
{
hours += m;
hours += minutes / 10;
minutes %= 60;
}
void Time::AddHr(int h)
{
hours += h;
}
void Time::Reset(int h, int m)
{
hours = h;
minutes = m;
}
Time operator+(const Time& t1, const Time& t2)
{
Time sum;
sum.minutes =t1.minutes + t2.minutes;
sum.hours = t1.hours + t2.hours + sum.minutes / 60;
sum.minutes %= 60;
return sum;
}
Time operator-(const Time& t1, const Time& t2)
{
Time diff;
int tot1, tot2;
tot1 = t1.minutes + 60 * t1.hours;
tot2 = t2.minutes + 60 *t2. hours;
diff.hours = (tot2 - tot1) / 60;
diff.minutes = (tot2 - tot1) % 60;
return diff;
}
Time operator*(const Time& t, double mult)
{
Time result;
long totalminutes = t.hours * mult * 60 + t.minutes * mult;
result.hours = totalminutes / 60;
result.minutes = totalminutes % 60;
return result;
}
std::ostream& operator<< (std::ostream& os, const Time& t)
{
os << t.hours << "hours, " << t.minutes << " minutes";
return os;
}
4.3使用类.cpp(不改变,与程序清单11.12相同)
#include "mytime114.h"
#include <iostream>
int main(void)
{
using std::cout;
using std::endl;
Time aida(3, 25);
Time tosca(2, 48);
Time temp;
cout << "Aida and Tosca:" << endl;
cout << aida << " ; " << tosca << endl;
temp = aida + tosca;
cout << "Aida + Tosca: " << temp << endl;
temp = aida * 1.17;
cout << "Aida * 1.17: " << temp << endl;
cout << "10.0*Tosca: " << 10.0 * tosca << endl;
system("pause");
return 0;
}
5.重新编写Stonewt类(程序清单11.16和程序清单11.17),使它有一个状态成员,由该状态成员控制对象应转换为英石格式、整数磅格式还是浮点磅格式。重载<<运算符,使用它来替换show_stn()和show_lbs()方法。重载加法、减法和乘发运算符,以便可以对Stonewt值进行加、减、乘运算。编写一个使用所有类方法和友元的小程序,来测试这个类。
5.1头文件stonewt115.h
#ifndef STONEWT115_H_
#define STONEWT115_H_
#include <iostream>
class Stonewt
{
public:
enum Format { st, intp, doublep };
private:
enum { Lbs_per_stn = 14 };
int stone;
double pds_left;
double pounds;
Format m_form;
public:
Stonewt(double lbs);
Stonewt(int stn, double lbs);
Stonewt();
~Stonewt();
void SetFormat(Format form);
Stonewt operator+ (const Stonewt& s)const;
Stonewt operator- (const Stonewt& s)const;
Stonewt operator* (double n)const;
friend Stonewt operator*(double m, const Stonewt& s){return s * m;}
friend std::ostream& operator<< (std::ostream& os, const Stonewt& s);
};
#endif
5.2成员函数定义.cpp
#include "stonewt115.h"
#include <iostream>
Stonewt::Stonewt(double lbs)
{
stone = int(lbs) / Lbs_per_stn;
pds_left = int(lbs) % Lbs_per_stn + lbs - int(lbs);
pounds = lbs;
m_form = st;
}
Stonewt::Stonewt(int stn, double lbs)
{
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn + lbs;
m_form = intp;
}
Stonewt::Stonewt()
{
stone = pounds = pds_left = 0;
m_form = doublep;
}
Stonewt::~Stonewt()
{
}
void Stonewt::SetFormat(Format from)
{
m_form = from;
}
Stonewt Stonewt::operator+ (const Stonewt& s)const
{
Stonewt sum;
sum.pounds = pounds + s.pounds;
sum.stone = int(sum.pounds) / Lbs_per_stn;
sum.pds_left = int(sum.pounds) % Lbs_per_stn + sum.pounds - int(sum.pounds);
return sum;
}
Stonewt Stonewt::operator- (const Stonewt& s)const
{
Stonewt diff;
diff.pounds = pounds - s.pounds;
diff.stone = int(diff.pounds) / Lbs_per_stn;
diff.pds_left = int(diff.pounds) % Lbs_per_stn + diff.pounds - int(diff.pounds);
return diff;
}
Stonewt Stonewt::operator* (double n)const
{
double mult;
mult = pounds * n;
return Stonewt(mult);
}
std::ostream& operator<< (std::ostream& os, const Stonewt& s)
{
if (s.m_form == Stonewt::st)
{
os << s.stone << " stone, " << s.pds_left << " pounds\n";
}
else if (s.m_form == Stonewt::intp)
{
os << int(s.pounds) << " pounds\n";
}
else if (s.m_form == Stonewt::doublep)
{
os << s.pounds << " pounds\n";
}
else
os << "Stonewt state is invalid";
return os;
}
5.3使用类.cpp
#include "stonewt115.h"
#include <iostream>
using std::cout;
using std::cin;
int main(void)
{
Stonewt incognito = 275;
Stonewt wolfe(285.7);
Stonewt taft(21, 8);
cout << "The celebrity weighed: " << incognito ; //st
cout << "The detective weighed: " << wolfe; //st
cout << "The President weighed: " << taft << "\n"; //intp
Stonewt tf(2);
Stonewt sum, diff, mult;
sum = incognito + tf;
diff = wolfe - tf;
mult = taft * 2;
cout << "The result will display as double_pounds: \n";
cout << "After dinner, the celebrity weighed: ";
sum.SetFormat(Stonewt::doublep);
cout << sum;
cout << "After sport, the detective weighed: ";
diff.SetFormat(Stonewt::doublep);
cout << diff;
cout << "Now,the President weighed: ";
mult.SetFormat(Stonewt::doublep);
cout << mult;
system("pause");
return 0;
}
6.重新编写Stonewt类(程序清单11.16和程序清单11.17),重载全部6个关系运算符。运算符对pounds成员进行比较,并返回一个bool值。编写一个程序,它声明一个包含6个Stonewt对象的数组,并在数组声明中初始化前3个对象。然后使用循环来读取用于设置剩余3个数组元素的值。接着报告最小的元素、最大的元素以及大于或等于11英石的元素的数量(最简单的方法是创建一个Stonewt对象,并将其初始化为11英石,然后将其同其他对象进行比较)。
6.1头文件stonewt116.ch
#ifndef STONEWT116_H_
#define STONEWT116_H_
#include <iostream>
class Stonewt
{
public:
enum Format { st, intp, doublep };
private:
enum { Lbs_per_stn = 14 };
int stone;
double pds_left;
double pounds;
Format state;
public:
Stonewt(double lbs);
Stonewt(int stn, double lbs);
Stonewt();
~Stonewt();
void Setstate(Format x);
friend bool operator>(const Stonewt& s1, const Stonewt& s2);
friend bool operator<(const Stonewt& s1, const Stonewt& s2);
friend bool operator>=(const Stonewt& s1, const Stonewt& s2);
friend bool operator<=(const Stonewt& s1, const Stonewt& s2);
friend bool operator==(const Stonewt& s1, const Stonewt& s2);
friend bool operator!=(const Stonewt& s1, const Stonewt& s2);
friend std::ostream& operator<< (std::ostream& os, const Stonewt& s);
};
#endif
6.2成员函数定义.cpp
#include "stonewt116.h"
#include <iostream>
using std::cout;
using std::endl;
using namespace std;
Stonewt::Stonewt(double lbs)
{
stone = int(lbs) / Lbs_per_stn;
pds_left = int(lbs) % Lbs_per_stn + lbs - int(lbs);
pounds = lbs;
state = st;
}
Stonewt::Stonewt(int stn, double lbs)
{
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn + lbs;
state = st;
}
Stonewt::Stonewt()
{
stone = pounds = pds_left = 0;
state = st;
}
Stonewt::~Stonewt()
{
}
void Stonewt::Setstate(Format x)
{
state = x;
}
bool operator>(const Stonewt& s1, const Stonewt& s2)
{
if (s1.pounds > s2.pounds)
return true;
else
return false;
}
bool operator<(const Stonewt& s1, const Stonewt& s2)
{
if (s1.pounds < s2.pounds)
return true;
else
return false;
}
bool operator>=(const Stonewt& s1, const Stonewt& s2)
{
if (s1.pounds >= s2.pounds)
return true;
else
return false;
}
bool operator<=(const Stonewt& s1, const Stonewt& s2)
{
if (s1.pounds <= s2.pounds)
return true;
else
return false;
}
bool operator==(const Stonewt& s1, const Stonewt& s2)
{
if (s1.pounds == s2.pounds)
return true;
else
return false;
}
bool operator!=(const Stonewt& s1, const Stonewt& s2)
{
if (s1.pounds != s2.pounds)
return true;
else
return false;
}
ostream& operator<< (ostream& os, const Stonewt& s)
{
if (s.state == Stonewt::st)
{
os << s.stone << " stone, " << s.pds_left << " pounds\n";
}
else if (s.state == Stonewt::intp)
{
os << int(s.pounds) << " pounds\n";
}
else if (s.state == Stonewt::doublep)
{
os << s.pounds << " pounds\n";
}
else
os << "Stonewt state is invalid";
return os;
}
6.3主函数.cpp
#include <iostream>
using namespace std;
#include "stonewt116.h"
//编写一个程序,它声明一个包含6个Stonewt对象的数组,
//并在数组声明中初始化前3个对象。
//然后使用循环来读取用于设置剩余3个数组元素的值。
//接着报告最小的元素、最大的元素以及大于或等于11英石的元素的数量
//最简单的方法是创建一个Stonewt对象,并将其初始化为11英石,然后将其同其他对象进行比较
int main(void)
{
Stonewt s[6] = {{200.0},{100.2},{21,5.2} };
cout << "Enter the rest three Stonewt:\n";
for (int i = 3; i < 6; i++)
{
double pounds;
cout << "#" << i + 1 << ": ";
cin >> pounds;
s[i] = pounds;
}
Stonewt max = s[0];
Stonewt min = s[0];
const Stonewt flag(11, 0);
int count = 0;
for (int i = 0; i < 6; i++)
{
max = max > s[i] ? max : s[i];
min = min < s[i] ? min : s[i];
if (s[i] >= flag)
count++;
}
cout << "The max is: " << max;
cout << "The min is: " << min;
cout << "There are " << count << " memeber bigger than 11 stone.\n";
system("pause");
return 0;
}
7.复数有两个部分组成:实数部分和虚数部分。复数的一种书写方式是:(3.0,4.0),其中,3.0是实数部分,4.0是虚数部分。假设a=(A,Bi),c=(C,Di),则下面是一些复数运算。
加法:a+c=(A+C,(B+D)i)。
减法:a-c=(A-C,(B-D)i)。
乘法:a * c=(A*C-B * D,(A * D+B * C)i)。
乘法:x * c=(x * C,x * Di),其中x为实数。
共轭:~a=(A,-Bi)。
请定义一个复数类,以便下面的程序可以使用它来获得正确的结果。
(……代码省略……)
注意。必须重载运算符<<和>>。标准C++使用头文件complex提供了比这个示例更广泛的复数支持,因此应将自定义的头文件命名为complex0.h,以免发生冲突。应尽可能使用const。
下面是该程序的运行情况。
(……代码省略……)
请注意,经过重载后,cin>>c将提示用户输入实数和虚数部分。
7.1头文件complex117.h
#ifndef COMPLEX117_H_
#define COMPLEX117_H_
#include <iostream>
class Complex
{
private:
double real;
double imag;
public:
Complex();
Complex(double m, double n);
~Complex();
Complex operator+(const Complex& c)const;
Complex operator-(const Complex& c)const;
Complex operator*(const Complex& c)const;
Complex operator*(double x)const;
friend Complex operator*(double n, const Complex& m){return m * n;}
Complex operator~()const;
friend std::ostream& operator<<(std::ostream& os, const Complex& n);
friend std::istream& operator>>(std::istream& is, Complex& n);
};
#endif // !COMPLEX117_H_
7.2成员函数定义.cpp
#include "complex117.h"
#include <iostream>
using namespace std;
Complex::Complex()
{
real = imag = 0.0;
}
Complex::Complex(double m, double n)
{
real = m;
imag = n;
}
Complex::~Complex()
{
}
Complex Complex::operator+(const Complex& c)const
{
Complex sum;
sum.real = c.real + this->real;
sum.imag = c.imag + this->imag;
return sum;
}
Complex Complex::operator-(const Complex& c)const
{
Complex diff;
diff.real = this->real - c.real;
diff.imag = this->imag - c.imag;
return diff;
}
Complex Complex::operator*(const Complex& c)const
{
Complex mult1;
mult1.real = this->real * c.real - this->imag * c.imag;
mult1.imag = this->real * c.imag + this->imag * c.real;
return mult1;
}
Complex Complex::operator*(double x)const
{
Complex mult2;
mult2.real = this->real * x;
mult2.imag = this->imag * x;
return mult2;
}
Complex Complex::operator~()const
{
Complex temp;
temp.real =this-> real;
temp.imag = -(this->imag);
return temp;
}
std::ostream& operator<<(std::ostream& os, const Complex& x)
{
os << "(" << x.real << ", " << x.imag << "i)";
return os;
}
std::istream& operator>>(std::istream& is, Complex& x)
{
cout << "real: ";
is >> x.real;
if(x.real )
{
cout << "imaginary: ";
is >> x.imag;
}
return is;
}
7.3使用类.cpp
#include <iostream>
#include "complex117.h"
using namespace std;
int main(void)
{
Complex a(3.0, 4.0);
Complex c;
cout << "Enter a complex number(q to quit):\n";
while (cin >> c)
{
cout << "c is " << c << endl;
cout << "complex conjugate is " << ~c << endl;
cout << "a is " << a << endl;
cout << "a + c is " << a + c << endl;
cout << "a - c is " << a - c << endl;
cout << "a * c is " << a * c << endl;
cout << "2 * c is " << 2 * c << endl;
cout << "Enter a complex number (q to quit):" << endl;
}
cout << "Done!" << endl;
system("pause");
return 0;
}
第12章 类和动态内存分配
1.对于下面的类声明:
(……代码忽略……)
给这个类提供实现,并编写一个使用所有成员函数的小程序。
笔记:#pragma warning(disable:4996) //解决strcpy报错的问题
1.1头文件cow121.h
#ifndef COW121_H_
#define COW121_H_
#pragma warning(disable:4996) //解决strcpy报错的问题
class Cow
{
private:
char name[20];
char* hobby;
double weight;
public:
Cow();
Cow(const char* nm, const char* ho, double wt);
Cow(const Cow &c);
~Cow();
Cow& operator= (const Cow& c);
void ShowCow()const;
};
#endif // ! Cow121_H_
1.2成员函数定义.cpp
#include <iostream>
#include <cstring>
#include "cow121.h"
using std::endl;
using std::cout;
Cow::Cow()
{
name[0] = '\0';
hobby = new char[1];
hobby[0] = '\0';
weight = 0.0;
}
Cow::Cow(const char* nm, const char* ho, double wt)
{
strcpy(name, nm);
hobby = new char[strlen(ho) + 1];
strcpy(hobby, ho);
weight = wt;
}
Cow::Cow(const Cow& c)
{
strcpy(name, c.name);
hobby = new char[strlen(c.hobby) + 1];
strcpy(hobby,c.hobby);
weight = c.weight;
}
Cow::~Cow()
{
delete[] hobby;
}
Cow& Cow::operator= (const Cow& c)
{
delete[] hobby;
strcpy(name,c.name);
hobby = new char[strlen(c.hobby) + 1];
strcpy(hobby, c.hobby);
weight = c.weight;
return *this;
}
void Cow::ShowCow()const
{
cout << "Name: " << name << endl;
cout << "Hobby: " << hobby << endl;
cout << "Weight: " << weight << endl;
cout << endl;
}
1.3使用类.cpp
#include "cow121.h"
#include <iostream>
using std::cout;
using std::endl;
int main(void)
{
Cow c1;
cout << "c1:" << endl;
c1.ShowCow();
Cow c2("Yonggan Niuniu", "study", 100.23);
cout << "c2:" << endl;
c2.ShowCow();
Cow c3("Tangping Niuniu", "play game", 150.80);
cout << "c3:" << endl;
c3.ShowCow();
Cow c4(c2);
cout << "c4:" << endl;
c4.ShowCow();
c1 = c3;
cout << "c1 = c3:" << endl;
c3.ShowCow();
c1.ShowCow();
system("pause");
return 0;
}
2.通过完成下面的工作来改进String类声明(即将String1.h升级为String2.h)。
a. 对+运算符进行重载,使之可将两个字符串合并成1个。
b. 提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写(别忘了cctype系列字符函数)。
c. 提供String()成员函数,将字符串中所有字母字符转换成大写。
d. 提供一个这样的成员函数,它接受一个char参数,返回该字符在字符串中出现的次数。
使用下面的程序来测试您的工作:
(……代码忽略……)
输出应与下面相似:
(……代码忽略……)
笔记:strcpy(temp+len, s.str); //注意!!! 是temp+len而不是temp,意味着从temp[len]开始复制。
2.1头文件string122.h
#ifndef STRING122_H_
#define STRING122_H_
#pragma warning(disable:4996)
#include <iostream>
using std::ostream;
using std::istream;
class String
{
private:
char* str;
int len;
static int num_strings;
static const int CINLIM = 80;
public:
String(const char* s);
String();
String(const String& st);
~String();
int length()const { return len; }
//重载
String& operator=(const String& st);
String& operator=(const char* s);
char& operator[](int i);
const char& operator[](int i)const;
//友元
friend bool operator<(const String& st1, const String& st2);
friend bool operator>(const String& st1, const String& st2);
friend bool operator==(const String& st1, const String& st2);
friend ostream& operator<<(ostream& os, const String& st);
friend istream& operator>>(istream& is, String& st);
//static function
static int Howmany();
//新增函数
//a.对 + 运算符进行重载,使之可将两个字符串合并成1个。
String operator+(const String &s)const;
String operator+(const char* s)const;
friend String operator+(const char* s1, const String& s2);
//b.提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写。
void stringlow();
//c.提供String()成员函数,将字符串中所有字母字符转换成大写。
void stringup();
//d.提供一个这样的成员函数,它接受一个char参数,返回该字符在字符串中出现的次数
int has(char ch);
};
#endif // !STRING1_H_
2.2string.cpp
#include <cstring>
#include <cctype>
#include "string122.h"
using std::cin;
using std::cout;
int String::num_strings = 0;
//static method
int String::Howmany()
{
return num_strings;
}
String::String(const char* s)
{
len = std::strlen(s);
str = new char[len + 1];
strcpy_s(str,len+1, s);
num_strings++;
}
String::String()
{
len = 4;
str = new char[1];
str[0] = '\0';
num_strings++;
}
String::String(const String&st)
{
num_strings++;
len = st.len;
str = new char[len + 1];
strcpy_s(str,len+1, st.str);
}
String::~String()
{
--num_strings;
delete[] str;
}
//重载
String& String::operator=(const String& st)
{
if (this == &st)
return *this;
delete[] str;
len = st.len;
str = new char[len + 1];
strcpy_s(str,len+1, st.str);
return *this;
}
String& String::operator=(const char* s)
{
delete[] str;
len = std::strlen(s);
str = new char[len + 1];
strcpy_s(str, len+1,s);
return *this;
}
char& String:: operator[](int i)
{
return str[i];
}
const char& String::operator[](int i)const
{
return str[i];
}
//友元
bool operator<(const String& st1, const String& st2)
{
return(std::strcmp(st1.str, st2.str));
}
bool operator>(const String& st1, const String& st2)
{
return st2 < st1;
}
bool operator==(const String& st1, const String& st2)
{
return(std::strcmp(st1.str, st2.str) == 0);
}
ostream& operator<<(ostream& os, const String& st)
{
os << st.str;
return os;
}
istream& operator>>(istream& is, String& st)
{
char temp[String::CINLIM];
is.get(temp,String::CINLIM);
if (is)
st = temp;
while (is && is.get() != '\n')
continue;
return is;
}
//新增函数
String String::operator+(const String& s)const
{
int lens = s.len + len;
char* temp = new char[lens + 1];
strcpy(temp, str);
strcpy(temp+len, s.str); //注意!!!
return String(temp);
}
String String::operator+(const char* s)const
{
int lens = strlen(s) + len;
char* temp = new char[lens + 1];
strcpy(temp, str);
strcpy(temp+len,s);
return String(temp);
}
String operator+(const char* s1, const String& s2)
{
return String(s1) + s2;
}
//b.提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写。
void String::stringlow()
{
for (int i = 0; i <= len; i++)
{
str[i] = tolower(str[i]);
}
}
//c.提供String()成员函数,将字符串中所有字母字符转换成大写。
void String::stringup()
{
for (int i = 0; i <= len; i++)
{
str[i] = toupper(str[i]);
}
}
//d.提供一个这样的成员函数,它接受一个char参数,返回该字符在字符串中出现的次数
int String::has(char ch)
{
int count = 0;
for (int i = 0; i <= len; i++)
{
if (str[i] == ch)
count++;
}
return count;
}
2.3测试类.cpp
#include <iostream>
using namespace std;
#include "string122.h"
int main()
{
String s1(" and I am a C++ student.");
String s2 = "Please enter your name: ";
String s3;
cout << s2;
cin >> s3;
s2 = "My name is " + s3;
cout << s2 << ".\n";
s2 = s2 + s1;
s2.stringup();
cout << "The string\n" << s2 << "\ncontains " << s2.has('A')
<< " 'A' characters in it.\n";
s1 = "red";
String rgb[3] = { String(s1),String("green"),String("blue") };
cout << "Enter the name of a primary color for mixing light: ";
String ans;
bool success = false;
while (cin >> ans)
{
ans.stringlow();
for (int i = 0; i < 3; i++)
{
if (ans == rgb[i])
{
cout << "That's right!\n";
success = true;
break;
}
}
if (success)
break;
else
cout << "Try again!\n";
}
cout << "Bye\n";
return 0;
}
3.新编写程序清单10.7和程序清单10.8描述的Stock类,使之使用动态内存分配的内存,而不是string类对象来存储股票名称。另外,使用重载的operator<<()定义代替show()成员函数。再使用程序清单10.9测试新的定义程序。
3.1头文件stock123.h
#ifndef STOCK123_H_
#define STOCK123_H_
#pragma warning(disable:4996)
#include <iostream>
using std::ostream;
class Stock
{
private:
char* company;
int shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
Stock(); // default constructor
Stock(const char* co, long n = 0, double pr = 0.0);
~Stock();
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
friend ostream& operator<<(ostream& os, const Stock& st);
const Stock& topval(const Stock& s) const;
};
#endif // !STOCK123_H_
3.2类定义.cpp
#include <iostream>
#include "stock123.h"
#include <cstring>
using namespace std;
Stock::Stock()
{
company = new char[strlen("no name") + 1];
strcpy(company, "no name");
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
Stock::Stock(const char* co, long n, double pr)
{
company = new char[strlen(co) + 1];
strcpy(company, co);
if (n < 0)
{
cout << "Number of shares can't be negative; "
<< company << " shares set to 0.\n";
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
Stock::~Stock()
{
delete[] company;
}
void Stock::buy(long num, double price)
{
if (num < 0)
{
std::cout << "Number of shares purchased can't be negative. "
<< "Transaction is aborted.\n";
}
else
{
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(long num, double price)
{
if (num < 0)
{
cout << "Number of shares sold can't be negative. "
<< "Transaction is aborted.\n";
}
else if (num > shares)
{
cout << "You can't sell more than you have! "
<< "Transaction is aborted.\n";
}
else
{
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price)
{
share_val = price;
set_tot();
}
ostream& operator<<(ostream& os, const Stock& st)
{
ios_base::fmtflags orig =
os.setf(ios_base::fixed, ios_base::floatfield);
std::streamsize prec = os.precision(3);
os << "Company: " << st.company
<< " Shares: " << st.shares << '\n';
os << " Share Price: $" << st.share_val;
// set format to #.##
os.precision(2);
os << " Total Worth: $" << st.total_val << '\n';
// restore original format
os.setf(orig, ios_base::floatfield);
os.precision(prec);
return os;
}
const Stock& Stock::topval(const Stock& s) const
{
if (s.total_val > total_val)
return s;
else
return *this;
}
3.3测试类.cpp
#include <iostream>
#include "stock123.h"
const int STKS = 4;
int main()
{
{
// create an array of initialized objects
Stock stocks[STKS] = {
Stock("NanoSmart", 12, 20.0),
Stock("Boffo Objects", 200, 2.0),
Stock("Monolithic Obelisks", 130, 3.25),
Stock("Fleep Enterprises", 60, 6.5)
};
std::cout << "Stock holdings:\n";
int st;
for (st = 0; st < STKS; st++)
std::cout << stocks[st];
// set pointer to first element
const Stock* top = &stocks[0];
for (st = 1; st < STKS; st++)
top = &top->topval(stocks[st]);
// now top points to the most valuable holding
std::cout << "\nMost valuable holding:\n";
std::cout << *top; }
return 0;
}
4.请看下面程序清单10.10定义的Stack类的变量:
(……代码忽略……)
正如私有成员表明的,这个类使用动态内存分配的数组来保存栈项。请重新编写方法,以适应这种新的表示法,并编写一个程序来演示所有的方法,包括复制构造函数和赋值运算符。
4.1头文件stack.h
#ifndef STACK124_H_
#define STACK124_H_
typedef unsigned long Item;
class Stack
{
private:
enum { MAX = 10 }; // constant specific to class
Item* pitems; // holds stack items
int size;
int top; // index for top stack item
public:
Stack(int n = MAX);
Stack(const Stack& st);
~Stack();
bool isempty() const;
bool isfull() const;
// push() returns false if stack already is full, true otherwise
bool push(const Item& item); // add item to stack
// pop() returns false if stack already is empty, true otherwise
bool pop(Item& item); // pop top into item
Stack& operator=(const Stack& st);
};
#endif
4.2成员函数定义.cpp
#include <iostream>
#include "stack124.h"
Stack::Stack(int n)
{
pitems = new Item[n];
size = n;
top = 0;
}
Stack::Stack(const Stack& st)
{
size = st.size;
pitems = new Item[size];
for (int i = 0; i < size; i++)
{
pitems[i] = st.pitems[i];
}
top = st.top;
}
Stack::~Stack()
{
delete[] pitems;
}
bool Stack::isempty() const
{
return top == 0;
}
bool Stack::isfull() const
{
return top == MAX;
}
// push() returns false if stack already is full, true otherwise
bool Stack::push(const Item& item) // add item to stack
{
if (top < MAX)
{
pitems[top++] = item;
return true;
}
else
return false;
}
// pop() returns false if stack already is empty, true otherwise
bool Stack::pop(Item& item) // pop top into item
{
if (top > 0)
{
item = pitems[--top];
return true;
}
else
return false;
}
Stack& Stack::operator=(const Stack& st)
{
if (this == &st)
return *this;
delete[]pitems;
size = st.size;
pitems = new Item[size];
for (int i = 0; i < size; i++)
{
pitems[i] = st.pitems[i];
}
top = st.top;
return *this;
}
4.3 使用类.cpp
#include <iostream>
#include "stack124.h"
using namespace std;
int main(void)
{
Stack st1;
Stack st2;
Item p1[10] = { 12,20,3,0,2,2,3,5,8,9 };
for (int i = 0; i < 10; i++)
{
st2.push(p1[i]);
cout << p1[i]<<" ";
}
cout << endl;
cout << "Is st2 empty: " << st2.isempty() << endl;
cout << "Is st2 full: " << st2.isfull() << endl;
st1 = st2;
cout << "st1赋值后:" << endl;
cout << "Is st1 empty: " << st1.isempty() << endl;
cout << "Is st1 full: " << st1.isfull() << endl;
Stack st3(st2);
cout << "用st2构造st3后:" << endl;
cout << "Is st3 empty: " << st3.isempty() << endl;
cout << "Is st3 full: " << st3.isfull() << endl;
for (int i = 0; i < 10; i++)
{
st2.pop(p1[i]);
cout << p1[i] << " ";
}
cout << endl;
cout << "st2全pop后:" << endl;
cout << "Is st2 empty: " << st2.isempty() << endl;
cout << "Is st2 full: " << st2.isfull() << endl;
for (int i = 0; i < 6; i++)
{
st3.pop(p1[i]);
cout << p1[i] << " ";
}
cout << endl;
cout << "st3部分pop后:" << endl;
cout << "Is st3 empty: " << st3.isempty() << endl;
cout << "Is st3 full: " << st3.isfull() << endl;
system("pause");
return 0;
}
5.Heather银行进行的研究表明,ATM客户不希望排队时间不超过1分钟。使用程序清单12.10中的模拟,找出要使平均等候时间为1分钟,每小时到达的客户数应为多少(试验时间不短于100小时)?
6.Heather银行想知道,如果再开设一台ATM,情况将如何。请对模拟进行修改,以包含两个队列。假设当第一台ATM前的排队人数少于第二台ATM时,客户将排在第一队,否则将排在第二队。然后再找出要使平均等候时间为1分钟,每小时到达的客户数应该为多少(注意,这是一个非线性问题,即将ATM数量加倍,并不能保证每小时处理的客户数量也翻倍,并确保客户等候的时间少于1分钟)?
5.6不会不想做。参考https://www.manongdao.com/article-172261.html
第13章 类继承
1.
1.以下面的类声明为基础:
class Cd { //represents a CD disk
private:
char performers[50];
char label[20];
int selections; //number of selections
double playtime; //playing time in minute
public:
Cd(char* s1, char* s2, int n, double x);
Cd(const Cd& d);
Cd();
~Cd();
void Report() const; //reports all CD data
Cd& operator=(const Cd& d);
};派生出一个Classic类,并添加一组char成员,用于存储指出CD中主要作品的字符串。修改上述声明,使基类的搜有函数都是虚的。如果上述定义声明的某个方法并不需要,则请删除它。使用下面的程序测试您的产品:
#include<iostream>
using namespace std;
#include"cd131.h"void Bravo(const Cd& disk);
int main()
{
Cd c1("beatles", "Capitol", 14, 35.5);
Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17);
Cd* pcd = &c1;
cout << "Using object directly:\n";
c1.Report(); //use Cd method
c2.Report(); //use Classic method
cout << "Using type cd *pointer to objects:\n";
pcd->Report(); //use Cd method for cd object
pcd = &c2;
pcd->Report(); //use Classic method for classic object
cout << "Calling a function with a Cd reference argument:\n";
Bravo(c1);
Bravo(c2);
cout << "Testing assignment: ";
Classic copy;
copy = c2;
copy.Report();
return 0;
}void Bravo(const Cd& disk)
{
disk.Report();
}
答:
1.1头文件cd131.h
#ifndef CD131_H_
#define CD131_H_
#pragma warning(disable:4996)
class Cd { //represents a CD disk
private:
char performers[50];
char label[20];
int selections; //number of selections
double playtime; //playing time in minute
public:
Cd(const char * s1,const char* s2, int n, double x);
Cd(const Cd& d);
Cd();
virtual ~Cd();
virtual void Report() const; //reports all CD data
virtual Cd& operator=(const Cd& d);
};
class Classic : public Cd
{
private:
char mainworks[50];
public:
Classic(const char* m,const char* s1,const char* s2, int n, double x);
Classic(const char* m,const Cd& rs);
Classic();
virtual ~Classic();
virtual void Report() const;
virtual Classic& operator=(const Classic& d);
};
#endif // !CD131_H_
1.2类函数定义.cpp
#include "cd131.h"
#include <iostream>
using namespace std;
#include <cstring>
#include <cstdlib>
Cd::Cd(const char* s1,const char* s2, int n, double x)
{
strncpy(performers, s1,49);
performers[49] = '\0';
strncpy(label, s2, 19);
label[19] = '\0';
selections = n;
playtime = x;
}
Cd::Cd(const Cd& d)
{
strncpy(performers, d.performers, 49);
performers[49] = '\0';
strncpy(label, d.performers, 19);
label[19] = '\0';
selections = d.selections;
playtime = d.playtime;
}
Cd::Cd()
{
strcpy(performers,"null");
strcpy(label,"null");
selections = 0;
playtime = 0.0;
}
Cd::~Cd()
{
}
void Cd::Report() const //reports all CD data
{
cout << "Performers: " << performers << endl;
cout << "Label: " << label << endl;
cout << "There are " << selections << " selections and lasts " << playtime << " minutes.\n";
}
Cd& Cd::operator=(const Cd& d)
{
strncpy(performers, d.performers, 49);
performers[49] = '\0';
strncpy(label, d.performers, 19);
label[19] = '\0';
selections = d.selections;
playtime = d.playtime;
return *this;
}
Classic::Classic(const char* m, const char* s1,const char* s2, int n, double x):Cd(s1, s2, n, x)
{
strncpy(mainworks,m, 49);
mainworks[49] = '\0';
}
Classic::Classic(const char* m,const Cd& rs) : Cd(rs)
{
strncpy(mainworks, m, 49);
mainworks[49] = '\0';
}
Classic::Classic() : Cd()
{
strcpy(mainworks,"null");
}
Classic::~Classic()
{
}
void Classic::Report() const
{
Cd::Report();
cout << "The main works of this disk are " << mainworks << endl;
}
Classic& Classic::operator=(const Classic& d)
{
if (this == &d)
return *this;
Cd::operator=(d);
strncpy(mainworks, d.mainworks,49);
mainworks[49] = '\0';
return *this;
}
1.3测试类.cpp
#include<iostream>
using namespace std;
#include"cd131.h" //which will contain #include cd.h
void Bravo(const Cd& disk);
int main()
{
Cd c1("beatles", "Capitol", 14, 35.5);
Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17);
Cd* pcd = &c1;
cout << "Using object directly:\n";
c1.Report(); //use Cd method
c2.Report(); //use Classic method
cout << "Using type cd *pointer to objects:\n";
pcd->Report(); //use Cd method for cd object
pcd = &c2;
pcd->Report(); //use Classic method for classic object
cout << "Calling a function with a Cd reference argument:\n";
Bravo(c1);
Bravo(c2);
cout << "Testing assignment: ";
Classic copy;
copy = c2;
copy.Report();
return 0;
}
void Bravo(const Cd& disk)
{
disk.Report();
}
2..完成练习1,但让两个类使用动态内存分配而不是长度固定的数组来记录字符串。
答:
2.1头文件“cd132.h”(与上题相比,仅仅把数组改成指针形式)
#ifndef CD132_H_
#define CD132_H_
#pragma warning(disable:4996)
class Cd { //represents a CD disk
private:
char* performers;
char* label;
int selections; //number of selections
double playtime; //playing time in minute
public:
Cd(const char* s1, const char* s2, int n, double x);
Cd(const Cd& d);
Cd();
virtual ~Cd();
virtual void Report() const; //reports all CD data
virtual Cd& operator=(const Cd& d);
};
class Classic : public Cd
{
private:
char* mainworks;
public:
Classic(const char* m, const char* s1, const char* s2, int n, double x);
Classic(const char* m, const Cd& rs);
Classic();
virtual ~Classic();
virtual void Report() const;
virtual Classic& operator=(const Classic& d);
};
#endif // !CD131_H_
2.2类函数定义.cpp(有变化)
#include "cd132.h"
#include <iostream>
using namespace std;
#include <cstring>
#include <cstdlib>
Cd::Cd(const char* s1, const char* s2, int n, double x)
{
performers = new char[strlen(s1) + 1];
strcpy(performers, s1);
label = new char[strlen(s2) + 1];
strcpy(label, s2);
selections = n;
playtime = x;
}
Cd::Cd(const Cd& d)
{
performers = new char[strlen(d.performers) + 1];
strcpy(performers, d.performers);
label = new char[strlen(d.label) + 1];
strcpy(label, d.label);
selections = d.selections;
playtime = d.playtime;
}
Cd::Cd()
{
performers = new char[5];
strcpy(performers, "null");
label = new char[5];
strcpy(label, "null");
selections = 0;
playtime = 0.0;
}
Cd::~Cd()
{
delete[] performers;
delete[] label;
}
void Cd::Report() const //reports all CD data
{
cout << "Performers: " << performers << endl;
cout << "Label: " << label << endl;
cout << "There are " << selections << " selections and lasts " << playtime << " minutes.\n";
}
Cd& Cd::operator=(const Cd& d)
{
performers = new char[strlen(d.performers) + 1];
strcpy(performers, d.performers);
label = new char[strlen(d.label) + 1];
strcpy(label, d.label);
selections = d.selections;
playtime = d.playtime;
return *this;
}
Classic::Classic(const char* m, const char* s1, const char* s2, int n, double x) :Cd(s1, s2, n, x)
{
mainworks = new char[strlen(m) + 1];
strcpy(mainworks, m);
}
Classic::Classic(const char* m, const Cd& rs) : Cd(rs)
{
mainworks = new char[strlen(m) + 1];
strcpy(mainworks, m);
}
Classic::Classic() : Cd()
{
mainworks = new char[5];
strcpy(mainworks, "null");
}
Classic::~Classic()
{
delete[] mainworks;
}
void Classic::Report() const
{
Cd::Report();
cout << "The main works of this disk are " << mainworks << endl;
}
Classic& Classic::operator=(const Classic& d)
{
if (this == &d)
return *this;
Cd::operator=(d);
mainworks = new char[strlen(d.mainworks) + 1];
strcpy(mainworks, d.mainworks);
return *this;
}
2.3类测试.cpp(与上题相同,无变化)
#include<iostream>
using namespace std;
#include"cd132.h" //which will contain #include cd.h
void Bravo(const Cd& disk);
int main()
{
Cd c1("beatles", "Capitol", 14, 35.5);
Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17);
Cd* pcd = &c1;
cout << "Using object directly:\n";
c1.Report(); //use Cd method
c2.Report(); //use Classic method
cout << "Using type cd *pointer to objects:\n";
pcd->Report(); //use Cd method for cd object
pcd = &c2;
pcd->Report(); //use Classic method for classic object
cout << "Calling a function with a Cd reference argument:\n";
Bravo(c1);
Bravo(c2);
cout << "Testing assignment: ";
Classic copy;
copy = c2;
copy.Report();
return 0;
}
void Bravo(const Cd& disk)
{
disk.Report();
}
3.修改baseDMA-lacksDMA-hasDMA类层次,让三个类都从一个ABC派生而来,然后使用与程序清单13.10相似的程序对结果进行测试。也就是说,它应使用ABC指针数组,并让用户决定要创建的对象类型。在类定义中添加virtual View()方法以处理数据显示。
答:
3.1头文件dma133.h
#ifndef ABC133_H_
#define ABC133_H_
#include <iostream>
#pragma warning(disable:4996)
class ABC
{
public:
ABC() {};
~ABC() {};
virtual void View() = 0;
};
//Baseclass using DMA
class baseDMA:public ABC
{
private:
char* label;
int rating;
public:
baseDMA(const char* l = "null", int r = 0);
baseDMA(const baseDMA& rs);
virtual ~baseDMA();
baseDMA& operator=(const baseDMA& rs);
friend std::ostream& operator<<(std::ostream& os, const baseDMA& rs);
virtual void View();
};
class lacksDMA :public baseDMA
{
private:
enum { COL_LEN = 40 };
char color[COL_LEN];
public:
lacksDMA(const char* c = "blank", const char* l = "null", int r = 0);
lacksDMA(const char* c, const baseDMA& rs);
friend std::ostream& operator<<(std::ostream& os, const lacksDMA& rs);
virtual void View();
};
class hasDMA :public baseDMA
{
private:
char* style;
public:
hasDMA(const char* s = "none", const char* l = "null", int r = 0);
hasDMA(const char* s, const baseDMA& rs);
hasDMA(const hasDMA& hs);
~hasDMA();
hasDMA& operator= (const hasDMA& hs);
friend std::ostream& operator<<(std::ostream& os, const hasDMA& hs);
virtual void View();
};
#endif // ! ABC
3.2类成员函数定义.cpp
#include "ABC133.h"
#include <cstring>
//Baseclass methods
baseDMA::baseDMA(const char* l, int r)
{
label = new char[std::strlen(l) + 1];
std::strcpy(label, l);
rating = r;
}
baseDMA::baseDMA(const baseDMA& rs)
{
label = new char[std::strlen(rs.label) + 1];
std::strcpy(label, rs.label);
rating = rs.rating;
}
baseDMA::~baseDMA()
{
delete[] label;
}
baseDMA& baseDMA::operator=(const baseDMA& rs)
{
if (this == &rs)
return *this;
delete[] label;
label = new char[std::strlen(rs.label) + 1];
strcpy(label, rs.label);
rating = rs.rating;
return *this;
}
std::ostream& operator<<(std::ostream& os, const baseDMA& rs)
{
os << "Label: " << rs.label << std::endl;
os << "Rating: " << rs.rating << std::endl;
return os;
}
void baseDMA::View()
{
std::cout<< "Label: " << label << std::endl;
std::cout<< "Rating: " << rating << std::endl;
}
//lacksDMA methods
lacksDMA::lacksDMA(const char* c, const char* l, int r) :baseDMA(l, r)
{
std::strncpy(color, c, 39); //用于指定长度的字符串赋值到字符数组中
color[39] = '\0';
}
lacksDMA::lacksDMA(const char* c, const baseDMA& rs) : baseDMA(rs)
{
std::strncpy(color, c, COL_LEN - 1);
color[COL_LEN - 1] = '\0';
}
std::ostream& operator<<(std::ostream& os, const lacksDMA& ls)
{
os << (const baseDMA&)ls;
os << "Color: " << ls.color << std::endl;
return os;
}
void lacksDMA::View()
{
baseDMA::View();
std::cout << "Color: " <<color <<std:: endl;
}
//hasDMA mmethods
hasDMA::hasDMA(const char* s, const char* l, int r) :baseDMA(l, r)
{
style = new char[std::strlen(s) + 1];
std::strcpy(style, s);
}
hasDMA::hasDMA(const char* s, const baseDMA& rs) : baseDMA(rs)
{
style = new char[std::strlen(s) + 1];
std::strcpy(style, s);
}
hasDMA::hasDMA(const hasDMA& hs) : baseDMA(hs)
{
style = new char[std::strlen(hs.style) + 1];
std::strcpy(style, hs.style);
}
hasDMA::~hasDMA()
{
delete[]style;
}
hasDMA& hasDMA::operator= (const hasDMA& hs)
{
if (this == &hs)
return *this;
baseDMA::operator=(hs);
delete[]style;
style = new char[std::strlen(hs.style) + 1];
std::strcpy(style, hs.style);
return *this;
}
std::ostream& operator<<(std::ostream& os, const hasDMA& hs)
{
os << (const baseDMA&)hs;
os << "Style: " << hs.style << std::endl;
return os;
}
void hasDMA::View()
{
baseDMA::View();
std::cout << "Style: " << style << std::endl;
}
3.3测试类.cpp
#include <iostream>
#include <string>
#include "ABC133.h"
using namespace std;
const int DMA = 6;
int main(void)
{
using std::cin;
using std::cout;
using std::endl;
ABC * p_dma[DMA];
char *templabel = new char[50];
int temprating;
char kind;
for (int i = 0; i < DMA; i++)
{
cout << "Enter label: ";
cin.getline(templabel, 50);
cout << "Enter rating: ";
cin >> temprating;
cout << "Enter 1 for baseDMA or 2 for lacksDMA or 3 for hasDMA: ";
while (cin >> kind && kind != '1' && kind != '2' && kind!='3')
cout << "Enter either 1 or 2 or 3: ";
cin.ignore(); //这里很重要,墨迹了好久才解决呜呜,长记性啊!!!
if (kind == '1')
{
p_dma[i] = new baseDMA(templabel, temprating);
}
else if(kind == '2')
{
char tempcolor[40];
cout << "Enter color: ";
cin.getline(tempcolor, 40);
p_dma[i] = new lacksDMA(tempcolor,templabel, temprating);
}
else
{
char *tempstyle = new char[20];
cout << "Enter style: ";
cin.getline(tempstyle, 20);
p_dma[i] = new hasDMA(tempstyle, templabel, temprating);
}
while (cin.get() != '\n')
continue;
}
cout << endl;
for (int i = 0; i < DMA; i++)
{
p_dma[i]->View();
cout << endl;
}
for (int i = 0; i < DMA; i++)
{
delete p_dma[i];
}
cout << "Done.\n" << endl;
system("pause");
return 0;
}
4.
4.Benevolent Order of Programmers用来维护瓶装葡萄酒箱。为描述它,BOP Portmaster设置了一个Port类,并声明如下:
#include<iostream>
using namespace std;
class Port
{
private:
char* brand;
char style[20]; //i.e., tawny, ruby, vintage
int bottles;public:
Port(const char* br = "none", const char* st = "none", int b = 0);
Port(const Port& p); //copy constructor
virtual ~Port() { delete[] brand; }
Port& operator=(const Port& p);
Port& operator+=(int b); //add b to bottles
Port& operator-=(int b); //subtracts b from bottles , if available
int BottleCount() const { return bottles; }
virtual void Show() const;
friend ostream& operator<<(ostream & os, const Port & p);
};
show()方法按下面的格式显示信息:
Brand : Gallo
Kind : tawny
Bottles : 20operator<<()函数按下面的格式显示信息(末尾没有换行符):
Gallo, tawny, 20
PortMaster完成了Port类的方法定义后派生了VintagePort类,然后被解职——因为不小心将一瓶45度Cockburn泼到了正在准备烤肉调料的人身上,VintagePort类如下显示:
class VintagePort : public Port //style necessarily = "vintage"
{
private:
char* nickname; //i.e. , "The Noble" or "Old Velvet", etc.
int year; //vintage year
public:
VintagePort();
VintagePort(const char* br, const char* st, int b, const char* nn, int y);
VintagePort(const VintagePort& vp);
~VintagePort() { delete[] nickname; }
VintagePort& operator = (const VintagePort& vp);
void show() const;
friend ostream& operator <<(ostream& os, const VintagePort& vp);
};
您被制定指定负责完成VintagePort。
a.第一个任务是重新创建Port方法定义,因为前任被开除时销毁了方法定义。
b.第二个任务是解释为什么有的方法重新定义了,而有些没有重新定义。
c.第三个任务解释为何没有将operator = () 和operator << ()声明为虚的。
d.第四个任务是提供VintagePort中各个方法的定义。
答:
a.第一个任务是重新创建Port方法定义,因为前任被开除时销毁了方法定义。
Port::Port(const char* br, const char* st, int b )
{
brand = new char[strlen(br) + 1];
strcpy(brand, br);
strcpy(style, st);
bottles = b;
}
Port::Port(const Port& p) //copy constructor
{
brand = new char[strlen(p.brand) + 1];
strcpy(brand, p.brand);
strcpy(style, p.style);
bottles = p.bottles;
}
Port& Port::operator=(const Port& p)
{
if (this == &p)
return *this;
delete[]brand;
brand = new char[strlen(p.brand) + 1];
strcpy(brand, p.brand);
strcpy(style, p.style);
bottles = p.bottles;
return *this;
}
Port& Port::operator+=(int b)//add b to bottles
{
bottles += b;
return *this;
}
Port& Port::operator-=(int b) //subtracts b from bottles , if available
{
bottles -= b;
return *this;
}
void Port::Show() const
{
cout << "Brand: " << brand << endl;
cout << "Kind: " << style << endl;
cout << "Bottles: " << bottles << endl;
}
ostream& operator<<(ostream& os, const Port& p)
{
os << p.brand << "," << p.style << ","<<p.bottles;
}
b.第二个任务是解释为什么有的方法重新定义了,而有些没有重新定义。
当派生类成员函数需要处理派生类独有的成员变量时,需要重新定义方法,如果不需要处理派生类独有的成员变量,直接调用基类的方法即可。
c.第三个任务解释为何没有将operator = () 和operator << ()声明为虚的。
a).如果要在派生类中重新定义基类的方法,则将它设置为虚方法。但是基类的operator = () 和派生类的operator = () 形参不一样,根本不是一个类方法,不存在重新定义的问题,因从也不必声明为虚的。
b).operator<<()函数是友元函数,友元函数不能是虚函数,因为友元不是类成员,而只有类成员才能是虚函数。
d.第四个任务是提供VintagePort中各个方法的定义。
VintagePort::VintagePort():Port()
{
}
VintagePort::VintagePort(const char* br, const char* st, int b, const char* nn, int y)
: Port(br, st, b)
{
nickname = new char[strlen(nn) + 1];
strcpy(nickname, nn);
int year = y;
}
VintagePort::VintagePort(const VintagePort& vp):Port(vp)
{
nickname = new char[strlen(vp.nickname) + 1];
strcpy(nickname, vp.nickname);
int year = vp.year;
}
VintagePort& VintagePort::operator = (const VintagePort& vp)
{
if (this == &vp)
return *this;
Port::operator=(vp);
delete[]nickname;
nickname = new char[strlen(vp.nickname) + 1];
strcpy(nickname, vp.nickname);
strcpy(nickname, vp.nickname);
year = vp.year;
return *this;
}
void VintagePort::show() const
{
Port::Show();
cout << "nickname: " << nickname << endl;
cout << "year: " << year << endl;
}
ostream& operator <<(ostream& os, const VintagePort& vp)
{
os << (const Port&)vp;
os << vp.nickname << "," << vp.year ;
return os;
}
第14章 C++中的代码重用
1.
1.Wine类有一个string类对象成员(参见第4章)和一个Pair对象(参见本章):其中前者用来存储葡萄酒的名称,而后者有2个valarry<int>对象(参见本章),这两个valarry<int>对象分别保存了葡萄酒的酿造年份和该年生产的瓶数。例如,Pair的第1个valarray<int>对象可能为1988、1992和1996,第二个valarry<int> 对象可能为24、48和144瓶。Wine最好有1个int成员用于存储年数。另外,一些typedef可能有助于简化编程工作:
这样,PairArray表示的类型是Pair<std::valarry<int>,std::valarray<int>>。使用包含来实现Wine类,并用一个简单的程序对其进行测试。Wine类应该有一个默认构造函数以及如下的构造函数:typedef std::valarry<int> ArrayInt; typedef Pair<ArrayInt, ArrayInt> PairArray;
Wine类应该有一个GetBottles()方法,它根据Wine对象能够存储集中年份(y),提示用户输入年份和瓶数。方法Label()返回一个指向葡萄酒名称的引用。sum()方法返回Pair对象中第二个valarray<int>对象中的瓶数总和。Wine(const char* l, int y, const int yr[], ocnst int bot[]); Wine(const char* l, int y);
测试程序应提示用户输入葡萄酒名称、元素个数以及每个元素存储的年份和瓶数等信息。程序将使用这些数据来构造一个Wine对象,然后显示对象中保存的信息。
下面是一个简单的测试程序:
int main()
下面是该程序的运行情况:{ cout << "Enter name of wine: "; char lab[50]; cin.getline(lab, 50); cout << "Enter number of years: "; int yrs; cin >> yrs; Wine holding(lab, yrs); holding.GetBottles(); holding.Show(); const int YRS = 3; int y[YRS] = {1993, 1995, 1998}; int b[YRS] = {48, 60, 72}; Wine more("Gushing Grape Red", YRS, y, b); more.Show(); cout << "Total bottle for " << more.Label() <<": " << more.sum() << endl; cout << "Bye\n"; return 0; }
Enter name of wine: Gully Wash
Enter number of years: 4
Enter Gully Wash data for 4 year(s):
Enter year: 1988
Enter bottles for that year: 42
Enter year: 1994
Enter bottles for that year: 58
Enter year: 1998
Enter bottles for that year: 122
Enter year: 2001
Enter bottles for that year: 144
Wine: Gully Wash
Year Bottles
1988 42
1994 58
1998 122
2001 144
Wine: Gushing Grape Red
Year Bottles
1993 48
1995 60
1998 72
Total bottle for Gushing Grape Red: 180
Bye
答:
1.1头文件winec.h
#ifndef WINEC141_H_
#define WINEC141_H_
#include <iostream>
#include <string>
#include <valarray>
template<class T1,class T2>
class Pair
{
private:
T1 a;
T2 b;
public:
Pair(const T1& aval, const T2& bval) :a(aval), b(bval) {}
Pair() {}
void set(const T1& yr, const T2& bot);
int sum() const;
void Show(int y) const;
};
typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArray;
class Wine
{
private:
std::string name;
PairArray b;
int yrs;
public:
Wine(const char* l, int y, const int yr[], const int bot[]);
Wine(const char* l, int y);
void GetBottles();
std::string& Label();
int sum()const;
void Show()const;
};
#endif // !WINEC141_H_
1.2wine.cpp
#include <iostream>
#include "winec141.h"
#include <string>
#include <valarray>
using namespace std;
template<class T1,class T2>
void Pair<T1, T2>::set(const T1& yr, const T2& bot)
{
a = yr;
b = bot;
}
template<class T1, class T2>
int Pair<T1, T2>::sum() const
{
return b.sum();
}
template<class T1, class T2>
void Pair<T1, T2>::Show(int y) const
{
for (int i = 0; i < y; i++)
{
cout << "\t\t" << a[i] << "\t\t" << b[i] << endl;
}
}
Wine::Wine(const char* l, int y, const int yr[], const int bot[])
{
name = l;
yrs = y;
b.set(ArrayInt(yr, yrs), ArrayInt(bot, yrs));
}
Wine::Wine(const char* l, int y)
{
name = l;
yrs = y;
}
void Wine::GetBottles()
{
ArrayInt yr(yrs), bot(yrs);
cout << "Enter" << name << " data for " << yrs << " year(s):\n";
for (int i = 0; i < yrs; i++)
{
cout << "Enter year: ";
cin >> yr[i];
cout << "Enter bottles for that year: ";
cin >> bot[i];
}
b.set(yr, bot);
}
std::string& Wine::Label()
{
return name;
}
int Wine::sum()const
{
return b.sum();
}
void Wine::Show()const
{
cout << "Wine: " << name << endl;
cout << "\t\tYear\t\tBottles\n";
b.Show(yrs);
}
1.3usewine.cpp
#include "winec141.h"
#include <iostream>
int main()
{
using std::cin;
using std::endl;
using std::cout;
cout << "Enter name of wine: ";
char lab[50];
cin.getline(lab, 50);
cout << "Enter number of years: ";
int yrs;
cin >> yrs;
Wine holding(lab, yrs);
holding.GetBottles();
holding.Show();
const int YRS = 3;
int y[YRS] = { 1993, 1995, 1998 };
int b[YRS] = { 48, 60, 72 };
Wine more("Gushing Grape Red", YRS, y, b);
more.Show();
cout << "Total bottle for " << more.Label()
<< ": " << more.sum() << endl;
cout << "Bye\n";
return 0;
}
2.
2.采用私有继承而不是包含来完成编程练习1.同样,一些typedef可能会有所帮助,另外,您可能还需要考虑诸如下面这样的语句的含义:
PairArray::operator=(PairArray(ArrayInt(), ArrayInt())); cout << (const string&)(*this);
您设计的类应该可以使用编程练习1中的测试程序进行测试。
答:
2.1头文件winep142.h
#ifndef WINEP142_H
#define WINEP142_H
#include <iostream>
#include <string>
#include <valarray>
template<class T1,class T2>
class Pair
{
private:
T1 a;
T2 b;
public:
Pair(const T1& aval, const T2& bval) :a(aval), b(bval) {}
Pair() {}
void set(const T1& yr, const T2& bot);
int sum() const;
void Show(int y) const;
};
typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArray;
class Wine : private std::string, private PairArray
{
private:
int yrs;
public:
Wine(const char* l,int y,const int yr[],const int bot[]);
Wine(const char* l,int y);
void GetBottles();
std::string& Label();
int sum() const;
void Show() const;
};
#endif // !WINEP_142_H
2.2winep.cpp
#include "winep142.h"
#include <iostream>
#include <string>
#include <valarray>
using std::cin;
using std::cout;
using std::string;
using std::endl;
template<class T1, class T2>
void Pair<T1, T2>::set(const T1& yr, const T2& bot)
{
a = yr;
b = bot;
}
template<class T1, class T2>
int Pair<T1, T2>::sum() const
{
return b.sum();
}
template<class T1, class T2>
void Pair<T1, T2>::Show(int y) const
{
for (int i = 0; i < y; i++)
{
cout << "\t\t" << a[i] << "\t\t" << b[i] << endl;
}
}
Wine::Wine(const char* l, int y, const int yr[], const int bot[]):
string(l), yrs(y), PairArray(ArrayInt(yr, yrs), ArrayInt(bot, yrs))
{
}
Wine::Wine(const char* l, int y):string(l),yrs(y)
{
}
void Wine::GetBottles()
{
ArrayInt yr(yrs), bot(yrs);
cout << "Enter" << (const string&)(*this) << " data for " << yrs << " year(s):\n";
for (int i = 0; i < yrs; i++)
{
cout << "Enter year: ";
cin >> yr[i];
cout << "Enter bottles for that year: ";
cin >> bot[i];
}
PairArray::set(yr, bot);
}
std::string& Wine::Label()
{
return (string&)(*this);
}
int Wine::sum() const
{
return PairArray::sum();
}
void Wine::Show() const
{
cout << "Wine: " << (const string&)(*this) << std::endl;
cout << "\t\tYear\t\tBottles\n";
PairArray::Show(yrs);
}
2.3usewinep.cpp
#include "winep142.h"
#include <iostream>
int main()
{
using std::cin;
using std::endl;
using std::cout;
cout << "Enter name of wine: ";
char lab[50];
cin.getline(lab, 50);
cout << "Enter number of years: ";
int yrs;
cin >> yrs;
Wine holding(lab, yrs);
holding.GetBottles();
holding.Show();
const int YRS = 3;
int y[YRS] = { 1993, 1995, 1998 };
int b[YRS] = { 48, 60, 72 };
Wine more("Gushing Grape Red", YRS, y, b);
more.Show();
cout << "Total bottle for " << more.Label()
<< ": " << more.sum() << endl;
cout << "Bye\n";
return 0;
}
3.
3.定义一个QueueTp模板。然后在一个类似于程序清单14.12的程序中创建一个指向Worker的指针队列(参见程序清单14.10中的定义),并使用该队列来测试它。
4.
4.Person类保存人的名和姓。除构造函数外,它还有Show()方法,用于显示名和姓。Gunslmger类以Person类为虚基类派生而来,它包含一个Draw()成员,该方法返回一个double值,表示枪手的拔枪时间。这个类还包含一个int成员,表示枪手枪上的刻痕数。最后,这个类还包含一个Show()函数,用于显示所有这些信息。
PokerPlayer类以Person类为虚基类派生而来。它包含一个Draw()成员,该函数返回一个1~52的随机数,用于扑克牌的值(也可以用定义一个Card类,其中包含花色和面值成员,然后让Draw()返回一个Card对象)。PokerPlayer类使用Person类的show()函数。BadDude()类从Gunslinger何PokerPlayer类公有派生而来。它包含Gdraw()成员(返回坏蛋拔枪时间)和Cdraw()成员(返回下一张扑克牌),另外还有一个合适的show()函数。请定义这些类和方法以及其他必要的方法(如用于设置对象值的方法),并使用一些类似程序清单14.12的简单程序对它们进行测试。
5.
5.下面是一些类声明:
注意,该类层次结构使用了带虚基类的MI,所以要牢记这种情况下用于构造函数初始化列表的特殊规则。还需要注意的是,有些方法被声明为保护的。这可以简化一些HighFink方法的代码(例如,如果HightFink::showAll()只是调用Fink::showAll()和Manager::showAll(),则它将调用abstr_emp::ShowAll()两次)。提供类方法的实现,并在一个程序中对这些类进行测试。下面是一个小型测试程序:class AbstrEmp { private: string _fname; string _lname; string _job; public: AbstrEmp(); AbstrEmp(const std::string& fn, const string& ln, const string& j); virtual void showAll()const; virtual void setAll(); friend ostream& operator<<(ostream& os, const AbstrEmp& e); virtual ~AbstrEmp() = 0; }; class Employee : public AbstrEmp { public: Employee(); Employee(const string& fn, const string& ln, const string& j); virtual void showAll()const; virtual void setAll(); }; class Manager : virtual public AbstrEmp { private: int _inchargeof; protected: int inChargeOf()const { return _inchargeof; } int& inChargeOf() { return _inchargeof; } public: Manager(); Manager(const string& fn, const string& ln, const string& j0, int ico = 0); Manager(const AbstrEmp& e, int ico); Manager(const Manager& m); virtual void showAll()const; virtual void setAll(); }; class Fink : virtual public AbstrEmp { private: string _reportsto; protected: const string reportsTo() const{ return _reportsto; } string& reportsTo(){ return _reportsto; } public: Fink(); Fink(const string& fn, const string& ln, const string& j, const string& rpo); Fink(const AbstrEmp& e, const string& rpo); Fink(const Fink& e); virtual void showAll()const; virtual void setAll(); }; class HighFink: public Manager, public Fink { public: HighFink(); HighFink(const string& fn, const string& ln, const string& j, const string& rpo, int ico); HighFink(const AbstrEmp& e, const string& rpo, int ico); HighFink(const Fink& f, int ico); HighFink(const Manager& m, const string& rpo); HighFink(const HighFink& h); virtual void showAll()const; virtual void setAll(); };
#include <iostream> #include "Test.h" #include <string> using namespace std; using namespace FableGame; int main(int argc, const char * argv[]) { Employee em("Trip", "Harris", "Thumper"); cout << em << endl; em.showAll(); Manager ma("Amorphia", "Spindragon", "Nuancer", 5); cout << ma << endl; ma.showAll(); Fink fi("Matt", "Oggs", "Oiler", "Juno Barr"); cout << fi << endl; fi.showAll(); HighFink hf(ma, "Curly Kew"); hf.showAll(); cout << "Press a key for next phase:\n"; cin.get(); HighFink hf2; hf2.setAll(); cout << "Using an abstr_emp * pointer:\n"; AbstrEmp* tri[4] = { &em, &fi, &hf, &hf2 }; for (int i = 0; i < 4; ++i) { tri[i]->showAll(); } return 0; }
为什么没有定义赋值运算符?
为什么要将ShowAll()和SetAll()定义为虚的?
为什么要将abstr_emp定义为虚基类?
为什么highfink类没有数据部分?
为什么只需一个operator << ()版本?
如果使用下面的代码替换程序的结尾部分,将会发生什么情况?abstr_emp str[4] = {em, fi, hf, hf2}; for(int i = 0; i < 4; ++i) tr[i].showAll()