当前位置:   article > 正文

C++primer plus编程练习参考答案_c++ primer plus 答案

c++ primer plus 答案

目录

第2章 开始学习C++

第3章 处理数据

第4章 复合类型

第5章 循环和关系表达式

第6章 分支语句和逻辑运算符

第7章 函数C++编程模块

第8章 函数探幽

第9章 内存模型和名称空间

第10章 对象和类

第11章 使用类

第12章 类和动态内存分配

第13章 类继承

第14章 C++中的代码重用


第2章 开始学习C++

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

  1. #include<iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. string name;
  6. string address;
  7. cout << "请输入您的姓名:" << endl;
  8. cin >> name;
  9. cout << "请输入您的地址:" << endl;
  10. cin >> address;
  11. cout << "您的姓名是:" <<name<< endl;
  12. cout << "您的地址是:" <<address<<endl;
  13. system("pause");
  14. return 0;
  15. }


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

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. double distence;
  6. cout << "请输入一个距离(单位:long):" << endl;
  7. cin >> distence;
  8. cout << "您输入的距离为 " << distence << " long," << "即 " << 220 * distence << " 码" << endl;
  9. system("pause");
  10. return 0;
  11. }

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

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

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

  1. #include <iostream>
  2. using namespace std;
  3. void print1(void)
  4. {
  5. cout << "Three blind mice" << endl;
  6. }
  7. void print2(void)
  8. {
  9. cout << "See how they run" << endl;
  10. }
  11. int main(void)
  12. {
  13. print1();
  14. print1();
  15. print2();
  16. print2();
  17. system("pause");
  18. return 0;
  19. }

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

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. int age;
  6. cout << "Enter your age:" << endl;
  7. cin >> age;
  8. cout << "your age cintains " << age * 12 << "months" << endl;
  9. system("pause");
  10. return 0;
  11. }

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

下面是转换公式:

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

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. double value;
  6. cout << "please, enter a Celsius value :" << endl;
  7. cin >> value;
  8. cout << value << " degrees Celsius is " << 1.8 * value + 32.0 << " degrees Fahrenheit" << endl;
  9. system("pause");
  10. return 0;
  11. }

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天文单位

  1. #include <iostream>
  2. using namespace std;
  3. double convert(double L_Y)
  4. {
  5. return L_Y * 63240;
  6. }
  7. int main(void)
  8. {
  9. double L_Y = 0;//光年值
  10. cout << "Enter the number of light years :";
  11. cin >> L_Y;
  12. int ast = convert(L_Y);
  13. cout << L_Y << " light years = " <<ast << " astronomical units." << endl;
  14. system("pause");
  15. return 0;
  16. }

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

  1. #include <iostream>
  2. using namespace std;
  3. void print(int hours, int minutes)
  4. {
  5. cout <<"Time: "<< hours<<":"<<minutes << endl;
  6. }
  7. int main(void)
  8. {
  9. int hours = 0;
  10. int minutes = 0;
  11. cout << "Enter the number of hours :";
  12. cin >> hours;
  13. cout << "Enter the number of minutes :";
  14. cin >> minutes;
  15. print(hours, minutes);
  16. system("pause");
  17. return 0;
  18. }

第3章 处理数据

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

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. //1 英尺=12 英寸
  6. const int convert_factor = 12;
  7. int height_inches = 0;
  8. cout << "Please enter your height (in inches):";
  9. cin >> height_inches;
  10. cout << "your height is " << height_inches / 12 << " foot and " << height_inches % 12 << " inches" << endl;
  11. system("pause");
  12. return 0;
  13. }

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

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. //以几英尺几英寸的方式输入其身高,并以磅为单位输入其体重。
  6. int height_foot;
  7. float height_inches, weight_pounds;
  8. cout << "Enter your height (in foot):";
  9. cin >> height_foot;
  10. cout << "And enter your height (in inches):";
  11. cin >> height_inches;
  12. cout << "Enter your weight(in pound):";
  13. cin >> weight_pounds;
  14. cout << "So you are " << height_foot << " foot and " << height_inches
  15. << " inches height and " << weight_pounds << " pounds weight." << endl;
  16. //以英寸的方式指出用户的身高(1英尺为12英寸)
  17. const int foot_inches = 12;
  18. float convert_to_inches;
  19. convert_to_inches = 12 * height_foot + height_inches;
  20. cout << "Your height is " << convert_to_inches << " inches" << endl;
  21. //以英寸为单位的身高转换为以米为单位的身高(1英寸 = 0.0254米)
  22. const float inches_to_meters = 0.0254;
  23. float height_meters = convert_to_inches * inches_to_meters;
  24. cout << "Your height is " << height_meters << " meters" << endl;
  25. //将以磅为单位的体重转换为以千克为单位的体重(1千克 = 2.2磅)
  26. const float kg_to_pounds = 2.2;
  27. float weight_kg = weight_pounds / kg_to_pounds;
  28. cout << "Your weight is " << weight_kg << " kg." << endl;
  29. //计算相应的BMI——体重(千克)除以身高(米)的平方。
  30. float BMI = weight_kg / pow(height_meters, 2);
  31. cout << "Your BMI is " << BMI << "!" << endl;
  32. system("pause");
  33. return 0;
  34. }

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. //1度为60分,1分等于60秒,请以符号常量的方式表示这些值。
  2. //对于每个输入值, 应使用一个独立的变量存储它。下面是该程序运行时的情况:
  3. //
  4. //
  5. // First, enter the degrees : 37
  6. // Next, enter the minutes of arc : 51
  7. //
  8. // Finally, enter the seconds of arc : 19
  9. // 37 degrees, 51 minutes, 19 seconds = 37.8553 degrees
  10. #include <iostream>
  11. using namespace std;
  12. int main(void)
  13. {
  14. //要求用户以度、分、秒的方式输入一个纬度
  15. int degrees, minutes, seconds;
  16. float convert_to_degrees;
  17. cout << "Enter a latitude in degrees, minutes, and seconds :" << endl;
  18. cout << "First, enter the degrees :";
  19. cin >> degrees;
  20. cout << "Next, enter the minutes of arc :";
  21. cin >> minutes;
  22. cout << "Finally, enter the seconds of arc :";
  23. cin >> seconds;
  24. //以度为单位显示该纬度。
  25. const int degrees_minutes = 60;
  26. const int degrees_seconds = 360;
  27. convert_to_degrees = degrees + (minutes / degrees_minutes) + (seconds / degrees_seconds);
  28. cout << degrees << " degrees, " << minutes << " minutes, " << seconds << " seconds = " <<
  29. convert_to_degrees << " degrees" << endl;
  30. system("pause");
  31. return 0;
  32. }

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

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. //要求用户以整数方式输入秒数
  6. long long before_seconds = 0;
  7. cout << "Enter the number of seconds :";
  8. cin >> before_seconds;
  9. //使用符号常量来表示每天有多少小时、每小时有多少分钟以及每分钟有多少秒
  10. const int day_hour = 24;
  11. const int hour_minute = 60;
  12. const int minute_second = 60;
  13. //以天、小时、分钟和秒的方式显示这段时间
  14. int days,hours,minutes,seconds;
  15. days = before_seconds / (day_hour * hour_minute * minute_second);
  16. hours = (before_seconds % (day_hour * hour_minute * minute_second)) / (hour_minute * minute_second);
  17. minutes = (before_seconds - days * day_hour * hour_minute * minute_second - hours * hour_minute * minute_second) / minute_second;
  18. seconds = (before_seconds - days * day_hour * hour_minute * minute_second - hours * hour_minute * minute_second) % minute_second;
  19. cout << before_seconds << " seconds " << "= " << days << " days,"<<
  20. hours << " hours, " << minutes << " minutes," << seconds << " seconds" << endl;
  21. system("pause");
  22. return 0;
  23. }


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.

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. //要求用户输入全球当前的人口和美国当前的人口
  6. long long population_world,population_US;
  7. cout << "Enter the world's population:";
  8. cin >> population_world;
  9. cout << "Enter the population of the US :";
  10. cin >> population_US;
  11. //显示美国的人口占全球人口的百分比
  12. double percent = 100*((double)population_US / (double)population_world);
  13. cout << "The population of the US is " << percent<< "% of the world population." << endl;
  14. system("pause");
  15. return 0;
  16. }

总结:刚开始没有对population_US 和population_world进行类型转换,导致结果不正确,应该注意先进行类型转换。100*((double)population_US / (double)population_world);
6.编写一个程序,要求用户输入驱车里程(英里)和使用汽油量(加仑),然后指出汽车耗油量为一加仑的里程。如果愿意,也可以让程序要求用户以公里为单位输入距离,并以升为单位输入汽油量,然后指出欧洲风格的结果—-—即每100公里的耗油量(升)。

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. double miles, gal;
  6. cout << "Please enter the mileage(miles):";
  7. cin >> miles;
  8. cout << "Please enter the amount of gasoline used(Gal):";
  9. cin >> gal;
  10. cout<<"The fuel consumption of the car is "<<miles/gal<<" miles/gallon"<<endl;
  11. system("pause");
  12. return 0;
  13. }

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

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. //用户按欧洲风格输入汽车的耗油量(每100公里消耗的汽油量(升))
  6. double consumption_Eur;
  7. int mpg;
  8. cout << "Enter the fuel consumption of the vehicle (per 100 km):";
  9. cin >> consumption_Eur;
  10. //将其转换为美国风格的耗油量―每加仑多少英里
  11. const double _100km_mile = 62.14;
  12. const double gai_L = 3.875;
  13. mpg = _100km_mile/(consumption_Eur / gai_L) ;
  14. cout << "So your fuel consumption of the vehicle is " << mpg << "mpg" << endl;
  15. system("pause");
  16. return 0;
  17. }

第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();

  1. #include <iostream>
  2. using namespace std;
  3. #define MaxSize 80
  4. int main(void)
  5. {
  6. char firstName[MaxSize];
  7. char lastName[MaxSize];
  8. char Grade;
  9. int Age;
  10. cout << "What is your first name?";
  11. cin.getline(firstName, MaxSize);
  12. cout << "What is your last name?";
  13. cin.getline(lastName, MaxSize);
  14. cout << "what letter grade do you deserve?";
  15. cin >> Grade;
  16. cout << "what is your age?";
  17. cin >> Age;
  18. Grade = Grade + 1;
  19. cout << "Name: " << lastName << ", " << firstName << endl;
  20. cout << "Grade: " << Grade << endl;
  21. cout << "Age: " << Age << endl;
  22. system("pause");
  23. return 0;
  24. }

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

解答:将一行输入读到string对象中的代码:getline(cin,str);(书p87)

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. int main(void)
  5. {
  6. string name;
  7. string desert;
  8. cout << "Enter your name:" << endl;
  9. getline(cin, name);
  10. cout << "Enter your favorite desert:" << endl;
  11. getline(cin, desert);
  12. cout << "I have some delicious " << desert << " for you, " << name << endl;
  13. system("pause");
  14. return 0;
  15. }

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。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;
  5. int main(void)
  6. {
  7. const int ArSize = 80;
  8. char firstname[ArSize];
  9. char lastname[ArSize];
  10. cout << "Enter your first name:" << endl;
  11. cin.getline(firstname, ArSize);
  12. cout << "Enter your last name:" << endl;
  13. cin.getline(lastname, ArSize);
  14. strcat(lastname, ", "); //把一个逗号和空格与lastname组合起来并赋给数组lastname
  15. strcat(lastname, firstname);//将firstname与lastname数组结合起来赋给lastname数组
  16. cout << "Here's the information in a single string:" << lastname << endl;
  17. system("pause");
  18. return 0;
  19. }

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

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

解答:与上题不同,string对象的字符串拼接使用运算符即可完成。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;
  5. int main(void)
  6. {
  7. string firstname;
  8. string lastname;
  9. cout << "Enter your first name:" << endl;
  10. getline(cin, firstname);
  11. cout << "Enter your last name:" << endl;
  12. getline(cin, lastname);
  13. string str = lastname + ", " + firstname;
  14. cout << "Here's the information in a single string:" << str << endl;
  15. system("pause");
  16. return 0;
  17. }

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

  1. #include <iostream>
  2. using namespace std;
  3. //定义结构
  4. struct CandyBar
  5. {
  6. string brand;
  7. float weight;
  8. int calorie;
  9. };
  10. int main(void)
  11. {
  12. CandyBar snack =
  13. {
  14. "Mocha Munch",
  15. 2.3,
  16. 350
  17. };
  18. cout << "Brand: " << snack.brand << "\tweight: " << snack.weight << "\tcalorie: " << snack.calorie << endl;
  19. system("pause");
  20. return 0;
  21. }

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

  1. #include <iostream>
  2. using namespace std;
  3. //定义结构
  4. struct CandyBar
  5. {
  6. string brand;
  7. float weight;
  8. int calorie;
  9. };
  10. int main(void)
  11. {
  12. CandyBar snack[3] =
  13. {
  14. {"Mocha Munch",2.3,350},
  15. {"Fruit Salad",5.2,200},
  16. {"hamburger",2.6,1000}
  17. };
  18. cout << "Brand: " << snack[0].brand << "\tweight: " << snack[0].weight
  19. << "\tcalorie: " << snack[0].calorie << endl;
  20. cout << "Brand: " << snack[1].brand << "\tweight: " << snack[1].weight
  21. << "\tcalorie: " << snack[1].calorie << endl;
  22. cout << "Brand: " << snack[2].brand << "\tweight: " << snack[2].weight
  23. << "\tcalorie: " << snack[2].calorie << endl;
  24. system("pause");
  25. return 0;
  26. }

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

1.披萨饼公司的名称,可以有多个单词组成。
2.披萨饼的直径。
3.披萨饼的重量。
请设计一个能够存储这些信息的结构,并编写一个使用这种结构变量的程序。程序将请求用户输入上述信息;然后显示这些信息。请使用_cin(或其它的方法)和 cout。

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. //定义结构
  5. struct Pizza
  6. {
  7. string Name;
  8. float diameter;
  9. float weight;
  10. };
  11. int main(void)
  12. {
  13. Pizza a;
  14. cout << "Enter the name of commpany:";
  15. getline(cin, a.Name);
  16. cout << "Enter the diameter of Pizza:";
  17. cin >> a.diameter;
  18. cout << "Enter the weight of Pizza:";
  19. cin>>a.weight;
  20. cout << "Name: " << a.Name<< "\tweight: " << a.weight
  21. << "\tdiameter: " << a.diameter << endl;
  22. system("pause");
  23. return 0;
  24. }


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

解答:

  1. 使用new为结构分配内存;注意:用指针去接,以及访问结构成员的时候用箭头访问。
  2. (书p81)先输直径后输入文字,考察怎么处理遗留在输入序列中的换行符问题。如果直接cin读取直径,将会把回车键生成的换行符留在输入队列中,后面的cin.getline()看到换行符后,将会认为是一个空行,并把空行赋给Name字符串。随意需要在读入公司名称前丢弃换行符。解决方式如下:
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. //定义结构
  5. struct Pizza
  6. {
  7. string Name;
  8. float diameter;
  9. float weight;
  10. };
  11. int main(void)
  12. {
  13. Pizza* a = new Pizza;
  14. cout << "Enter the diameter of Pizza:";
  15. (cin >> a->diameter).get(); //or cin>>a->diameter; cin.get();
  16. cout << "Enter the name of commpany:";
  17. getline(cin, a->Name);
  18. cout << "Enter the weight of Pizza:";
  19. cin >> a->weight;
  20. cout << "Name: " << a->Name << "\tweight: " << a->weight
  21. << "\tdiameter: " << a->diameter << endl;
  22. delete a;
  23. system("pause");
  24. return 0;
  25. }


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

  1. #include <iostream>
  2. using namespace std;
  3. //定义结构
  4. struct CandyBar
  5. {
  6. string brand;
  7. float weight;
  8. int calorie;
  9. };
  10. int main(void)
  11. {
  12. const int Size = 3;
  13. CandyBar* snack = new CandyBar[Size];
  14. snack[0] = { "Mocha Munch",2.3,350 };
  15. snack[1] = { "Fruit Salad",5.2,200 };
  16. snack[2] = { "hamburger",2.6,1000 };
  17. for (int i = 0; i < Size; i++)
  18. {
  19. cout << "Brand:" << snack[i].brand << " weight:" << snack[i].weight
  20. << " calorie:" << snack[i].calorie << endl;
  21. }
  22. delete[] snack;
  23. system("pause");
  24. return 0;
  25. }

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

解答:array<typeName,n_elem> arr;

代码写的不好,写成函数应该更好。不懂模板类数组的调用,后续有时间再改;

  1. #include <iostream>
  2. #include <array>
  3. using namespace std;
  4. int main(void)
  5. {
  6. const int num = 3;
  7. array<double, num> score;
  8. //输入成绩
  9. cout << "Please enter the result of your first 40 yard run:";
  10. cin >> score[0];
  11. cout << "Please enter the result of your second 40 yard run:";
  12. cin >> score[1];
  13. cout << "Please enter the result of your third 40 yard run:";
  14. cin >> score[2];
  15. //输出成绩
  16. for (int i = 0; i < num; i++)
  17. {
  18. cout << "第" << i+1 << "次成绩:" << score[i] << endl;
  19. }
  20. //平均成绩
  21. double sum = 0;
  22. for (int i = 0; i < num; i++)
  23. {
  24. sum += score[i];
  25. }
  26. cout << "your average score is:" << sum / num << endl;
  27. system("pause");
  28. return 0;
  29. }

第5章 循环和关系表达式

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

  1. //编写一个要求用户输入两个整数的程序。
  2. //该程序将计算并输出这两个整数之间(包括这两个整数)所有整数的和。
  3. //这里假设先输入较小的整数。
  4. //例如,如果用户输入的是29,则程序将指出2~9之间所有整数的和为44
  5. #include <iostream>
  6. using namespace std;
  7. int main(void)
  8. {
  9. int a;
  10. int b;
  11. int sum1 = 0;
  12. int sum2 = 0;
  13. int sum3 = 0;
  14. cout << "请输入第一个整数:";
  15. cin >> a;
  16. cout << "请输入第二个整数:";
  17. cin >> b;
  18. 法一:for循环
  19. //for (; a <= b; a++)
  20. // sum1 += a;
  21. //cout << "您输入的两个整数之间所有整数的和为:" << sum1 << endl;
  22. //法二:while循环
  23. while (a <= b)
  24. {
  25. sum2 += a;
  26. a++;
  27. }
  28. cout << "您输入的两个整数之间所有整数的和为:"<< sum2 << endl;
  29. 法三:do while循环
  30. //do
  31. //{
  32. // sum3 += a;
  33. // a++;
  34. //} while (a <= b);
  35. //cout << "您输入的两个整数之间所有整数的和为:" << sum3 << endl;
  36. system("pause");
  37. return 0;
  38. }

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

  1. //使用 array对象(而不是数组)和 long double(而不是long long)重新编写程序清单5.4
  2. //并计算100!的值。
  3. //array在书p120 array<typeName,n_elm>arr;
  4. #include <iostream>
  5. #include <array>
  6. using namespace std;
  7. int main(void)
  8. {
  9. const int arrSize = 101;
  10. array<long double, arrSize> arr;
  11. arr[0] = arr[1] = 1;
  12. for (int i = 2; i < arrSize; i++)
  13. {
  14. arr[i] = i * arr[i - 1];
  15. }
  16. cout << "100! = " << arr[100] << endl;
  17. system("pause");
  18. return 0;
  19. }

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

  1. //编写一个要求用户输入数字的程序。每次输入后,
  2. //程序都将报告到目前为止,所有输入的累计和。
  3. //当用户输入0时, 程序结束。
  4. #include <iostream>
  5. using namespace std;
  6. int main(void)
  7. {
  8. double a;
  9. double sum = 0;
  10. cout << "请输入一个数字(输入0程序结束):" ;
  11. while (cin >> a && a)
  12. {
  13. sum += a;
  14. cout << "目前为止,所有输入的和为:" << sum << endl;
  15. cout << "请输入一个数字(输入0程序结束):" ;
  16. }
  17. system("pause");
  18. return 0;
  19. }

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

  1. //4.Daphne 以10 % 的单利投资了100美元。
  2. //也就是说,每一年的利润都是投资额的10 % ,即每年10美元:利息 = 0.10×原始存款
  3. //而Cleo以5 % 的复利投资了100美元。也就是说,利息是当前存款(包括获得的利息的5%, :
  4. // 利息 = 0.05×当前
  5. //Cleo在第一年投资100美元的盈利是5 % ——得到了105美元。
  6. //下一年的盈利是105美元的5 % —即5.25美元,依此类推。
  7. //请编写一个程序,计算多少年后,Cleo 的投资价值才能超过Daphne的投资价值,
  8. //并显示此时两个人的投资价值。
  9. #include <iostream>
  10. using namespace std;
  11. int main(void)
  12. {
  13. double Cleo = 100;
  14. double Daph = 100;
  15. int year_count = 0;
  16. do
  17. {
  18. Daph += 100 * 0.1;
  19. Cleo += Cleo * 0.05;
  20. year_count++;
  21. } while (Cleo < Daph);
  22. cout << year_count << "年后, Cleo投资价值超过Daph."<<endl;
  23. cout<<"Daphene:" << Daph << "\tCleo:" << Cleo << endl;
  24. system("pause");
  25. return 0;
  26. }

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

  1. //假设要销售《C++ For Fools》一书。
  2. //请编写一个程序,输入全年中每个月的销售量(图书数量,而不是销售额)。
  3. //程序通过循环,使用初始化为月份字符串的char* 数组
  4. //(或string对象数组逐月进行提示, 并将输入的数据储存在一个int数组中。
  5. //然后,程序计算数组中各元素的总数,并报告这一年的销售情况。
  6. #include <iostream>
  7. using namespace std;
  8. int main(void)
  9. {
  10. //初始化为月份字符串的string对象数组
  11. string months[12] = {
  12. "January", "February", "March",
  13. "April", "May", "June","July",
  14. "August", "September", "October",
  15. "November","December"
  16. };
  17. int sales[12];
  18. int sum = 0;
  19. for (int i = 0; i < 12; i++)
  20. {
  21. cout << "Please enter the sales volume for " << months[i] << " :";
  22. cin >> sales[i];
  23. }
  24. for (int i = 0; i < 12; i++)
  25. {
  26. cout << months[i] << " sales : " << sales[i] << endl;
  27. sum += sales[i];
  28. }
  29. cout << "Annual sales :" << sum << endl;
  30. system("pause");
  31. return 0;
  32. }

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

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. //初始化为月份字符串的string对象数组
  6. string months[12] = {
  7. "January", "February", "March",
  8. "April", "May", "June","July",
  9. "August", "September", "October",
  10. "November","December"
  11. };
  12. int sales[3][12]; //二维数组存储三年每个月的销量
  13. int sum[3] = {0};
  14. for (int i = 0; i < 3; i++)
  15. {
  16. cout << "Year" << i + 1 << ":" << endl;
  17. for (int j = 0; j < 12; j++)
  18. {
  19. cout << "Please enter the sales volume for " << months[j] << " :";
  20. cin >> sales[i][j];
  21. sum[i] += sales[i][j];
  22. }
  23. cout << (i + 1) << " year sales:" << sum[i] << endl;
  24. }
  25. cout << "The saLes of three year is " << sum[0] + sum[1] + sum[2] << endl;
  26. system("pause");
  27. return 0;
  28. }

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

  1. //设计一个名为car的结构,用它存储下述有关汽车的信息:
  2. //生产商(存储在字符数组或string对象中的字符串)、
  3. //生产年份(整数)
  4. //编写一个程序,向用户询问有多少辆汽车。
  5. //随后,程序使用new来创建一个由相应数量的car结构组成的动态数组。
  6. //接下来,程序提示用户输入每辆车的生产商(可能由多个单词组成)和年份信息。
  7. //请注意,这需要特别小心,因为它将交替读取数值和字符串(参见第4章)。
  8. //最后,程序将显示每个结构的内容。
  9. #include <iostream>
  10. #include <string>
  11. using namespace std;
  12. //设计一个名为car的结构
  13. struct Car
  14. {
  15. string producer; //生产商
  16. int MadeYear; //生产年份
  17. };
  18. int main(void)
  19. {
  20. int Num; //汽车数量
  21. //向用户询问有多少辆汽车。
  22. cout << "How many cars do you wish to catalog?" ;
  23. cin >> Num;
  24. cin.get();
  25. Car* pt = new Car[Num];
  26. for (int i = 0; i < Num; i++)
  27. {
  28. cout << "car #" << i+1 << ":" << endl;
  29. cout << "Please enter the make:";
  30. getline(cin, pt[i].producer);
  31. cout << "please enter the year made:";
  32. cin >> pt[i].MadeYear;
  33. cin.get();
  34. }
  35. cout << "Here is your colrection :" << endl;
  36. for (int i = 0; i < Num; i++)
  37. {
  38. cout << pt[i].MadeYear << " " << pt[i].producer << endl;
  39. }
  40. system("pause");
  41. return 0;
  42. }

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

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. #define MaxSize 30
  5. int main(void)
  6. {
  7. char word[MaxSize];
  8. int count = 0;
  9. cout << "Enter words (to stop, type the word done):" << endl;
  10. cin >> word;
  11. while (strcmp(word, "done"))
  12. {
  13. count++;
  14. cin >> word;
  15. }
  16. cout<<"You entered a total of "<<count<<" words."<<endl;
  17. system("pause");
  18. return 0;
  19. }

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

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. int main(void)
  5. {
  6. string word;
  7. int count = 0;
  8. cout << "Enter words (to stop, type the word done):" << endl;
  9. cin >> word;
  10. while (word != "done")
  11. {
  12. count++;
  13. cin >> word;
  14. }
  15. cout << "You entered a total of " << count << " words." << endl;
  16. system("pause");
  17. return 0;
  18. }

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

...**

..***

.****

*****
 

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. int Num = 0;
  6. cout << "Enter number of rows :";
  7. cin >> Num;
  8. for (int i = 1; i <= Num; i++)
  9. {
  10. for (int j = i; j < Num; j++)
  11. {
  12. cout << ".";
  13. }
  14. for (int j = 0; j < i; j++)
  15. {
  16. cout << "*";
  17. }
  18. cout << endl;
  19. }
  20. system("pause");
  21. return 0;
  22. }

第6章 分支语句和逻辑运算符

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

  1. //1.读取键盘输入,直到遇到@
  2. //2.回显除了数字以外的输入 isdigit
  3. //3.大写转小写 tolower() 小写转大写toupper()
  4. #include <iostream>
  5. #include <cctype>
  6. using namespace std;
  7. int main(void)
  8. {
  9. char ch;
  10. cout << "Enter text for analysis, and type @ to terminate input:"<<endl;
  11. cin.get(ch);
  12. while ((ch != '@'))
  13. {
  14. if (islower(ch))
  15. {
  16. ch = toupper(ch);
  17. }
  18. else if (isupper(ch))
  19. {
  20. ch = tolower(ch);
  21. }
  22. if (isdigit(ch) == false)
  23. {
  24. cout << ch;
  25. }
  26. cin.get(ch);
  27. }
  28. system("pause");
  29. return 0;
  30. }

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

  1. //编写一个程序,最多将10个donation值读入到一个double数组中
  2. //(如果您愿意,也可使用模板类array)。
  3. //程序遇到非数字输入时将结束输入,
  4. //并报告这些数字的平均值以及数组中有多少个数字大于平均值
  5. //6.7读取数字的循环 p187 程序清单6.13
  6. #include <iostream>
  7. #include <array>
  8. using namespace std;
  9. #define max 10
  10. int main(void)
  11. {
  12. array<double, max> donation;
  13. cout << "Enter the elements you want to exist in the array "
  14. <<"( a non number input to terminate):"<<endl;
  15. int i = 0;
  16. double sum = 0;
  17. int n_elem = 0;
  18. int n_above = 0;
  19. while (i < max && cin >> donation[i])
  20. {
  21. n_elem++;
  22. sum += donation[i];
  23. }
  24. double average = sum / n_elem;
  25. for (i = 0; i < max; i++)
  26. {
  27. if (donation[i] > average)
  28. n_above++;
  29. }
  30. cout << "average = " << average << endl;
  31. cout << n_above << " numbers greater than average" << endl;
  32. system("pause");
  33. return 0;
  34. }

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.

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. char ch;
  6. cout << "Please enter one of the following choices :" << endl;
  7. cout << "c) carnivore " << "\t p) pianist" << endl;
  8. cout<< " t) tree" << " \tg) game" << endl;
  9. while (cin >> ch)
  10. {
  11. switch (ch)
  12. {
  13. case 'c':
  14. cout << "tiger is a carnivore." << endl;
  15. break;
  16. case 'p':
  17. cout << "Xiaoming is a pianist." << endl;
  18. break;
  19. case 't':
  20. cout << "A maple is a tree." << endl;
  21. break;
  22. case 'g':
  23. cout << "Golf is a game." << endl;
  24. break;
  25. default:
  26. cout << "Please enter a c, p, t, or g: ";
  27. }
  28. }
  29. system("pause");
  30. return 0;
  31. }

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!

  1. #include <iostream>
  2. using namespace std;
  3. const int strsize = 20;
  4. const int n_elm = 5;
  5. // Benevolent Order of Programmers name structure
  6. struct bop
  7. {
  8. char fullname[strsize];// real name
  9. char title[strsize]; // job title
  10. char bopname[strsize]; //secret BOP name
  11. int preference; //0 = fullname,1 = title, 2 = bopname);
  12. };
  13. bop exampel[n_elm] =
  14. {
  15. { "Wimp Mache", "BOSS", "AS", 0 },
  16. { "Raki Rhodes", "Junior Programmer", "MA", 1 },
  17. { "Celia Laiter", "Manager", "MIPS", 2 },
  18. { "Hoppy Hipman", "Analyst Trainee", "CL", 1 },
  19. { "Pat Hand", "Student", "LOOPY", 2 }
  20. };
  21. void display_name(void)
  22. {
  23. for (int j = 0; j < n_elm; j++)
  24. cout << exampel[j].fullname<< endl;
  25. }
  26. void display_title(void)
  27. {
  28. for (int j = 0; j < n_elm; j++)
  29. cout << exampel[j].title << endl;
  30. }
  31. void display_bopname(void)
  32. {
  33. for (int j = 0; j < n_elm; j++)
  34. cout << exampel[j].bopname<< endl;
  35. }
  36. void display_perference(void)
  37. {
  38. for (int j = 0; j < n_elm; j++)
  39. {
  40. if (exampel[j].preference == 0)
  41. cout << exampel[j].fullname << endl;
  42. else if (exampel[j].preference == 1)
  43. cout << exampel[j].title << endl;
  44. else
  45. cout << exampel[j].bopname << endl;
  46. }
  47. }
  48. int main(void)
  49. {
  50. char ch;
  51. cout << "Benevolent Order of Programmers Report" << endl;
  52. cout<< "a.display by name b.display by title" << endl;
  53. cout<< "c.display by bopname d.display by preference" << endl;
  54. cout<< "q.quit"<<endl;
  55. cout << "Enter your chlice:";
  56. while (cin >> ch && ch !='q')
  57. {
  58. switch (ch)
  59. {
  60. case 'a':
  61. display_name();
  62. break;
  63. case 'b':
  64. display_title();
  65. break;
  66. case 'c':
  67. display_bopname();
  68. break;
  69. case 'd':
  70. display_perference();
  71. break;
  72. }
  73. cout << "Next choice:";
  74. }
  75. cout << "Bye!" << endl;
  76. system("pause");
  77. return 0;
  78. }

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。请编写一个程序,使用循环来要求用户输入收入,并报告所得税。当用户输入负数或非数字时,循环将结束。

  1. #include <iostream>
  2. using namespace std;
  3. int main(void)
  4. {
  5. int income;
  6. cout << "Enter your income:";
  7. while (cin >> income && income >= 0)
  8. {
  9. if (income <= 5000)
  10. {
  11. cout << "tax = 0" << endl;
  12. }
  13. else if (income > 5000 && income <= 15000)
  14. {
  15. cout << "tax = " << (double)(income - 5000) * 0.1<<"tvarps"<< endl;
  16. }
  17. else if (income > 15000 && income < 35000)
  18. {
  19. cout << "tax = " << 0 + (15000 - 5000) * 0.1 + (double)(income - 15000) * 0.15 << "tvarps" << endl;
  20. }
  21. else
  22. {
  23. cout << "tax = " << 0 + (15000 - 5000) * 0.1 + (35000 - 15000) * 0.15+(double)(income - 35000)*0.2 << "tvarps" << endl;
  24. }
  25. cout << "Enter your income:";
  26. }
  27. system("pause");
  28. return 0;
  29. }

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

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. //用来储存姓名的字符数组(或string对象)和用来存储款项的double成员
  5. struct information
  6. {
  7. string name;
  8. double money;
  9. };
  10. //显示所有捐款超过10000的捐款者的姓名及其捐款数额。
  11. void show_Grand(information* info, int num)
  12. {
  13. cout << "Grand Patrons:" << endl;
  14. int n_Grand = 0;
  15. for (int j = 0; j < num; j++)
  16. {
  17. if (info[j].money> 10000)
  18. {
  19. cout << info[j].name << "\t" << info[j].money << endl;
  20. n_Grand++;
  21. }
  22. }
  23. if (n_Grand == 0)
  24. {
  25. cout << "none" << endl;
  26. }
  27. }
  28. //程序将列出其他的捐款者,该列表要以Patrons开头。
  29. void show_other(information* info, int num)
  30. {
  31. cout << "Patrons:" << endl;
  32. int n_other = 0;
  33. for (int j = 0; j < num; j++)
  34. {
  35. if (info[j].money <= 10000)
  36. {
  37. cout << info[j].name << "\t" << info[j].money << endl;
  38. n_other++;
  39. }
  40. }
  41. if (n_other == 0)
  42. {
  43. cout << "none" << endl;
  44. }
  45. }
  46. int main(void)
  47. {
  48. int num; //捐献者数目
  49. cout << "Pleser enter the number of donors: ";
  50. cin >> num;
  51. cin.get(); //清除缓存 后面还要输入字母
  52. information* info = new information[num]; //这些信息被储存在一个动态分配的结构数组中。
  53. //要求用户输入每一个捐献者的姓名和款项。
  54. for (int i = 0; i < num; i++)
  55. {
  56. cout << "Please enter the " << i + 1 << "-th name: ";
  57. getline(cin, info[i].name);
  58. cout << "Please enter the " << i + 1 << "-th money:";
  59. cin >> info[i].money;
  60. cin.get();
  61. }
  62. show_Grand(info, num);
  63. show_other(info, num);
  64. system("pause");
  65. return 0;
  66. }

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

  1. //单词 == 字符数组
  2. #include <iostream>
  3. #include <cctype>
  4. using namespace std;
  5. const int ArrSize = 30;
  6. int main(void)
  7. {
  8. char ch;
  9. char str[ArrSize];
  10. int count_other = 0;
  11. int count_vowel = 0;
  12. int count_consonant = 0;
  13. cout << "Enter words(q to quit) :" << endl;
  14. while (cin >> str)
  15. {
  16. if (strcmp(str, "q") == 0) //单独一个字母q就退出
  17. break;
  18. ch = str[0];
  19. if (isalpha(ch))
  20. {
  21. switch (ch)
  22. {
  23. case 'a':
  24. case 'e':
  25. case 'i':
  26. case 'o':
  27. case 'u':
  28. count_vowel++;
  29. break;
  30. default:
  31. count_consonant++;
  32. }
  33. }
  34. else
  35. count_other++;
  36. }
  37. cout << count_vowel << " words beginning with vowels\n";
  38. cout << count_consonant << " words beginning with consonants\n";
  39. cout << count_other << " others\n";
  40. system("pause");
  41. return 0;
  42. }

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

解:参考书p195

  1. //8.编写一个程序,它打开一个文件文件,逐个字符地读取该文件,
  2. //直到到达文件末尾,然后指出该文件中包含多少个字符。
  3. #include<iostream>
  4. #include <fstream>
  5. #include <cstdlib>
  6. using namespace std;
  7. const int SIZE = 60;
  8. int main(void)
  9. {
  10. char filename[SIZE];
  11. ifstream inFile;
  12. cout << "Enter name of data file:";
  13. cin.getline(filename, SIZE);
  14. inFile.open(filename);
  15. if (!inFile.is_open())
  16. {
  17. cout << "Could not open the file " << filename << endl;
  18. cout << "Program terminating." << endl;
  19. exit(EXIT_FAILURE);
  20. }
  21. int count = 0;
  22. char ch;
  23. inFile >> ch;
  24. while (inFile.good())
  25. {
  26. count++;
  27. inFile >> ch;
  28. }
  29. if (inFile.eof())
  30. cout << "End of file reached." << endl;
  31. else if (inFile.fail())
  32. {
  33. cout << "Input terminated by data mismatch." << endl;
  34. }
  35. else
  36. cout << "Input terminated for unknown reason." << endl;
  37. cout << "A total of " << count << " characters were read." << endl;
  38. inFile.close();
  39. system("pause");
  40. return 0;
  41. }

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

2000
Freida Flass

100500
Tammy Tubbs

5000
Rich Raptor

55000

  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4. using namespace std;
  5. const int size = 20;
  6. //用来储存姓名的字符数组(或string对象)和用来存储款项的double成员
  7. struct information
  8. {
  9. string name;
  10. double money;
  11. };
  12. //显示所有捐款超过10000的捐款者的姓名及其捐款数额。
  13. void show_grand(information* info, int num)
  14. {
  15. cout << "grand patrons:" << endl;
  16. int n_grand = 0;
  17. for (int j = 0; j < num; j++)
  18. {
  19. if (info[j].money> 10000)
  20. {
  21. cout << info[j].name << "\t" << info[j].money << endl;
  22. n_grand++;
  23. }
  24. }
  25. if (n_grand == 0)
  26. {
  27. cout << "none" << endl;
  28. }
  29. }
  30. //程序将列出其他的捐款者,该列表要以patrons开头。
  31. void show_other(information* info, int num)
  32. {
  33. cout << "patrons:" << endl;
  34. int n_other = 0;
  35. for (int j = 0; j < num; j++)
  36. {
  37. if (info[j].money <= 10000)
  38. {
  39. cout << info[j].name << "\t" << info[j].money << endl;
  40. n_other++;
  41. }
  42. }
  43. if (n_other == 0)
  44. {
  45. cout << "none" << endl;
  46. }
  47. }
  48. int main(void)
  49. {
  50. char filename[size];
  51. ifstream infile;
  52. cout << "enter name of data file:";
  53. cin.getline(filename, size);
  54. infile.open(filename);
  55. if (!infile.is_open())
  56. {
  57. cout << "could not open the file " << filename << endl;
  58. cout << "program terminating." << endl;
  59. exit(exit_failure);
  60. }
  61. int num;
  62. int i;
  63. infile>>num;
  64. infile.get(); //清除缓存 后面还要输入字母
  65. information* info = new information[num]; //这些信息被储存在一个动态分配的结构数组中。
  66. for (i = 0; i < num; i++)
  67. {
  68. getline(infile, info[i].name);
  69. infile >> info[i].money;
  70. infile.get();
  71. }
  72. show_grand(info, num);
  73. show_other(info, num);
  74. system("pause");
  75. return 0;
  76. }

第7章 函数C++编程模块

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

  1. #include <iostream>
  2. using namespace std;
  3. double Harmonic_mean(double x, double y)
  4. {
  5. return 2.0 * x * y / (x + y);
  6. }
  7. int main(void)
  8. {
  9. double x;
  10. double y;
  11. cout << "Please input two numbers x and y:(x>0&&y>0):" << endl;
  12. while (cin >> x >> y && ((x > 0) && (y > 0)))
  13. {
  14. double result = Harmonic_mean(x, y);
  15. cout << x << " and " << y << ":" << result << endl;
  16. cout << "Input two numbers x and y:(x>0&&y>0):" << endl;
  17. }
  18. cout << "Done!" << endl;
  19. system("pause");
  20. return 0;
  21. }

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

  1. #include <iostream>
  2. using namespace std;
  3. const int ArrSize = 10;
  4. int True_Size = 0;
  5. //输入
  6. void Input(double *Golf_scores)
  7. {
  8. cout << "If you want to end the input, press the letter!" << endl;
  9. for (int i = 0; i < ArrSize; i++)
  10. {
  11. cout << "Input the " << i + 1 << "_th Score:" << endl;
  12. if (cin >> Golf_scores[i])
  13. {
  14. }
  15. else
  16. {
  17. True_Size = i;
  18. break;
  19. }
  20. True_Size = i;
  21. }
  22. cout << "Enter end!" << endl;
  23. }
  24. //显示
  25. void Display(const double* Golf_scores)
  26. {
  27. cout << "All Scores:";
  28. for (int i = 0; i < True_Size; i++)
  29. {
  30. cout << Golf_scores[i] << " ";
  31. }
  32. cout << endl;
  33. }
  34. //计算平均成绩
  35. void Caculate(double* Golf_scores)
  36. {
  37. double sum = 0;
  38. cout << "Average score:";
  39. for (int i = 0; i < True_Size; i++)
  40. {
  41. sum += Golf_scores[i];
  42. }
  43. cout << (double)sum/True_Size << endl;
  44. }
  45. int main(void)
  46. {
  47. double Golf_scores[ArrSize];
  48. Input(Golf_scores);
  49. Display(Golf_scores);
  50. Caculate(Golf_scores);
  51. system("pause");
  52. return 0;
  53. }

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

struct box
{
char maker [40];

float height ;

float width;

float length;

float volume ;
};
a.编写一个函数,按值传递box结构,并显示每个成员的值。
b.编写一个函数,传递box结构的地址,并将volume成员设置为其他三维长度的乘积。

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

  1. #include <iostream>
  2. using namespace std;
  3. struct box
  4. {
  5. char maker[40];
  6. float height;
  7. float width;
  8. float length;
  9. float volume;
  10. };
  11. //b.编写一个函数,传递box结构的地址,并将volume成员设置为其他三维长度的乘积。
  12. void Caculate_volume(box* example)
  13. {
  14. example->volume = example->length * example->width * example->height;
  15. }
  16. //a.编写一个函数,按值传递box结构,并显示每个成员的值。
  17. void Display(box example)
  18. {
  19. cout << "maker: " << example.maker << endl;
  20. cout << "height: " << example.height << endl;
  21. cout << "width: " << example.width << endl;
  22. cout << "length: " << example.length << endl;
  23. cout << "volume: " << example.volume << endl;
  24. }
  25. int main(void)
  26. {
  27. box example;
  28. cout << "Enter the name of maker:";
  29. cin.getline(example.maker, 40);
  30. cout << "Enter the height:";
  31. cin >> example.height;
  32. cout << "Enter the width:";
  33. cin >> example.width;
  34. cout << "Enter the length:";
  35. cin >> example.length;
  36. Caculate_volume(&example);
  37. Display(example);
  38. system("pause");
  39. return 0;
  40. }

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

  1. #include <iostream>
  2. using namespace std;
  3. long double probability(unsigned numbers, unsigned picks)
  4. {
  5. long double result = 1.0;
  6. long double n;
  7. unsigned p;
  8. for (n = numbers, p = picks; p > 0; n--, p--)
  9. {
  10. result = result * n / p;
  11. }
  12. return result;
  13. }
  14. int main(void)
  15. {
  16. double field_number = 47, field_pick = 5;
  17. double special_number = 27, special_pick = 1;
  18. cout << "You have one chance in "<<
  19. probability(field_number,field_pick)*probability(special_number,special_pick)<<
  20. " of winning." << endl;
  21. system("pause");
  22. return 0;
  23. }

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

  1. #include <iostream>
  2. using namespace std;
  3. long Factorial(int n)
  4. {
  5. if(n == 0)
  6. return 1;
  7. else
  8. return Factorial(n - 1) * n;
  9. }
  10. int main(void)
  11. {
  12. int n;
  13. cout << "Enter a number n(n>0)(q to quit):";
  14. while (cin>>n)
  15. {
  16. cout << n << "! = " << Factorial(n) << endl;
  17. cout << "Next number(q to quit): ";
  18. }
  19. system("pause");
  20. return 0;
  21. }

6.编写一个程序,它使用下列函数:
Fill_array()将一个double数组的名称和长度作为参数。它提示用户输入double值,并将这些值存储到数组中。当数组被填满或用户输入了非数字时,输入将停止,并返回实际输入了多少个数字。
Show_array()将一个double数组的名称和长度作为参数,并显示该数组的内容。
Reverse-array()将一个double数组的名称和长度作为参数,并将存储在数组中的值的顺序反转。程序将使用这些函数来填充数组,然后显示数组;反转数组,然后显示数组;反转数组中除第一个和最后一个元素之外的所有元素,然后显示数组。

  1. #include <iostream>
  2. using namespace std;
  3. const unsigned int ArrSize = 20;
  4. //填充数组
  5. int Fill_array(double Array[],unsigned int ArrSize)
  6. {
  7. int i = 0;
  8. cout << "If you want to end the input, press the letter!" << endl;
  9. while (cin >> Array[i] && i < ArrSize)
  10. {
  11. i++;
  12. }
  13. return i;
  14. }
  15. //显示数组
  16. void Show_array(const double Array[], int Length)
  17. {
  18. for (int i = 0; i < Length; i++)
  19. cout << Array[i] << " ";
  20. cout << endl;
  21. }
  22. //反转数组
  23. void Reverse_array(double Array[], int Length)
  24. {
  25. double temp;
  26. for (int i = 1,j = Length - 2; i < j; i++, j--)
  27. {
  28. temp = Array[i];
  29. Array[i] = Array[j];
  30. Array[j] = temp;
  31. }
  32. }
  33. int main(void)
  34. {
  35. double Array[ArrSize];
  36. //填充数组,然后显示数组
  37. int Length = Fill_array(Array, ArrSize);
  38. Show_array(Array, Length);
  39. //反转数组中除第一个和最后一个元素之外的所有元素,然后显示数组。
  40. cout << "---------------------------------------------------" << endl;
  41. Reverse_array(Array, Length);
  42. Show_array(Array, Length);
  43. system("pause");
  44. return 0;
  45. }

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

  1. #include <iostream>
  2. using namespace std;
  3. const int Max = 5;
  4. double* fill_array(double* Beign, double* End);
  5. void show_array(const double* Beign, const double* End);
  6. void revalue(double r, double* Beign, double* End);
  7. int main(void)
  8. {
  9. double propreties[Max];
  10. double * End = fill_array(propreties,propreties+Max);
  11. show_array(propreties,End);
  12. if (End != propreties)
  13. {
  14. cout << "Enter revaluation factor:";
  15. double factor;
  16. while (!(cin >> factor))
  17. {
  18. cin.clear();
  19. while (cin.get() != '\n')
  20. {
  21. continue;
  22. }
  23. cout << "Bad input;Please enter a number:";
  24. }
  25. revalue(factor, propreties, End);
  26. show_array(propreties, End);
  27. }
  28. cout << "Done!" << endl;
  29. system("pause");
  30. return 0;
  31. }
  32. double * fill_array(double* Beign, double *End)
  33. {
  34. double *temp = Beign;
  35. int i = 0;
  36. for (; temp != End; temp++)
  37. {
  38. cout << "Enter value #" << (i + 1) << ":";
  39. cin >> *temp;
  40. if (!cin)
  41. {
  42. cin.clear();
  43. while (cin.get() != '\n')
  44. {
  45. continue;
  46. }
  47. cout << "Bad input;Please enter a number:";
  48. break;
  49. }
  50. else if (*temp < 0)
  51. {
  52. break;
  53. }
  54. i++;
  55. }
  56. return temp;
  57. }
  58. void show_array(const double* Beign, const double* End)
  59. {
  60. int i = 0;
  61. for (; Beign != End; Beign++)
  62. {
  63. cout << "Property #" << (i + 1) << ": $";
  64. cout << *Beign << endl;
  65. i++;
  66. }
  67. }
  68. void revalue(double r, double* Beign, double* End)
  69. {
  70. for (double* temp = Beign; temp != End; temp++)
  71. *temp *= r;
  72. }

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

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

  1. #include <iostream>
  2. #include <array>
  3. #include <string>
  4. using namespace std;
  5. const int Seasons = 4;
  6. const char* Snames[4] = { "Sppring","Summer","Fall","Winter" };
  7. void fill(double *expenses);
  8. void show(const double expenses[], int Length);
  9. int main(void)
  10. {
  11. double expenses[Seasons];
  12. fill(expenses);
  13. show(expenses,Seasons);
  14. system("pause");
  15. return 0;
  16. }
  17. void fill(double* expenses)
  18. {
  19. for (int i = 0; i < Seasons; i++)
  20. {
  21. cout << "Enter " << Snames[i] << " expenses:";
  22. cin >> expenses[i];
  23. }
  24. }
  25. void show(const double expenses[], int Length)
  26. {
  27. double total = 0.0;
  28. cout << "\nEXPENSES\n";
  29. for (int i = 0; i < Seasons; i++)
  30. {
  31. cout << Snames[i] << ": $" << expenses[i] << endl;
  32. total += expenses[i];
  33. }
  34. cout << "Total Expenses: $" << total << endl;
  35. }

  1. #include <iostream>
  2. #include <array>
  3. #include <string>
  4. using namespace std;
  5. const int Seasons = 4;
  6. struct Expenses
  7. {
  8. double expenses[Seasons];
  9. };
  10. const char* Snames[4] = { "Sppring","Summer","Fall","Winter" };
  11. void fill(struct Expenses * e);
  12. void show(const Expenses *ptr);
  13. int main(void)
  14. {
  15. Expenses e;
  16. fill(&e);
  17. show(&e);
  18. system("pause");
  19. return 0;
  20. }
  21. void fill(struct Expenses* ptr)
  22. {
  23. for (int i = 0; i < Seasons; i++)
  24. {
  25. cout << "Enter " << Snames[i] << " expenses:";
  26. cin >> ptr->expenses[i];
  27. }
  28. }
  29. void show(const Expenses *ptr)
  30. {
  31. double total = 0.0;
  32. cout << "\nEXPENSES\n";
  33. for (int i = 0; i < Seasons; i++)
  34. {
  35. cout << Snames[i] << ": $" << ptr->expenses[i] << endl;
  36. total += ptr->expenses[i];
  37. }
  38. cout << "Total Expenses: $" << total << endl;
  39. }

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 ;

  1. #include <iostream>
  2. using namespace std;
  3. const int SLEN = 30;
  4. struct student {
  5. char fullname[SLEN];
  6. char hobby[SLEN];
  7. int ooplevel;
  8. };
  9. int getinfo(student pa[], int n)
  10. {
  11. cout << "Please input the students information:" << endl;
  12. int i;
  13. for (i = 0; i < n; i++)
  14. {
  15. cout << "Student #" << i + 1 << ": " << endl;
  16. cout << "Fullname: ";
  17. cin.getline(pa[i].fullname, SLEN);
  18. if (pa[i].fullname[0] == '\0')
  19. break;
  20. cout << "Hobby: ";
  21. if (pa[i].hobby[0] == '\0')
  22. break;
  23. cin.getline(pa[i].hobby, SLEN);
  24. cout << "Ooplevel: ";
  25. if (!(cin >> pa[i].ooplevel))
  26. break;
  27. cin.get();
  28. }
  29. cout <<"Enter End!"<< endl;
  30. return i; //返回实际获取到的元素的数量
  31. }
  32. void display1(student st)
  33. {
  34. cout << "fullname:" << st.fullname << " hobby:" << st.hobby <<
  35. " opplevel:" << st.ooplevel << endl;
  36. }
  37. // display2 () takes the address of student structure as an
  38. //argument and displays the structure's contents
  39. void display2(const student* ps)
  40. {
  41. cout << "fullname:" << ps->fullname << " hobby:" << ps->hobby <<
  42. " opplevel:" << ps->ooplevel << endl;
  43. }
  44. //display3 () takes the address of the first element of an array
  45. //of student structures and the number of array elements as
  46. //arguments and displays the contents of the structures
  47. void display3(const student pa[], int n)
  48. {
  49. for (int i = 0; i < n; i++)
  50. {
  51. cout << "Student #" << i + 1 << endl;
  52. cout << "fullname:" << pa[i].fullname << " hobby:" << pa[i].hobby <<
  53. " opplevel:" << pa[i].ooplevel << endl;
  54. }
  55. }
  56. int main()
  57. {
  58. cout << "Enter class size: ";
  59. int class_size;
  60. cin >> class_size;
  61. while (cin.get()!= '\n')
  62. continue;
  63. student* ptr_stu = new student[class_size];
  64. int entered = getinfo(ptr_stu, class_size);
  65. for (int i = 0; i < entered; i++)
  66. {
  67. display1(ptr_stu[i]);
  68. display2(&ptr_stu[i]);
  69. }
  70. display3(ptr_stu, entered);
  71. delete[] ptr_stu;
  72. cout << "Done\n";
  73. return 0;
  74. }

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);
可以采用数组初始化语法,并将函数名作为地址来初始化这样的数组。

  1. #include <iostream>
  2. using namespace std;
  3. double add(double x, double y);
  4. double subtract(double x, double y);
  5. double multiply(double x, double y);
  6. double caculate(double x, double y, double (*func)(double, double));
  7. int main(void)
  8. {
  9. double x;
  10. double y;
  11. double (*pf[3])(double, double) = {add,subtract,multiply};//指针数组
  12. cout << "Enter two numbers(q to quit):" ;
  13. while (cin >> x >> y)
  14. {
  15. for (int i = 0; i < 3; i++)
  16. {
  17. cout << "The result #" << i + 1 << ":" << caculate(x, y,pf[i]) << endl;
  18. }
  19. cout << "Enter two numbers(q to quit):" << endl;
  20. }
  21. system("pause");
  22. return 0;
  23. }
  24. double add(double x, double y)
  25. {
  26. return x + y;
  27. }
  28. double subtract(double x, double y)
  29. {
  30. return x - y;
  31. }
  32. double multiply(double x, double y)
  33. {
  34. return x * y;
  35. }
  36. double caculate(double x, double y, double (*func)(double, double))
  37. {
  38. return (*func)(x, y);
  39. }

第8章 函数探幽

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

解:使用默认参数。

  1. #include <iostream>
  2. const int Len = 20;
  3. void print(char* str, int a = 0);
  4. using namespace std;
  5. int main(void)
  6. {
  7. char str[Len] = "abcdefg" ;
  8. print(str);
  9. cout << endl;
  10. print(str);
  11. cout << endl;
  12. print(str,10);
  13. cout << endl;
  14. print(str,30);
  15. cout << endl;
  16. system("pause");
  17. return 0;
  18. }
  19. void print(char* str, int n)
  20. {
  21. static int count = 0;
  22. count++;
  23. while (n >= 0)
  24. {
  25. if (n == 0)
  26. {
  27. cout << str << endl;
  28. return;
  29. }
  30. else
  31. {
  32. for (int i = 0; i < count; i++)
  33. {
  34. cout << str << endl;
  35. }
  36. return;
  37. }
  38. }
  39. }


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拷贝

  这里出错好久才明白。

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. const int Len = 30;
  5. struct CandyBar
  6. {
  7. char brand[Len];
  8. double weight;
  9. int calories;
  10. };
  11. void fill_candybar(CandyBar& x, const char* a= "Millennijum Munch ", const double b = 2.85, const int c = 350);
  12. void Display(const CandyBar& s);
  13. int main(void)
  14. {
  15. CandyBar candy1, candy2,candy3;
  16. fill_candybar(candy1);
  17. cout << "candy1: "<< endl;
  18. Display(candy1);
  19. const char* m = new char[Len];
  20. m= "Dove";
  21. fill_candybar(candy2, m, 3.30, 300); //baby使用自定义参
  22. cout << "candy2: " << endl;
  23. Display(candy2);
  24. const char* s = new char[Len];
  25. s = "Margaret";
  26. fill_candybar(candy3, s, 4.28, 900); //baby使用自定义参
  27. cout << "candy3: " << endl;
  28. Display(candy3);
  29. system("pause");
  30. return 0;
  31. }
  32. void fill_candybar(CandyBar &x,const char* a,const double b,const int c)
  33. {
  34. //x.brand = a; //如果brand是string,这里可以直接赋值
  35. strcpy_s(x.brand,a); //如果brand是char[],字符串不能直接赋值,需要进行strcpy拷贝
  36. x.weight = b;
  37. x.calories = c;
  38. }
  39. void Display(const CandyBar& s)
  40. {
  41. cout << "Brand:" << s.brand << endl;
  42. cout << "Weight:" << s.weight << endl;
  43. cout << "Calories:" << s.calories << endl;
  44. }


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()只能得到字符数组长度。

  1. #include <iostream>
  2. #include <cctype>
  3. #include <string>
  4. using namespace std;
  5. string upper(string& a);
  6. int main(void)
  7. {
  8. string a;
  9. cout << "Enter a string (q to quit) :";
  10. getline(cin, a);
  11. while (a != "q")
  12. {
  13. cout << upper(a) << endl;
  14. cout << "Next string (q to quit) :";
  15. getline(cin, a);
  16. }
  17. cout << "Bye." << endl;
  18. system("pause");
  19. return 0;
  20. }
  21. string upper(string &a)
  22. {
  23. for (int i = 0; i < a.size(); i++)
  24. {
  25. a[i] = toupper(a[i]);
  26. }
  27. return a;
  28. }

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

  1. #include<iostream>
  2. using namespace std;
  3. #include<string> //for strlen(),strcpy()
  4. struct stringy
  5. {
  6. char* str; //points to a string
  7. int ct; //length of string (not couting '\0')
  8. };
  9. // prototypes for set(), show(), and show() go here
  10. void set(stringy &beany, const char * testing);
  11. void show(const stringy &a, int b = 1);
  12. void show(const char* a, int b = 1);
  13. int main()
  14. {
  15. stringy beany;
  16. char testing[] = "Reality isn't what it used to be.";
  17. set(beany, testing); //first argument is a reference,allocates space to hold copy of testing
  18. //sets str member of beany to point to the new block,
  19. //copies testing to new block,and sets ct member of beany
  20. show(beany); //prints member string once
  21. show(beany, 2); //prints member string twice
  22. testing[0] = 'D';
  23. testing[1] = 'u';
  24. show(testing); //prints testing string once
  25. show(testing, 3); //prints testing string thrice
  26. show("Done!");
  27. return 0;
  28. }
  29. void set(stringy& beany, const char* testing)
  30. {
  31. beany.ct = strlen(testing) + 1;
  32. beany.str = new char[beany.ct];
  33. strcpy_s(beany.str,beany.ct,testing); //这里编译器要求strcpy_s版本
  34. //三个参数时:strcpy_s( strDestination,size_t numberOfElements,const char* strSource);
  35. //两个参数时:strcpy (char(&strDestination)[size],const char* strSource);
  36. //使用3个参数的版本时,一般的做法就是将长度定为被复制的字符串长度 + 1
  37. }
  38. void show(const stringy& a, int b )
  39. {
  40. for (int i = 0; i < b; i++)
  41. {
  42. cout << a.str << endl;
  43. }
  44. }
  45. void show(const char* a, int b)
  46. {
  47. for (int i = 0; i < b; i++)
  48. {
  49. cout << a<<endl;
  50. }
  51. }

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

  1. #include <iostream>
  2. using namespace std;
  3. template <typename T>
  4. T max5(T arr[]);
  5. int main(void)
  6. {
  7. int a[5] = { 1,6,3,2,5 };
  8. double b[5] = { 1.20,2.30,5.2,1.4,2.7 };
  9. int c = max5(a);
  10. double d = max5(b);
  11. cout << "int数组中最大值为:" << c << endl;
  12. cout << "double数组中最大值为:" << d << endl;
  13. system("pause");
  14. return 0;
  15. }
  16. template <typename T>
  17. T max5(T arr[])
  18. {
  19. T temp = arr[0];
  20. for (int i = 1; i < 5; i++)
  21. {
  22. if (arr[i] > temp)
  23. temp = arr[i];
  24. }
  25. return temp;
  26. }

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

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. template <typename T>
  5. T maxn(T* arr, const int n);
  6. //具体化
  7. template<> const char* maxn(const char* arr[], const int n);
  8. int main(void)
  9. {
  10. int a[6] = { 4,6,3,5,8,2 };
  11. double b[4] = { 2.3,5.4,1.3,6.2 };
  12. int c = maxn(a,sizeof(a)/sizeof(int));
  13. double d = maxn(b, sizeof(b) / sizeof(double));
  14. cout << "int数组中最大值为:" << c << endl;
  15. cout << "double数组中最大值为:" << d << endl;
  16. const char* arr[7] = { "absaihc","chuahuiap","asjch cnck c","csamkc casj","fwef","a","bc" };
  17. const char* f = maxn(arr, 7) ;
  18. cout << f << endl;
  19. system("pause");
  20. return 0;
  21. }
  22. template <typename T>
  23. T maxn(T* arr, const int n)
  24. {
  25. T temp = arr[0];
  26. for (int i = 1; i < n; i++)
  27. {
  28. if (arr[i] > temp)
  29. {
  30. temp = arr[i];
  31. }
  32. }
  33. return temp;
  34. }
  35. template<> const char* maxn(const char* arr[], const int n)
  36. {
  37. const char* temp = arr[0];
  38. for (int i = 1; i < n; i++)
  39. {
  40. if (strlen(arr[i]) > strlen(temp))
  41. temp = arr[i];
  42. }
  43. ;
  44. return temp;
  45. }

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

  1. #include <iostream>
  2. using namespace std;
  3. template<typename T>
  4. T SumArray(T arr[], int n); //template A
  5. template<typename T> //template B
  6. T SumArray(T* arr[], int n);
  7. struct debts
  8. {
  9. char name[50];
  10. double amouunt;
  11. };
  12. int main(void)
  13. {
  14. int things[6] = { 13,31,103,301,310,130 };
  15. struct debts me_E[3] =
  16. {
  17. {"Ima Wolfe",2400.0},
  18. {"Ura Foxe",1300.0},
  19. {"Iby Stout",1800.0}
  20. };
  21. double* pd[3];
  22. for (int i = 0; i < 3; i++)
  23. pd[i] = &me_E->amouunt;
  24. cout << "Listing Mr.E's counts:" << endl;
  25. cout << SumArray(things, 6) << endl;
  26. cout << "Listing Mr.E's debts:" << endl;
  27. cout << SumArray(pd, 3) << endl;
  28. system("pause");
  29. return 0;
  30. }
  31. template<typename T>
  32. T SumArray(T arr[], int n)
  33. {
  34. T sum = 0;
  35. cout << "template A" << endl;
  36. for (int i = 0; i < n; i++)
  37. sum += arr[i];
  38. return sum;
  39. }
  40. template<typename T> //template B
  41. T SumArray(T* arr[], int n)
  42. {
  43. T sum = 0;
  44. cout << "template B" << endl;
  45. for (int i = 0; i < n; i++)
  46. sum += *arr[i];
  47. return sum;
  48. }

第9章 内存模型和名称空间

1. 下面是一个头文件:

(…………)

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

golf ann;

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

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

golf andy;

setgolf(andy);

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

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

头文件 golf.h

  1. #include <iostream>
  2. using namespace std;
  3. const int Len = 40;
  4. struct golf
  5. {
  6. char fullname[Len];
  7. int handicap;
  8. };
  9. void setgolf(golf& g, const char* name, int hc);
  10. int setgolf(golf& g);
  11. void handicap(golf& g, int hc);
  12. void showgolf(const golf& g);

golf.cpp(函数定义)

  1. #include "golf.h"
  2. #include <iostream>
  3. #include <cstring>
  4. using namespace std;
  5. void setgolf(golf &g, const char* name, int hc)
  6. {
  7. strcpy_s(g.fullname, name);
  8. g.handicap = hc;
  9. }
  10. int setgolf(golf& g)
  11. {
  12. cout << "Please enter the full name of player:";
  13. cin.getline(g.fullname, Len);
  14. if (strcmp(g.fullname, "") == 0)
  15. {
  16. return 0;
  17. }
  18. cout << "Please enter the handicap of player:";
  19. cin >> g.handicap;
  20. cin.get();
  21. return 1;
  22. }
  23. void handicap(golf& g, int hc)
  24. {
  25. g.handicap = hc;
  26. }
  27. void showgolf(const golf& g)
  28. {
  29. cout << "Information:" << endl;
  30. cout << "Name: " << g.fullname << endl;
  31. cout << "handicap: " << g.handicap << endl;
  32. }

main.cpp主函数

  1. #include "golf.h"
  2. #include <iostream>
  3. using namespace std;
  4. int main(void)
  5. {
  6. golf ann;
  7. setgolf(ann, "Ann Birdfree", 24);
  8. showgolf(ann);
  9. golf andy;
  10. setgolf(andy);
  11. showgolf(andy);
  12. handicap(andy, 30);
  13. showgolf(andy);
  14. system("pause");
  15. return 0;
  16. }

 测试结果

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

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. void strcount(const string str);
  5. int main(void)
  6. {
  7. string input;
  8. cout << "Enter a line:" << endl;
  9. getline(cin, input);
  10. while (cin)
  11. {
  12. strcount(input);
  13. cout << "Enter next line (empty line to quit):\n";
  14. getline(cin, input);
  15. if (input == "")
  16. break;
  17. }
  18. cout << "Bye." << endl;
  19. system("pause");
  20. return 0;
  21. }
  22. void strcount(const string str)
  23. {
  24. static int total = 0;
  25. int count = 0;
  26. cout << "\"" << str << "\" contains ";
  27. while (str[count])
  28. count++;
  29. total += count;
  30. cout << count << " characters\n";
  31. cout << total << " characters in total\n";
  32. }

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

struct chaff

{

       char dross[20];

        int slag;

};

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

方法一:定位运算符

  1. #include <iostream>
  2. #include <string>
  3. #include <new>
  4. using namespace std;
  5. const int BUF = 512;
  6. char buffer[BUF];
  7. struct chaff
  8. {
  9. char dross[20];
  10. int slag;
  11. };
  12. int main(void)
  13. {
  14. chaff * p = new(buffer) chaff[2];
  15. char dross[20];
  16. for (int i = 0; i < 2; i++)
  17. {
  18. cout << "Enter dross of #" << i + 1 << " chaff:\n";
  19. cin.getline(dross, 20);
  20. strcpy_s(p[i].dross, dross);
  21. cout << "Enter slag of #" << i + 1 << " chaff:\n";
  22. cin >> p[i].slag;
  23. cin.get();
  24. }
  25. for (int i = 0; i < 2; i++)
  26. {
  27. cout << "chaff #" << i + 1 << ":\n";
  28. cout << "dross: " << p[i].dross << " slag: " << p[i].slag << endl;
  29. }
  30. system("pause");
  31. return 0;
  32. }

方法二:常规new运算符

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. struct chaff
  5. {
  6. char dross[20];
  7. int slag;
  8. };
  9. int main(void)
  10. {
  11. chaff* p = new chaff[2];
  12. char dross[20];
  13. for (int i = 0; i < 2; i++)
  14. {
  15. cout << "Enter dross of #" << i + 1 << " chaff:\n";
  16. cin.getline(dross, 20);
  17. strcpy_s(p[i].dross, dross);
  18. cout << "Enter slag of #" << i + 1 << " chaff:\n";
  19. cin >> p[i].slag;
  20. cin.get();
  21. }
  22. for (int i = 0; i < 2; i++)
  23. {
  24. cout << "chaff #" << i + 1 << ":\n";
  25. cout << "dross: " << p[i].dross << " slag: " << p[i].slag << endl;
  26. }
  27. delete []p;
  28. system("pause");
  29. return 0;
  30. }

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

(…………)

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

解答:

  1. 对名称空间进行扩展,以提供三个函数的定义。(书p332)在名称空间中声明的函数名的作用域为整个名称空间,因此定义和声明必须位于同一名称空间中。通过包含头文件可以导入原来的名称空间。然后在文件中将函数定义添加到名称空间中。
  2. 在main函数中包含名称空间使用using编译指令即可。using namespace SALES;

头文件9.4.h

  1. #include <iostream>
  2. namespace SALES
  3. {
  4. const int QUARTERS = 4;
  5. struct Sales
  6. {
  7. double sales[QUARTERS];
  8. double average;
  9. double max;
  10. double min;
  11. };
  12. void setSales(Sales& s, const double ar[], int n);
  13. void setSales(Sales& s);
  14. void showSales(const Sales& s);
  15. }

函数定义.cpp

  1. #include "9.4.h"
  2. #include <iostream>
  3. using namespace std;
  4. namespace SALES
  5. {
  6. void setSales(Sales& s, const double ar[], int n) //非交互式版本
  7. {
  8. if (n < 4)
  9. {
  10. for (int i = 0; i < n; i++)
  11. {
  12. s.sales[i] = ar[i];
  13. }
  14. for (int j = n; j < 4; j++)
  15. {
  16. s.sales[j] = 0;
  17. }
  18. }
  19. else
  20. {
  21. for (int i = 0; i < 4; i++)
  22. {
  23. s.sales[i] = ar[i];
  24. }
  25. }
  26. s.average = (s.sales[0] + s.sales[1] + s.sales[2] + s.sales[3]) / 4;
  27. double max = 0.0;
  28. double min = 1000000;
  29. for (int i = 0; i < 4; i++)
  30. {
  31. if (s.sales[i] > max)
  32. {
  33. max = s.sales[i];
  34. }
  35. if (s.sales[i] < min)
  36. {
  37. min = s.sales[i];
  38. }
  39. }
  40. s.max = max;
  41. s.min = min;
  42. }
  43. void setSales(Sales& s)
  44. {
  45. cout << "Please enter sales:\n";
  46. for (int i = 0; i < 4; i++)
  47. {
  48. cout << "The #" << i + 1 << " quarter is: ";
  49. cin >> s.sales[i];
  50. }
  51. s.average = (s.sales[0] + s.sales[1] + s.sales[2] + s.sales[3]) / 4;
  52. double max = 0.0;
  53. double min = 1000000;
  54. for (int i = 0; i < 4; i++)
  55. {
  56. if (s.sales[i] > max)
  57. {
  58. max = s.sales[i];
  59. }
  60. if (s.sales[i] < min)
  61. {
  62. min = s.sales[i];
  63. }
  64. }
  65. s.max = max;
  66. s.min = min;
  67. }
  68. void showSales(const Sales& s)
  69. {
  70. cout << "The sales of 4 quarters are $" << s.sales[0] << ", $" << s.sales[1] << ", $" << s.sales[2] << ", $" << s.sales[3] << endl;
  71. cout << "Average:" << s.average << endl;
  72. cout << "Max:" << s.max << endl;
  73. cout << "Min:" << s.min << endl;
  74. }
  75. }

main函数.cpp

  1. #include "9.4.h"
  2. #include <iostream>
  3. using namespace std;
  4. using namespace SALES;
  5. int main(void)
  6. {
  7. Sales s1, s2;
  8. cout << "#1:" << endl;
  9. setSales(s1);
  10. showSales(s1);
  11. cout << "--------------------------------------------------" << endl;
  12. cout << "#2"<<endl;
  13. double ar[3] = { 10,20,30 };
  14. setSales(s2, ar, 3);
  15. showSales(s2);
  16. cout << "Bye\n";
  17. system("pause");
  18. return 0;
  19. }

第10章 对象和类

(为节约时间,使用类的程序只写了简单的测试,未循环写入、未考虑交互性等)

1. 为复习题5描述的类提供方法定义,并编写一个小程序来演示所有的特性。
   复习题5:
   定义一个类来表示银行账户。数据成员包括储户姓名、账号(使用字符串)和存款。成员函数执行如下操作:
   ·创建一个对象并将其初始化
   ·显示储户姓名、账号和存款
   ·存入参数指定的存款
   ·取出参数指定的款项

1.1. 头文件bank.h

  1. #ifndef BANK_H_
  2. #define BANK_H_
  3. #include <iostream>
  4. #include <string>
  5. using namespace std;
  6. class BankAccount
  7. {
  8. private:
  9. string m_name;
  10. string m_acctnum;
  11. double m_balance;
  12. public:
  13. BankAccount(); //默认构造函数
  14. BankAccount(const string &cilent, const string & num, double bal );
  15. void show(void) const; //显示
  16. void deposit(double crash); //存
  17. void withdraw(double crash); //取
  18. };
  19. #endif // !10.1_H_s

1.2.定义成员函数.cpp

  1. #include "bank.h"
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;
  5. BankAccount::BankAccount()
  6. {
  7. m_name = "None";
  8. m_acctnum = "None";
  9. m_balance = 0.0;
  10. }
  11. BankAccount::BankAccount(const string &cilent, const string &num, double bal )
  12. {
  13. m_name = cilent;
  14. m_acctnum = num;
  15. m_balance = bal;
  16. }
  17. void BankAccount::show(void) const
  18. {
  19. cout << "Account information:" << endl;
  20. cout << "Name: " << m_name << endl;
  21. cout << "Account number: " << m_acctnum << endl;
  22. cout << "Balance: " << m_balance << endl;
  23. }
  24. void BankAccount::deposit(double crash)
  25. {
  26. m_balance += crash;
  27. }
  28. void BankAccount::withdraw(double crash)
  29. {
  30. m_balance -= crash;
  31. }

1.3.使用类.cpp

  1. #include "bank.h"
  2. #include <iostream>
  3. #include <string>
  4. int main(void)
  5. {
  6. //使用默认构造函数创建账户bank1
  7. string name1;
  8. string accountnum1;
  9. double bal1;
  10. double add, minus;
  11. BankAccount bank1 = BankAccount(); //使用默认构造函数
  12. bank1.show();
  13. cout << "Enter name:";
  14. getline(cin, name1);
  15. cout << "Enter the number of account:";
  16. getline(cin, accountnum1);
  17. cout << "Enter balance:";
  18. cin >> bal1;
  19. cin.get();
  20. bank1 = BankAccount(name1, accountnum1, bal1); //使用构造函数
  21. bank1.show();
  22. cout << "Please enter the amount to deposit:";
  23. cin >> add;
  24. bank1.deposit(add);
  25. bank1.show();
  26. cout << "Please input the amount to be withdrawn:";
  27. cin >> minus;
  28. bank1.withdraw(minus);
  29. bank1.show();
  30. system("pause");
  31. return 0;
  32. }

总结:我把头文件命名成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

  1. #ifndef PERSON_H_
  2. #define PERSON_H_
  3. #include <iostream>
  4. using namespace std;
  5. class Person
  6. {
  7. private:
  8. static const int LIMIT = 25;
  9. string lname;
  10. char fname[LIMIT];
  11. public:
  12. Person() { lname = ""; fname[0] = '\0'; };
  13. Person(const string& ln, const char* fn = "Heyyou");
  14. void Show()const;
  15. void FormalShow()const;
  16. };
  17. #endif // !10.2_H_

 2.2.成员函数.cpp

  1. #include "person.h"
  2. #include <iostream>
  3. using namespace std;
  4. Person::Person(const string& ln, const char* fn ) //默认参数在原型时有即可,定义时不需要有
  5. {
  6. lname = ln;
  7. strcpy_s(fname, LIMIT, fn);
  8. }
  9. void Person::Show()const
  10. {
  11. cout << fname << " " << lname << endl;
  12. }
  13. void Person::FormalShow()const
  14. {
  15. cout << lname << " , " << fname << endl;
  16. }

2.3.使用类.cpp

  1. #include "person.h"
  2. #include <iostream>
  3. int main(void)
  4. {
  5. Person one;
  6. cout << "默认构造one:" << endl;
  7. one.Show();
  8. one.FormalShow();
  9. Person two("Smythecraft");
  10. cout << "two显示如下:" << endl;
  11. two.Show();
  12. two.FormalShow();
  13. Person three("Dimwiddy", "Sam");
  14. cout << "three显示如下:" << endl;
  15. three.Show();
  16. three.FormalShow();
  17. system("pause");
  18. return 0;
  19. }

总结:含有默认参数的函数只有在函数原型时写,函数定义时不用,会出错。

3. 完成第9章的编程练习1,但要用正确的golf类声明替换那里的代码。用带合适参数的构造函数替换setgolf(golf&, const char*, int),以提供初始值。保留setgolf()的交互版本,但要用构造函数来实现它(例如,setgolf()的代码应该获得数据,将数据传递给构造函数来创建一个临时对象,并将其赋给调用对象,即*this)。
3.1.头文件golf10.h

  1. #ifndef GOLF_H_
  2. #define GOLF_H_
  3. #include <iostream>
  4. using namespace std;
  5. class Golf
  6. {
  7. private:
  8. static const int Len = 40;
  9. char m_fullname[Len];
  10. int m_handicap;
  11. public:
  12. Golf(const char* name, int hc);
  13. Golf();
  14. void sethandicap(int hc);
  15. void showgolf( );
  16. };
  17. #endif // !GOLF_H_

3.2.成员函数定义.cpp

  1. #include "golf10.h"
  2. #include <iostream>
  3. #include <cstring>
  4. using namespace std;
  5. Golf::Golf(const char* name, int hc)
  6. {
  7. strcpy_s(m_fullname, name);
  8. m_handicap = hc;
  9. }
  10. Golf::Golf()
  11. {
  12. char t_name[Len];
  13. int t_handicap;
  14. cout << "Please enter the fullname of player:";
  15. cin.getline(t_name, Len);
  16. cout << "Please enter the handicap of player:";
  17. cin >> t_handicap;
  18. cin.get();
  19. *this = Golf(t_name, t_handicap);
  20. }
  21. void Golf::sethandicap(int hc)
  22. {
  23. m_handicap = hc;
  24. }
  25. void Golf::showgolf()
  26. {
  27. cout << "Information:" << endl;
  28. cout << "Name: " << m_fullname << endl;
  29. cout << "handicap: " << m_handicap << endl;
  30. }

3.3.使用类.cpp

  1. #include "golf10.h"
  2. #include <iostream>
  3. using namespace std;
  4. int main(void)
  5. {
  6. golf g1;
  7. g1.showgolf();
  8. g1.sethandicap(100);
  9. g1.showgolf();
  10. golf g2("li hua", 99);
  11. g2.showgolf();
  12. g2.sethandicap(100);
  13. g2.showgolf();
  14. system("pause");
  15. return 0;
  16. }

 4.完成第九章编程练习4,但将Sales结构及相关的函数转换为一个类及其方法。用构造函数替换setSales(sales&, double[], int)函数。 用构造函数实现setSales(Sales&)方法的交互版本。将类保留在名称空间SALES中。

4.1.头文件sales.h

  1. #ifndef SALES10_H_
  2. #define SALES_H_
  3. #include <iostream>
  4. namespace SALES
  5. {
  6. class Sales
  7. {
  8. private:
  9. static const int QUARTERS = 4;
  10. double m_sales[QUARTERS];
  11. double m_average;
  12. double m_max;
  13. double m_min;
  14. public:
  15. Sales(const double ar[], int n);
  16. Sales();
  17. void showSales();
  18. };
  19. }
  20. #endif // !SALES10_H_

4.2.成员函数定义.cpp

  1. #include "sales10.h"
  2. #include <iostream>
  3. using namespace std;
  4. namespace SALES
  5. {
  6. Sales::Sales(const double ar[], int n)
  7. {
  8. if (n < 4)
  9. {
  10. for (int i = 0; i < n; i++)
  11. {
  12. m_sales[i] = ar[i];
  13. }
  14. for (int j = n; j < 4; j++)
  15. {
  16. m_sales[j] = 0;
  17. }
  18. }
  19. else
  20. {
  21. for (int i = 0; i < 4; i++)
  22. {
  23. m_sales[i] = ar[i];
  24. }
  25. }
  26. m_average = (m_sales[0] + m_sales[1] + m_sales[2] + m_sales[3]) / 4;
  27. double max = 0.0;
  28. double min = 1000000;
  29. for (int i = 0; i < 4; i++)
  30. {
  31. if (m_sales[i] > max)
  32. {
  33. max = m_sales[i];
  34. }
  35. if (m_sales[i] < min)
  36. {
  37. min = m_sales[i];
  38. }
  39. }
  40. m_max = max;
  41. m_min = min;
  42. }
  43. Sales::Sales()
  44. {
  45. cout << "Please enter sales:\n";
  46. for (int i = 0; i < 4; i++)
  47. {
  48. cout << "The #" << i + 1 << " quarter is: ";
  49. cin >> m_sales[i];
  50. }
  51. m_average = (m_sales[0] + m_sales[1] + m_sales[2] + m_sales[3]) / 4;
  52. double max = 0.0;
  53. double min = 1000000;
  54. for (int i = 0; i < 4; i++)
  55. {
  56. if (m_sales[i] > max)
  57. {
  58. max = m_sales[i];
  59. }
  60. if (m_sales[i] < min)
  61. {
  62. min = m_sales[i];
  63. }
  64. }
  65. m_max = max;
  66. m_min = min;
  67. }
  68. void Sales::showSales()
  69. {
  70. cout << "The sales of 4 quarters are $" << m_sales[0] << ", $" << m_sales[1] << ", $" << m_sales[2] << ", $" << m_sales[3] << endl;
  71. cout << "Average:" << m_average << endl;
  72. cout << "Max:" << m_max << endl;
  73. cout << "Min:" << m_min << endl;
  74. }
  75. }

4.3.使用类.cpp

  1. #include "sales10.h"
  2. #include <iostream>
  3. using namespace std;
  4. using namespace SALES;
  5. int main(void)
  6. {
  7. Sales s1;
  8. cout << "#1:" << endl;
  9. s1.showSales();
  10. cout << "--------------------------------------------------" << endl;
  11. cout << "#2"<<endl;
  12. double ar[3] = { 10,20,30 };
  13. Sales s2 = Sales( ar, 3);
  14. s2.showSales();
  15. cout << "Bye\n";
  16. system("pause");
  17. return 0;
  18. }

5. 考虑下面的结构声明:
struct customer{
    char fullname[35];
    double payment;
};
编写一个程序,它从栈中添加和删除customer结构(栈用Stack类声明表示)。每次customer结构被删除时,其payment的值都将被加入到总数中,并报告总数。
注意:应该可以直接使用Stack类而不作修改;只需修改typedef声明,使Item的类型为customer,而不是unsigned long即可。
5.1.头文件stack.h

  1. #ifndef STACK10_H_
  2. #define STACK10_H_
  3. #include <iostream>
  4. struct customer
  5. {
  6. char fullname[35];
  7. double payment;
  8. };
  9. typedef customer Item;
  10. class Stack
  11. {
  12. private:
  13. enum{MAX = 10};
  14. Item items[MAX];
  15. int top;
  16. public:
  17. Stack();
  18. bool isempty() const;
  19. bool isfull() const;
  20. bool push(const Item& item);
  21. bool pop(Item& item);
  22. };
  23. #endif // !STACK_H_

5.2.成员函数定义.cpp

  1. #include "stack10.h"
  2. Stack::Stack()
  3. {
  4. top = 0;
  5. }
  6. bool Stack::isempty() const
  7. {
  8. return top == 0;
  9. }
  10. bool Stack::isfull() const
  11. {
  12. return top == MAX;
  13. }
  14. bool Stack::push(const Item& item)
  15. {
  16. if (top < MAX)
  17. {
  18. items[top++] = item;
  19. return true;
  20. }
  21. else
  22. return false;
  23. }
  24. bool Stack::pop(Item& item)
  25. {
  26. if (top > 0)
  27. {
  28. item = items[--top];
  29. return true;
  30. }
  31. else
  32. return false;
  33. }

5.3使用类.cpp

  1. #include <iostream>
  2. #include <cctype>
  3. #include "stack10.h"
  4. using namespace std;
  5. int main(void)
  6. {
  7. Stack st;
  8. char ch;
  9. customer po;
  10. double totalpayment = 0.0;
  11. cout << "Please enter A to add a purchase order," << endl;
  12. cout << "P to process a PO,or Q to quit." << endl;
  13. while (cin >> ch && toupper(ch) != 'Q')
  14. {
  15. while (cin.get() != '\n')
  16. continue;
  17. if (!isalpha(ch))
  18. {
  19. cout << "\a";
  20. continue;
  21. }
  22. switch (ch)
  23. {
  24. case'A':
  25. case 'a':
  26. cout << "Enter the name of customer:";
  27. cin.getline(po.fullname,30);
  28. cout << "Enter the payment: ";
  29. cin >> po.payment;
  30. cin.get();
  31. if (st.isfull())
  32. cout << "Stack aleady full" << endl;
  33. else
  34. st.push(po);
  35. break;
  36. case 'P':
  37. case 'p':
  38. if (st.isempty())
  39. cout << "stack aleady empty" << endl;
  40. else
  41. {
  42. totalpayment += po.payment;
  43. st.pop(po);
  44. cout << "PO #" << po .fullname<< " popped" << endl;
  45. }
  46. break;
  47. }
  48. cout << "Please enter A to add a purchase order," << endl;
  49. cout << "P to Process a PO,or Q to quit." << endl;
  50. }
  51. cout << "Bye!" << endl;
  52. return 0;
  53. }

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

  1. #ifndef MOVE_H_
  2. #define MOVE_H_
  3. #include <iostream>
  4. class Move
  5. {
  6. private:
  7. double x;
  8. double y;
  9. public:
  10. Move(double a = 0, double b = 0);
  11. void showmove()const;
  12. Move& add(const Move& m)const;
  13. void reset(double a = 0, double b = 0);
  14. };
  15. #endif // !MOVE_H_

6.2成员函数.cpp

  1. #include "move10.h"
  2. #include <iostream>
  3. using namespace std;
  4. Move::Move(double a , double b)
  5. {
  6. x = a;
  7. y = b;
  8. }
  9. void Move::showmove()const
  10. {
  11. cout << "x = " << x << endl;
  12. cout << "y = " << y << endl;
  13. }
  14. Move& Move::add(const Move& m)const
  15. {
  16. Move new_m;
  17. new_m.x = m.x + this->x;
  18. new_m.y = m.y + this->y;
  19. return new_m;
  20. }
  21. void Move::reset(double a , double b )
  22. {
  23. x = a;
  24. y = b;
  25. }

6.3使用类.cpp

  1. #include "move10.h"
  2. #include <iostream>
  3. using namespace std;
  4. int main(void)
  5. {
  6. Move a;
  7. Move b = Move(120, 60);
  8. a.showmove();
  9. b.showmove();
  10. Move c = a.add(b);
  11. c.showmove();
  12. a = b.add(c);
  13. a.showmove();
  14. a.reset();
  15. a.showmove();
  16. system("pasue");
  17. return 0;
  18. }

7. Betelgeusean plorg有这些特征。
数据:
    ·plorg的名称不超过19个字符
    ·plorg的满意指数(CI),这是一个整数
操作:
    ·新的plorg将有名称,其CI值为50
    ·plorg的CI可以修改
    ·plorg可以报告其名称和CI
请编写一个Plorg类声明(包括数据成员和成员函数原型)来表示plorg,并编写成员函数的函数定义。然后编写一个小程序,以演示Plorg类的所有特性。

7.1.头文件plorg10.h

  1. #ifndef PLORG_H_
  2. #include <iostream>
  3. class Plorg
  4. {
  5. private:
  6. static const int Len = 20;
  7. char m_name[Len];
  8. int m_CI;
  9. public:
  10. Plorg();
  11. void SetName(const char* name);
  12. void SetCI(int CI);
  13. void showPlorg();
  14. };
  15. #endif // !PLORGA_H_

7.2.成员函数定义.cpp

  1. #include "plorg10.h"
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;
  5. Plorg::Plorg()
  6. {
  7. strcpy_s(m_name,Len, "Plorga");
  8. m_CI = 0;
  9. }
  10. void Plorg::SetName(const char *name)
  11. {
  12. strcpy_s(m_name,Len, name);
  13. m_CI = 50;
  14. }
  15. void Plorg::SetCI(int CI)
  16. {
  17. m_CI = CI;
  18. }
  19. void Plorg::showPlorg()
  20. {
  21. cout << "The current information is as follows:" << endl;
  22. cout << "Name: " << m_name << endl;
  23. cout << "CI: " << m_CI << endl;
  24. }

7.3.使用类.cpp

  1. #include "plorg10.h"
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;
  5. int main(void)
  6. {
  7. Plorg p;
  8. p.showPlorg();
  9. p.SetName("LI Hua");
  10. p.showPlorg();
  11. p.SetCI(20);
  12. p.showPlorg();
  13. system("pause");
  14. return 0;
  15. }

8. 可以将简单列表描述成下面这样
 ·可存储0或多个某种类型的列表
 ·可创建空列表
 ·可在列表中添加数据项
 ·可确定列表是否为空
 ·可确定列表是否为满
 ·可访问列表中的每一个数据项,并对它执行某种操作
 可以看到,这个列表确实很简单,例如,它不允许插入或删除数据项
 请设计一个List类来表示这种抽象类型。您应提供头文件list.h和实现文件list.cpp,前者包含类定义,后者包含类方法的实现。您还应该创建一个简短的程序来使用这个类
 该列表的规范很简单,这个主要旨在简化这个编程练习。可以选择使用数组或链表来实现该列表,但公有接口不应依赖于所做的选择。也就是说,公有接口不应有数组索引、节点指针等。
 应使用通用概念来表达创建列表、在列表中添加数据项等操作。对于访问数据项以及执行操作,通常应使用将函数指针作为参数的函数来处理:void visit(void (*pf)(Item &));
 其中。pf指向一个将Item引用作为参数的函数(而不是成员函数),Item是列表中数据项的类型。visit()函数将该函数用于列表中的每个数据项。

8.1头文件list.h

  1. #ifndef LIST_H_
  2. #define LIST_H_
  3. #include <iostream>
  4. #include <string>
  5. using namespace std;
  6. struct customer
  7. {
  8. string name;
  9. double consumption;
  10. };
  11. typedef customer Item;
  12. class List
  13. {
  14. private:
  15. static const int Len = 20;
  16. Item items[Len];
  17. int top = 0;
  18. public:
  19. List();
  20. bool isempty() const;
  21. bool isfull() const;
  22. bool add(const Item& item);
  23. void visit(void(*pf)(Item& item));
  24. void showitem() const;
  25. };
  26. void turnover(Item& item); //计算总营业额(列表中所有顾客消费额相加)
  27. #endif // !LIST_H_

8.2list.cpp

  1. #include "list10.h"
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;
  5. double Sum = 0.0;
  6. List::List()
  7. {
  8. top = 0;
  9. }
  10. bool List::isempty() const
  11. {
  12. return top == 0;
  13. }
  14. bool List::isfull() const
  15. {
  16. return top == Len;
  17. }
  18. bool List::add(const Item& item)
  19. {
  20. if (top < Len)
  21. {
  22. items[top++] = item;
  23. return true;
  24. }
  25. else
  26. return false;
  27. }
  28. void List::showitem() const
  29. {
  30. for (int i = 0; i < top; i++)
  31. {
  32. cout << "#" << i + 1 <<":"<< endl;
  33. cout << "Name: " << items[i].name << endl;
  34. cout << "Consumption: " << items[i].consumption << endl;
  35. }
  36. }
  37. void List::visit(void(*pf)(Item& item))
  38. {
  39. for (int i = 0; i < top; i++)
  40. {
  41. pf(items[i]);
  42. }
  43. }
  44. void turnover(Item& item)
  45. {
  46. Sum += item.consumption;
  47. }

8.3使用类.cpp
 

  1. #include "list10.h"
  2. #include <iostream>
  3. using namespace std;
  4. extern double Sum;
  5. int main(void)
  6. {
  7. List st;
  8. char ch;
  9. customer po;
  10. cout << "Please enter A to add a purchase order,V to caculate the turnover,S to show the items,or Q to quit." << endl;
  11. while (cin >> ch && toupper(ch) != 'Q')
  12. {
  13. while (cin.get() != '\n')
  14. continue;
  15. if (!isalpha(ch))
  16. {
  17. cout << "\a";
  18. continue;
  19. }
  20. switch (ch)
  21. {
  22. case'A':
  23. case 'a':
  24. cout << "Enter the name of customer:";
  25. getline(cin, po.name);
  26. cout << "Enter the payment: ";
  27. cin >> po.consumption;
  28. cin.get();
  29. if (st.isfull())
  30. cout << "List aleady full" << endl;
  31. else
  32. st.add(po);
  33. break;
  34. case 'S':
  35. case 's':
  36. st.showitem();
  37. break;
  38. case 'V':
  39. case 'v':
  40. if (st.isempty())
  41. {
  42. cout << "List is empty." << endl;
  43. cout << "Sum = 0" << endl;
  44. }
  45. else
  46. {
  47. st.visit(turnover);
  48. cout <<"Sum = "<< Sum << endl;
  49. }
  50. }
  51. cout << "Please enter A to add a purchase order,V to caculate the turnover,S to show the items,or Q to quit." << endl;
  52. }
  53. cout << "Bye!" << endl;
  54. system("pause");
  55. return 0;
  56. }

总结(注意事项):

  1. 文件间通用一个变量的方法是在一个文件中将其定义为全局变量后,其他文件使用关键字extern。
  2. 注意使用函数指针做参数的用法。

第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

  1. #ifndef VECTOR_H_
  2. #define VECTOR_H_
  3. #include <iostream>
  4. namespace VECTOR
  5. {
  6. class Vector
  7. {
  8. public:
  9. enum Mode{RECT,POL};
  10. private:
  11. double x;
  12. double y;
  13. double mag;
  14. double ang;
  15. Mode mode;
  16. void set_mag();
  17. void set_ang();
  18. void set_x();
  19. void set_y();
  20. public:
  21. Vector();
  22. Vector(double n1, double n2, Mode from = RECT);
  23. void reset(double n1, double n2, Mode from = RECT);
  24. ~Vector();
  25. double xval()const { return x; };
  26. double yval()const { return y; };
  27. double magval() const { return mag; };
  28. double angval()const { return ang; };
  29. void polar_mode();
  30. void rect_mode();
  31. Vector operator+(const Vector& b)const;
  32. Vector operator-(const Vector& b)const;
  33. Vector operator-()const;
  34. Vector operator*(double n)const;
  35. friend Vector operator*(double n, const Vector& a);
  36. friend std::ostream& operator<<(std::ostream& os, const Vector& v);
  37. };
  38. }
  39. #endif // !VECTOR_H_

1.2成员函数定义.cpp

  1. #include "vector11.h"
  2. #include <iostream>
  3. #include <cmath>
  4. using namespace std;
  5. namespace VECTOR
  6. {
  7. const double Rad_to_deg = 45.0 / atan(1.0);
  8. void Vector::set_mag()
  9. {
  10. mag = sqrt(x * x + y * y);
  11. }
  12. void Vector::set_ang()
  13. {
  14. if (x == 0 && y == 0)
  15. {
  16. ang = 0.0;
  17. }
  18. else
  19. ang = atan2(y, x);
  20. }
  21. void Vector::set_x()
  22. {
  23. x = mag * cos(ang);
  24. }
  25. void Vector::set_y()
  26. {
  27. y = mag * sin(ang);
  28. }
  29. Vector::Vector()
  30. {
  31. x = y = mag = ang = 0.0;
  32. mode = RECT;
  33. }
  34. Vector::Vector(double n1, double n2, Mode from)
  35. {
  36. mode = from;
  37. if (from == RECT)
  38. {
  39. x = n1;
  40. y = n2;
  41. set_ang();
  42. set_mag();
  43. }
  44. else if(from == POL)
  45. {
  46. mag = n1;
  47. ang = n2 / Rad_to_deg;
  48. set_x();
  49. set_y();
  50. }
  51. else
  52. {
  53. cout << "Incorrect 3rd argument to Vector()--";
  54. cout << "vector set to 0" << endl;
  55. x = y = mag = ang = 0.0;
  56. mode = RECT;
  57. }
  58. }
  59. void Vector::reset(double n1, double n2, Mode from)
  60. {
  61. mode = from;
  62. if (from == RECT)
  63. {
  64. x = n1;
  65. y = n2;
  66. set_mag();
  67. set_ang();
  68. }
  69. else if (from == POL)
  70. {
  71. mag = n1;
  72. ang = n2 / Rad_to_deg;
  73. set_x();
  74. set_y();
  75. }
  76. else
  77. {
  78. cout << "Incorrect 3rd argument to Vector()--";
  79. cout << "vector set to 0" << endl;
  80. x = y = mag = ang = 0.0;
  81. mode = RECT;
  82. }
  83. }
  84. Vector::~Vector()
  85. {
  86. }
  87. void Vector::polar_mode()
  88. {
  89. mode = POL;
  90. }
  91. void Vector::rect_mode()
  92. {
  93. mode = RECT;
  94. }
  95. Vector Vector::operator+(const Vector& b)const
  96. {
  97. return Vector(x + b.x, y + b.y);
  98. }
  99. Vector Vector::operator-(const Vector& b)const
  100. {
  101. return Vector(x - b.x, y - b.y);
  102. }
  103. Vector Vector::operator-()const
  104. {
  105. return Vector(-x, -y);
  106. }
  107. Vector Vector::operator*(double n)const
  108. {
  109. return Vector(n * x, n * y);
  110. }
  111. Vector operator*(double n, const Vector& a)
  112. {
  113. return a * n;
  114. }
  115. ostream& operator<<(ostream& os, const Vector& v)
  116. {
  117. if (v.mode == Vector::RECT)
  118. os << "(x,y) = (" << v.x << "," << v.y << ")";
  119. else if (v.mode == Vector::POL)
  120. os << "(m,a) = (" << v.mag << "," << v.ang << ")";
  121. else
  122. os << "Vector object mode is invalid";
  123. return os;
  124. }
  125. }

1.3使用类.cpp

  1. #include <iostream>
  2. #include <cstdlib> //rand()、srand()
  3. #include <ctime> //time()
  4. #include "vector11.h"
  5. #include <fstream>
  6. using namespace std;
  7. int main()
  8. {
  9. using VECTOR::Vector;
  10. ofstream outFile;
  11. outFile.open("11.1randwalker.txt");
  12. srand(time(0));
  13. double direction;
  14. Vector step;
  15. Vector result(0.0, 0.0);
  16. unsigned long steps = 0;
  17. double target;
  18. double dstep;
  19. cout << "Enter target distance:(q to quit)";
  20. while (cin >> target)
  21. {
  22. cout << "Enter step length:";
  23. if (!(cin >> dstep))
  24. break;
  25. outFile<< "Target Distance: " << target << ", " << "Step Size: " << dstep << endl;
  26. while (result.magval() < target)
  27. {
  28. outFile << steps << ": " << result << endl;
  29. direction = rand() % 360;
  30. step.reset(dstep, direction, Vector::POL);
  31. result = result + step;
  32. steps++;
  33. }
  34. cout << "After " << steps << " steps,the subject ""has the following location:" << endl;
  35. outFile << "After " << steps << " steps,the subject ""has the following location:" << endl;
  36. cout << result << endl;
  37. outFile << result << endl;
  38. result.polar_mode();
  39. cout << " or\n" << result << endl;
  40. cout << "Average outward distance per step = " << result.magval() / steps << endl;
  41. outFile << " or\n" << result << endl;
  42. outFile << "Average outward distance per step = " << result.magval() / steps << endl;
  43. steps = 0;
  44. result.reset(0.0, 0.0);
  45. cout << "Enter target distance(q to quit):";
  46. }
  47. cout << "Bye!" << endl;
  48. cin.clear();
  49. while (cin.get() != '\n')
  50. continue;
  51. outFile.close();
  52. system("pause");
  53. return 0;
  54. }

结果展示:


2.对于Vector类的头文件(程序清单11.13)和实现文件(程序清单11.14)进行修改,使其不再储存矢量的长度和角度,而是在magval()和angval()被调用时计算它们。
应保留公有接口不变(公有方法及其参数不变),但对私有部分(包括一些私有方法)和方法实现进行修改。然后,使用程序清单11.15对修改后的版本进行测试,结果应该与以前相同,因为Vecotr类的公有接口与原来相同。

2.1头文件vector112.h有修改,删除了两个私有变量,修改了两个私有成员函数。

  1. #ifndef VECTOR112_H_
  2. #define VECTOR112_H_
  3. #include <iostream>
  4. namespace VECTOR
  5. {
  6. class Vector
  7. {
  8. public:
  9. enum Mode { RECT, POL };
  10. private:
  11. double x;
  12. double y;
  13. Mode mode;
  14. double set_mag();
  15. double set_ang();
  16. void set_x(double mag, double ang);
  17. void set_y(double mag, double ang);
  18. public:
  19. Vector();
  20. Vector(double n1, double n2, Mode from = RECT);
  21. void reset(double n1, double n2, Mode from = RECT);
  22. ~Vector();
  23. double xval()const { return x; };
  24. double yval()const { return y; };
  25. double magval() const;
  26. double angval()const;
  27. void polar_mode();
  28. void rect_mode();
  29. Vector operator+(const Vector& b)const;
  30. Vector operator-(const Vector& b)const;
  31. Vector operator-()const;
  32. Vector operator*(double n)const;
  33. friend Vector operator*(double n, const Vector& a);
  34. friend std::ostream& operator<<(std::ostream& os, const Vector& v);
  35. };
  36. }
  37. #endif // !VECTOR_H_

2.2成员函数定义.cpp (有修改)

  1. #include "vector112.h"
  2. #include <iostream>
  3. #include <cmath>
  4. using namespace std;
  5. namespace VECTOR
  6. {
  7. const double Rad_to_deg = 45.0 / atan(1.0);
  8. double Vector::set_mag()
  9. {
  10. double mag;
  11. mag = sqrt(x * x + y * y);
  12. return mag;
  13. }
  14. double Vector::set_ang()
  15. {
  16. double ang;
  17. if (x == 0 && y == 0)
  18. {
  19. ang = 0.0;
  20. }
  21. else
  22. ang = atan2(y, x);
  23. return ang;
  24. }
  25. void Vector::set_x(double mag,double ang)
  26. {
  27. x = mag * cos(ang);
  28. }
  29. void Vector::set_y(double mag,double ang)
  30. {
  31. y = mag * sin(ang);
  32. }
  33. Vector::Vector()
  34. {
  35. x = y = 0;
  36. mode = RECT;
  37. }
  38. Vector::Vector(double n1, double n2, Mode from)
  39. {
  40. mode = from;
  41. if (from == RECT)
  42. {
  43. x = n1;
  44. y = n2;
  45. set_mag();
  46. set_ang();
  47. }
  48. else if(from == POL)
  49. {
  50. double mag, ang;
  51. mag = n1;
  52. ang = n2 / Rad_to_deg;
  53. set_x(mag,ang);
  54. set_y(mag,ang);
  55. }
  56. else
  57. {
  58. cout << "Incorrect 3rd argument to Vector()--";
  59. cout << "vector set to 0" << endl;
  60. x = y = 0.0;
  61. mode = RECT;
  62. }
  63. }
  64. void Vector::reset(double n1, double n2, Mode from)
  65. {
  66. mode = from;
  67. if (from == RECT)
  68. {
  69. x = n1;
  70. y = n2;
  71. }
  72. else if (from == POL)
  73. {
  74. double mag, ang;
  75. mag = n1;
  76. ang = n2 / Rad_to_deg;
  77. set_x(mag,ang);
  78. set_y(mag,ang);
  79. }
  80. else
  81. {
  82. cout << "Incorrect 3rd argument to Vector()--";
  83. cout << "vector set to 0" << endl;
  84. x = y = 0.0;
  85. mode = RECT;
  86. }
  87. }
  88. Vector::~Vector()
  89. {
  90. }
  91. double Vector::magval() const
  92. {
  93. double mag;
  94. mag = sqrt(x * x + y * y);
  95. return mag;
  96. }
  97. double Vector::angval() const
  98. {
  99. double ang;
  100. if (x == 0.0 && y == 0.0)
  101. ang = 0.0;
  102. else
  103. ang = atan2(y, x);
  104. return ang;
  105. }
  106. void Vector::polar_mode()
  107. {
  108. mode = POL;
  109. }
  110. void Vector::rect_mode()
  111. {
  112. mode = RECT;
  113. }
  114. Vector Vector::operator+(const Vector& b)const
  115. {
  116. return Vector(x + b.x, y + b.y);
  117. }
  118. Vector Vector::operator-(const Vector& b)const
  119. {
  120. return Vector(x - b.x, y - b.y);
  121. }
  122. Vector Vector::operator-()const
  123. {
  124. return Vector(-x, -y);
  125. }
  126. Vector Vector::operator*(double n)const
  127. {
  128. return Vector(n * x, n * y);
  129. }
  130. Vector operator*(double n, const Vector& a)
  131. {
  132. return a * n;
  133. }
  134. ostream& operator<<(ostream& os, const Vector& v)
  135. {
  136. if (v.mode == Vector::RECT)
  137. os << "(x,y) = (" << v.x << "," << v.y << ")";
  138. else if (v.mode == Vector::POL)
  139. os << "(m,a) = (" << v.magval()<< "," << v.angval() << ")";
  140. else
  141. os << "Vector object mode is invalid";
  142. return os;
  143. }
  144. }

2.3使用类main函数(无修改)

  1. #include <iostream>
  2. #include <cstdlib> //rand()、srand()
  3. #include <ctime> //time()
  4. #include "vector112.h"
  5. using namespace std;
  6. int main()
  7. {
  8. using VECTOR::Vector;
  9. srand(time(0));
  10. double direction;
  11. Vector step;
  12. Vector result(0.0, 0.0);
  13. unsigned long steps = 0;
  14. double target;
  15. double dstep;
  16. cout << "Enter target distance:(q to quit)";
  17. while (cin >> target)
  18. {
  19. cout << "Enter step length:";
  20. if (!(cin >> dstep))
  21. break;
  22. while (result.magval() < target)
  23. {
  24. direction = rand() % 360;
  25. step.reset(dstep, direction, Vector::POL);
  26. result = result + step;
  27. steps++;
  28. }
  29. cout << "After " << steps << " steps,the subject ""has the following location:" << endl;
  30. cout << result << endl;
  31. result.polar_mode();
  32. cout << " or\n" << result << endl;
  33. cout << "Average outward distance per step = " << result.magval() / steps << endl;
  34. steps = 0;
  35. result.reset(0.0, 0.0);
  36. cout << "Enter target distance(q to quit):";
  37. }
  38. cout << "Bye!" << endl;
  39. cin.clear();
  40. while (cin.get() != '\n')
  41. continue;
  42. system("pause");
  43. return 0;
  44. }

3. 修改程序清单11.15,使之报告N次测试中的最高、最低和平均步数(其中N是用户输入的整数),而不是报告每次测试的结果。

3.1头文件vector113.h同上题

  1. #ifndef VECTOR112_H_
  2. #define VECTOR112_H_
  3. #include <iostream>
  4. namespace VECTOR
  5. {
  6. class Vector
  7. {
  8. public:
  9. enum Mode { RECT, POL };
  10. private:
  11. double x;
  12. double y;
  13. Mode mode;
  14. double set_mag();
  15. double set_ang();
  16. void set_x(double mag, double ang);
  17. void set_y(double mag, double ang);
  18. public:
  19. Vector();
  20. Vector(double n1, double n2, Mode from = RECT);
  21. void reset(double n1, double n2, Mode from = RECT);
  22. ~Vector();
  23. double xval()const { return x; };
  24. double yval()const { return y; };
  25. double magval() const;
  26. double angval()const;
  27. void polar_mode();
  28. void rect_mode();
  29. Vector operator+(const Vector& b)const;
  30. Vector operator-(const Vector& b)const;
  31. Vector operator-()const;
  32. Vector operator*(double n)const;
  33. friend Vector operator*(double n, const Vector& a);
  34. friend std::ostream& operator<<(std::ostream& os, const Vector& v);
  35. };
  36. }
  37. #endif // !VECTOR_H_

3.2成员函数定义.cpp同上题

  1. #include "vector113.h"
  2. #include <iostream>
  3. #include <cmath>
  4. using namespace std;
  5. namespace VECTOR
  6. {
  7. const double Rad_to_deg = 45.0 / atan(1.0);
  8. double Vector::set_mag()
  9. {
  10. double mag;
  11. mag = sqrt(x * x + y * y);
  12. return mag;
  13. }
  14. double Vector::set_ang()
  15. {
  16. double ang;
  17. if (x == 0 && y == 0)
  18. {
  19. ang = 0.0;
  20. }
  21. else
  22. ang = atan2(y, x);
  23. return ang;
  24. }
  25. void Vector::set_x(double mag,double ang)
  26. {
  27. x = mag * cos(ang);
  28. }
  29. void Vector::set_y(double mag,double ang)
  30. {
  31. y = mag * sin(ang);
  32. }
  33. Vector::Vector()
  34. {
  35. x = y = 0;
  36. mode = RECT;
  37. }
  38. Vector::Vector(double n1, double n2, Mode from)
  39. {
  40. mode = from;
  41. if (from == RECT)
  42. {
  43. x = n1;
  44. y = n2;
  45. set_mag();
  46. set_ang();
  47. }
  48. else if(from == POL)
  49. {
  50. double mag, ang;
  51. mag = n1;
  52. ang = n2 / Rad_to_deg;
  53. set_x(mag,ang);
  54. set_y(mag,ang);
  55. }
  56. else
  57. {
  58. cout << "Incorrect 3rd argument to Vector()--";
  59. cout << "vector set to 0" << endl;
  60. x = y = 0.0;
  61. mode = RECT;
  62. }
  63. }
  64. void Vector::reset(double n1, double n2, Mode from)
  65. {
  66. mode = from;
  67. if (from == RECT)
  68. {
  69. x = n1;
  70. y = n2;
  71. }
  72. else if (from == POL)
  73. {
  74. double mag, ang;
  75. mag = n1;
  76. ang = n2 / Rad_to_deg;
  77. set_x(mag,ang);
  78. set_y(mag,ang);
  79. }
  80. else
  81. {
  82. cout << "Incorrect 3rd argument to Vector()--";
  83. cout << "vector set to 0" << endl;
  84. x = y = 0.0;
  85. mode = RECT;
  86. }
  87. }
  88. Vector::~Vector()
  89. {
  90. }
  91. double Vector::magval() const
  92. {
  93. double mag;
  94. mag = sqrt(x * x + y * y);
  95. return mag;
  96. }
  97. double Vector::angval() const
  98. {
  99. double ang;
  100. if (x == 0.0 && y == 0.0)
  101. ang = 0.0;
  102. else
  103. ang = atan2(y, x);
  104. return ang;
  105. }
  106. void Vector::polar_mode()
  107. {
  108. mode = POL;
  109. }
  110. void Vector::rect_mode()
  111. {
  112. mode = RECT;
  113. }
  114. Vector Vector::operator+(const Vector& b)const
  115. {
  116. return Vector(x + b.x, y + b.y);
  117. }
  118. Vector Vector::operator-(const Vector& b)const
  119. {
  120. return Vector(x - b.x, y - b.y);
  121. }
  122. Vector Vector::operator-()const
  123. {
  124. return Vector(-x, -y);
  125. }
  126. Vector Vector::operator*(double n)const
  127. {
  128. return Vector(n * x, n * y);
  129. }
  130. Vector operator*(double n, const Vector& a)
  131. {
  132. return a * n;
  133. }
  134. ostream& operator<<(ostream& os, const Vector& v)
  135. {
  136. if (v.mode == Vector::RECT)
  137. os << "(x,y) = (" << v.x << "," << v.y << ")";
  138. else if (v.mode == Vector::POL)
  139. os << "(m,a) = (" << v.magval()<< "," << v.angval() << ")";
  140. else
  141. os << "Vector object mode is invalid";
  142. return os;
  143. }
  144. }

3.3使用类.cpp做修改

  1. #include <iostream>
  2. #include <cstdlib> //rand()、srand()
  3. #include <ctime> //time()
  4. #include "vector113.h"
  5. using namespace std;
  6. int main()
  7. {
  8. using VECTOR::Vector;
  9. srand(time(0));
  10. double direction;
  11. Vector step;
  12. Vector result(0.0, 0.0);
  13. unsigned long steps = 0;
  14. double target;
  15. double dstep;
  16. int max = 0;
  17. int min = 100000;
  18. int sum = 0;
  19. double average = 0.0;
  20. int N;
  21. cout << "Test times:";
  22. cin >> N;
  23. for (int i = 0; i < N; i++)
  24. {
  25. cout << "Enter target distance:(q to quit)";
  26. cin >> target;
  27. cout << "Enter step length:";
  28. cin >> dstep;
  29. while (result.magval() < target)
  30. {
  31. direction = rand() % 360;
  32. step.reset(dstep, direction, Vector::POL);
  33. result = result + step;
  34. steps++;
  35. }
  36. cout << "# "<<i+1<<":"<<"After " << steps << " the subject reach destination." << endl;
  37. max = max > steps ? max : steps;
  38. min = min < steps ? min : steps;
  39. sum += steps;
  40. steps = 0;
  41. result.reset(0.0, 0.0);
  42. }
  43. average = double(sum) / N;
  44. cout << "The max steps is: " << max << endl;
  45. cout << "The min steps is: " << min << endl;
  46. cout << "The average steps is: " << average << endl;
  47. cout << "Bye!" << endl;
  48. cin.clear();
  49. system("pause");
  50. return 0;
  51. }

4.重新编写最后的Time类示例(程序清单11.10、程序清单11.11和程序清单11.12),使用友元函数来实现所有的重载运算符。

4.1头文件mytime114.h

  1. #ifndef MYTIME114_H_
  2. #define MYTIME114_H_
  3. #include <iostream>
  4. class Time
  5. {
  6. private:
  7. int hours;
  8. int minutes;
  9. public:
  10. Time();
  11. Time(int h, int m = 0);
  12. void AddMin(int m);
  13. void AddHr(int h);
  14. void Reset(int h = 0, int m = 0);
  15. friend Time operator+(const Time& t1,const Time &t2);
  16. friend Time operator-(const Time& t1,const Time &t2);
  17. friend Time operator*(const Time & t,double mult);
  18. friend Time operator* (double m, const Time& t) { return t * m; }
  19. friend std::ostream& operator<< (std::ostream & os, const Time & t);
  20. };
  21. #endif

4.2成员函数定义.cpp

  1. #include "mytime114.h"
  2. #include <iostream>
  3. Time::Time()
  4. {
  5. hours = minutes = 0;
  6. }
  7. Time::Time(int h, int m)
  8. {
  9. hours = h;
  10. minutes = m;
  11. }
  12. void Time::AddMin(int m)
  13. {
  14. hours += m;
  15. hours += minutes / 10;
  16. minutes %= 60;
  17. }
  18. void Time::AddHr(int h)
  19. {
  20. hours += h;
  21. }
  22. void Time::Reset(int h, int m)
  23. {
  24. hours = h;
  25. minutes = m;
  26. }
  27. Time operator+(const Time& t1, const Time& t2)
  28. {
  29. Time sum;
  30. sum.minutes =t1.minutes + t2.minutes;
  31. sum.hours = t1.hours + t2.hours + sum.minutes / 60;
  32. sum.minutes %= 60;
  33. return sum;
  34. }
  35. Time operator-(const Time& t1, const Time& t2)
  36. {
  37. Time diff;
  38. int tot1, tot2;
  39. tot1 = t1.minutes + 60 * t1.hours;
  40. tot2 = t2.minutes + 60 *t2. hours;
  41. diff.hours = (tot2 - tot1) / 60;
  42. diff.minutes = (tot2 - tot1) % 60;
  43. return diff;
  44. }
  45. Time operator*(const Time& t, double mult)
  46. {
  47. Time result;
  48. long totalminutes = t.hours * mult * 60 + t.minutes * mult;
  49. result.hours = totalminutes / 60;
  50. result.minutes = totalminutes % 60;
  51. return result;
  52. }
  53. std::ostream& operator<< (std::ostream& os, const Time& t)
  54. {
  55. os << t.hours << "hours, " << t.minutes << " minutes";
  56. return os;
  57. }

4.3使用类.cpp(不改变,与程序清单11.12相同)

  1. #include "mytime114.h"
  2. #include <iostream>
  3. int main(void)
  4. {
  5. using std::cout;
  6. using std::endl;
  7. Time aida(3, 25);
  8. Time tosca(2, 48);
  9. Time temp;
  10. cout << "Aida and Tosca:" << endl;
  11. cout << aida << " ; " << tosca << endl;
  12. temp = aida + tosca;
  13. cout << "Aida + Tosca: " << temp << endl;
  14. temp = aida * 1.17;
  15. cout << "Aida * 1.17: " << temp << endl;
  16. cout << "10.0*Tosca: " << 10.0 * tosca << endl;
  17. system("pause");
  18. return 0;
  19. }

5.重新编写Stonewt类(程序清单11.16和程序清单11.17),使它有一个状态成员,由该状态成员控制对象应转换为英石格式、整数磅格式还是浮点磅格式。重载<<运算符,使用它来替换show_stn()和show_lbs()方法。重载加法、减法和乘发运算符,以便可以对Stonewt值进行加、减、乘运算。编写一个使用所有类方法和友元的小程序,来测试这个类。

5.1头文件stonewt115.h

  1. #ifndef STONEWT115_H_
  2. #define STONEWT115_H_
  3. #include <iostream>
  4. class Stonewt
  5. {
  6. public:
  7. enum Format { st, intp, doublep };
  8. private:
  9. enum { Lbs_per_stn = 14 };
  10. int stone;
  11. double pds_left;
  12. double pounds;
  13. Format m_form;
  14. public:
  15. Stonewt(double lbs);
  16. Stonewt(int stn, double lbs);
  17. Stonewt();
  18. ~Stonewt();
  19. void SetFormat(Format form);
  20. Stonewt operator+ (const Stonewt& s)const;
  21. Stonewt operator- (const Stonewt& s)const;
  22. Stonewt operator* (double n)const;
  23. friend Stonewt operator*(double m, const Stonewt& s){return s * m;}
  24. friend std::ostream& operator<< (std::ostream& os, const Stonewt& s);
  25. };
  26. #endif

5.2成员函数定义.cpp

  1. #include "stonewt115.h"
  2. #include <iostream>
  3. Stonewt::Stonewt(double lbs)
  4. {
  5. stone = int(lbs) / Lbs_per_stn;
  6. pds_left = int(lbs) % Lbs_per_stn + lbs - int(lbs);
  7. pounds = lbs;
  8. m_form = st;
  9. }
  10. Stonewt::Stonewt(int stn, double lbs)
  11. {
  12. stone = stn;
  13. pds_left = lbs;
  14. pounds = stn * Lbs_per_stn + lbs;
  15. m_form = intp;
  16. }
  17. Stonewt::Stonewt()
  18. {
  19. stone = pounds = pds_left = 0;
  20. m_form = doublep;
  21. }
  22. Stonewt::~Stonewt()
  23. {
  24. }
  25. void Stonewt::SetFormat(Format from)
  26. {
  27. m_form = from;
  28. }
  29. Stonewt Stonewt::operator+ (const Stonewt& s)const
  30. {
  31. Stonewt sum;
  32. sum.pounds = pounds + s.pounds;
  33. sum.stone = int(sum.pounds) / Lbs_per_stn;
  34. sum.pds_left = int(sum.pounds) % Lbs_per_stn + sum.pounds - int(sum.pounds);
  35. return sum;
  36. }
  37. Stonewt Stonewt::operator- (const Stonewt& s)const
  38. {
  39. Stonewt diff;
  40. diff.pounds = pounds - s.pounds;
  41. diff.stone = int(diff.pounds) / Lbs_per_stn;
  42. diff.pds_left = int(diff.pounds) % Lbs_per_stn + diff.pounds - int(diff.pounds);
  43. return diff;
  44. }
  45. Stonewt Stonewt::operator* (double n)const
  46. {
  47. double mult;
  48. mult = pounds * n;
  49. return Stonewt(mult);
  50. }
  51. std::ostream& operator<< (std::ostream& os, const Stonewt& s)
  52. {
  53. if (s.m_form == Stonewt::st)
  54. {
  55. os << s.stone << " stone, " << s.pds_left << " pounds\n";
  56. }
  57. else if (s.m_form == Stonewt::intp)
  58. {
  59. os << int(s.pounds) << " pounds\n";
  60. }
  61. else if (s.m_form == Stonewt::doublep)
  62. {
  63. os << s.pounds << " pounds\n";
  64. }
  65. else
  66. os << "Stonewt state is invalid";
  67. return os;
  68. }

5.3使用类.cpp

  1. #include "stonewt115.h"
  2. #include <iostream>
  3. using std::cout;
  4. using std::cin;
  5. int main(void)
  6. {
  7. Stonewt incognito = 275;
  8. Stonewt wolfe(285.7);
  9. Stonewt taft(21, 8);
  10. cout << "The celebrity weighed: " << incognito ; //st
  11. cout << "The detective weighed: " << wolfe; //st
  12. cout << "The President weighed: " << taft << "\n"; //intp
  13. Stonewt tf(2);
  14. Stonewt sum, diff, mult;
  15. sum = incognito + tf;
  16. diff = wolfe - tf;
  17. mult = taft * 2;
  18. cout << "The result will display as double_pounds: \n";
  19. cout << "After dinner, the celebrity weighed: ";
  20. sum.SetFormat(Stonewt::doublep);
  21. cout << sum;
  22. cout << "After sport, the detective weighed: ";
  23. diff.SetFormat(Stonewt::doublep);
  24. cout << diff;
  25. cout << "Now,the President weighed: ";
  26. mult.SetFormat(Stonewt::doublep);
  27. cout << mult;
  28. system("pause");
  29. return 0;
  30. }

6.重新编写Stonewt类(程序清单11.16和程序清单11.17),重载全部6个关系运算符。运算符对pounds成员进行比较,并返回一个bool值。编写一个程序,它声明一个包含6个Stonewt对象的数组,并在数组声明中初始化前3个对象。然后使用循环来读取用于设置剩余3个数组元素的值。接着报告最小的元素、最大的元素以及大于或等于11英石的元素的数量(最简单的方法是创建一个Stonewt对象,并将其初始化为11英石,然后将其同其他对象进行比较)。

6.1头文件stonewt116.ch

  1. #ifndef STONEWT116_H_
  2. #define STONEWT116_H_
  3. #include <iostream>
  4. class Stonewt
  5. {
  6. public:
  7. enum Format { st, intp, doublep };
  8. private:
  9. enum { Lbs_per_stn = 14 };
  10. int stone;
  11. double pds_left;
  12. double pounds;
  13. Format state;
  14. public:
  15. Stonewt(double lbs);
  16. Stonewt(int stn, double lbs);
  17. Stonewt();
  18. ~Stonewt();
  19. void Setstate(Format x);
  20. friend bool operator>(const Stonewt& s1, const Stonewt& s2);
  21. friend bool operator<(const Stonewt& s1, const Stonewt& s2);
  22. friend bool operator>=(const Stonewt& s1, const Stonewt& s2);
  23. friend bool operator<=(const Stonewt& s1, const Stonewt& s2);
  24. friend bool operator==(const Stonewt& s1, const Stonewt& s2);
  25. friend bool operator!=(const Stonewt& s1, const Stonewt& s2);
  26. friend std::ostream& operator<< (std::ostream& os, const Stonewt& s);
  27. };
  28. #endif

6.2成员函数定义.cpp

  1. #include "stonewt116.h"
  2. #include <iostream>
  3. using std::cout;
  4. using std::endl;
  5. using namespace std;
  6. Stonewt::Stonewt(double lbs)
  7. {
  8. stone = int(lbs) / Lbs_per_stn;
  9. pds_left = int(lbs) % Lbs_per_stn + lbs - int(lbs);
  10. pounds = lbs;
  11. state = st;
  12. }
  13. Stonewt::Stonewt(int stn, double lbs)
  14. {
  15. stone = stn;
  16. pds_left = lbs;
  17. pounds = stn * Lbs_per_stn + lbs;
  18. state = st;
  19. }
  20. Stonewt::Stonewt()
  21. {
  22. stone = pounds = pds_left = 0;
  23. state = st;
  24. }
  25. Stonewt::~Stonewt()
  26. {
  27. }
  28. void Stonewt::Setstate(Format x)
  29. {
  30. state = x;
  31. }
  32. bool operator>(const Stonewt& s1, const Stonewt& s2)
  33. {
  34. if (s1.pounds > s2.pounds)
  35. return true;
  36. else
  37. return false;
  38. }
  39. bool operator<(const Stonewt& s1, const Stonewt& s2)
  40. {
  41. if (s1.pounds < s2.pounds)
  42. return true;
  43. else
  44. return false;
  45. }
  46. bool operator>=(const Stonewt& s1, const Stonewt& s2)
  47. {
  48. if (s1.pounds >= s2.pounds)
  49. return true;
  50. else
  51. return false;
  52. }
  53. bool operator<=(const Stonewt& s1, const Stonewt& s2)
  54. {
  55. if (s1.pounds <= s2.pounds)
  56. return true;
  57. else
  58. return false;
  59. }
  60. bool operator==(const Stonewt& s1, const Stonewt& s2)
  61. {
  62. if (s1.pounds == s2.pounds)
  63. return true;
  64. else
  65. return false;
  66. }
  67. bool operator!=(const Stonewt& s1, const Stonewt& s2)
  68. {
  69. if (s1.pounds != s2.pounds)
  70. return true;
  71. else
  72. return false;
  73. }
  74. ostream& operator<< (ostream& os, const Stonewt& s)
  75. {
  76. if (s.state == Stonewt::st)
  77. {
  78. os << s.stone << " stone, " << s.pds_left << " pounds\n";
  79. }
  80. else if (s.state == Stonewt::intp)
  81. {
  82. os << int(s.pounds) << " pounds\n";
  83. }
  84. else if (s.state == Stonewt::doublep)
  85. {
  86. os << s.pounds << " pounds\n";
  87. }
  88. else
  89. os << "Stonewt state is invalid";
  90. return os;
  91. }

6.3主函数.cpp

  1. #include <iostream>
  2. using namespace std;
  3. #include "stonewt116.h"
  4. //编写一个程序,它声明一个包含6个Stonewt对象的数组,
  5. //并在数组声明中初始化前3个对象。
  6. //然后使用循环来读取用于设置剩余3个数组元素的值。
  7. //接着报告最小的元素、最大的元素以及大于或等于11英石的元素的数量
  8. //最简单的方法是创建一个Stonewt对象,并将其初始化为11英石,然后将其同其他对象进行比较
  9. int main(void)
  10. {
  11. Stonewt s[6] = {{200.0},{100.2},{21,5.2} };
  12. cout << "Enter the rest three Stonewt:\n";
  13. for (int i = 3; i < 6; i++)
  14. {
  15. double pounds;
  16. cout << "#" << i + 1 << ": ";
  17. cin >> pounds;
  18. s[i] = pounds;
  19. }
  20. Stonewt max = s[0];
  21. Stonewt min = s[0];
  22. const Stonewt flag(11, 0);
  23. int count = 0;
  24. for (int i = 0; i < 6; i++)
  25. {
  26. max = max > s[i] ? max : s[i];
  27. min = min < s[i] ? min : s[i];
  28. if (s[i] >= flag)
  29. count++;
  30. }
  31. cout << "The max is: " << max;
  32. cout << "The min is: " << min;
  33. cout << "There are " << count << " memeber bigger than 11 stone.\n";
  34. system("pause");
  35. return 0;
  36. }

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

  1. #ifndef COMPLEX117_H_
  2. #define COMPLEX117_H_
  3. #include <iostream>
  4. class Complex
  5. {
  6. private:
  7. double real;
  8. double imag;
  9. public:
  10. Complex();
  11. Complex(double m, double n);
  12. ~Complex();
  13. Complex operator+(const Complex& c)const;
  14. Complex operator-(const Complex& c)const;
  15. Complex operator*(const Complex& c)const;
  16. Complex operator*(double x)const;
  17. friend Complex operator*(double n, const Complex& m){return m * n;}
  18. Complex operator~()const;
  19. friend std::ostream& operator<<(std::ostream& os, const Complex& n);
  20. friend std::istream& operator>>(std::istream& is, Complex& n);
  21. };
  22. #endif // !COMPLEX117_H_

7.2成员函数定义.cpp

  1. #include "complex117.h"
  2. #include <iostream>
  3. using namespace std;
  4. Complex::Complex()
  5. {
  6. real = imag = 0.0;
  7. }
  8. Complex::Complex(double m, double n)
  9. {
  10. real = m;
  11. imag = n;
  12. }
  13. Complex::~Complex()
  14. {
  15. }
  16. Complex Complex::operator+(const Complex& c)const
  17. {
  18. Complex sum;
  19. sum.real = c.real + this->real;
  20. sum.imag = c.imag + this->imag;
  21. return sum;
  22. }
  23. Complex Complex::operator-(const Complex& c)const
  24. {
  25. Complex diff;
  26. diff.real = this->real - c.real;
  27. diff.imag = this->imag - c.imag;
  28. return diff;
  29. }
  30. Complex Complex::operator*(const Complex& c)const
  31. {
  32. Complex mult1;
  33. mult1.real = this->real * c.real - this->imag * c.imag;
  34. mult1.imag = this->real * c.imag + this->imag * c.real;
  35. return mult1;
  36. }
  37. Complex Complex::operator*(double x)const
  38. {
  39. Complex mult2;
  40. mult2.real = this->real * x;
  41. mult2.imag = this->imag * x;
  42. return mult2;
  43. }
  44. Complex Complex::operator~()const
  45. {
  46. Complex temp;
  47. temp.real =this-> real;
  48. temp.imag = -(this->imag);
  49. return temp;
  50. }
  51. std::ostream& operator<<(std::ostream& os, const Complex& x)
  52. {
  53. os << "(" << x.real << ", " << x.imag << "i)";
  54. return os;
  55. }
  56. std::istream& operator>>(std::istream& is, Complex& x)
  57. {
  58. cout << "real: ";
  59. is >> x.real;
  60. if(x.real )
  61. {
  62. cout << "imaginary: ";
  63. is >> x.imag;
  64. }
  65. return is;
  66. }

7.3使用类.cpp

  1. #include <iostream>
  2. #include "complex117.h"
  3. using namespace std;
  4. int main(void)
  5. {
  6. Complex a(3.0, 4.0);
  7. Complex c;
  8. cout << "Enter a complex number(q to quit):\n";
  9. while (cin >> c)
  10. {
  11. cout << "c is " << c << endl;
  12. cout << "complex conjugate is " << ~c << endl;
  13. cout << "a is " << a << endl;
  14. cout << "a + c is " << a + c << endl;
  15. cout << "a - c is " << a - c << endl;
  16. cout << "a * c is " << a * c << endl;
  17. cout << "2 * c is " << 2 * c << endl;
  18. cout << "Enter a complex number (q to quit):" << endl;
  19. }
  20. cout << "Done!" << endl;
  21. system("pause");
  22. return 0;
  23. }

第12章 类和动态内存分配

1.对于下面的类声明:

(……代码忽略……)

给这个类提供实现,并编写一个使用所有成员函数的小程序。

笔记:#pragma warning(disable:4996)      //解决strcpy报错的问题

1.1头文件cow121.h

  1. #ifndef COW121_H_
  2. #define COW121_H_
  3. #pragma warning(disable:4996) //解决strcpy报错的问题
  4. class Cow
  5. {
  6. private:
  7. char name[20];
  8. char* hobby;
  9. double weight;
  10. public:
  11. Cow();
  12. Cow(const char* nm, const char* ho, double wt);
  13. Cow(const Cow &c);
  14. ~Cow();
  15. Cow& operator= (const Cow& c);
  16. void ShowCow()const;
  17. };
  18. #endif // ! Cow121_H_

 1.2成员函数定义.cpp

  1. #include <iostream>
  2. #include <cstring>
  3. #include "cow121.h"
  4. using std::endl;
  5. using std::cout;
  6. Cow::Cow()
  7. {
  8. name[0] = '\0';
  9. hobby = new char[1];
  10. hobby[0] = '\0';
  11. weight = 0.0;
  12. }
  13. Cow::Cow(const char* nm, const char* ho, double wt)
  14. {
  15. strcpy(name, nm);
  16. hobby = new char[strlen(ho) + 1];
  17. strcpy(hobby, ho);
  18. weight = wt;
  19. }
  20. Cow::Cow(const Cow& c)
  21. {
  22. strcpy(name, c.name);
  23. hobby = new char[strlen(c.hobby) + 1];
  24. strcpy(hobby,c.hobby);
  25. weight = c.weight;
  26. }
  27. Cow::~Cow()
  28. {
  29. delete[] hobby;
  30. }
  31. Cow& Cow::operator= (const Cow& c)
  32. {
  33. delete[] hobby;
  34. strcpy(name,c.name);
  35. hobby = new char[strlen(c.hobby) + 1];
  36. strcpy(hobby, c.hobby);
  37. weight = c.weight;
  38. return *this;
  39. }
  40. void Cow::ShowCow()const
  41. {
  42. cout << "Name: " << name << endl;
  43. cout << "Hobby: " << hobby << endl;
  44. cout << "Weight: " << weight << endl;
  45. cout << endl;
  46. }

1.3使用类.cpp

  1. #include "cow121.h"
  2. #include <iostream>
  3. using std::cout;
  4. using std::endl;
  5. int main(void)
  6. {
  7. Cow c1;
  8. cout << "c1:" << endl;
  9. c1.ShowCow();
  10. Cow c2("Yonggan Niuniu", "study", 100.23);
  11. cout << "c2:" << endl;
  12. c2.ShowCow();
  13. Cow c3("Tangping Niuniu", "play game", 150.80);
  14. cout << "c3:" << endl;
  15. c3.ShowCow();
  16. Cow c4(c2);
  17. cout << "c4:" << endl;
  18. c4.ShowCow();
  19. c1 = c3;
  20. cout << "c1 = c3:" << endl;
  21. c3.ShowCow();
  22. c1.ShowCow();
  23. system("pause");
  24. return 0;
  25. }

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

  1. #ifndef STRING122_H_
  2. #define STRING122_H_
  3. #pragma warning(disable:4996)
  4. #include <iostream>
  5. using std::ostream;
  6. using std::istream;
  7. class String
  8. {
  9. private:
  10. char* str;
  11. int len;
  12. static int num_strings;
  13. static const int CINLIM = 80;
  14. public:
  15. String(const char* s);
  16. String();
  17. String(const String& st);
  18. ~String();
  19. int length()const { return len; }
  20. //重载
  21. String& operator=(const String& st);
  22. String& operator=(const char* s);
  23. char& operator[](int i);
  24. const char& operator[](int i)const;
  25. //友元
  26. friend bool operator<(const String& st1, const String& st2);
  27. friend bool operator>(const String& st1, const String& st2);
  28. friend bool operator==(const String& st1, const String& st2);
  29. friend ostream& operator<<(ostream& os, const String& st);
  30. friend istream& operator>>(istream& is, String& st);
  31. //static function
  32. static int Howmany();
  33. //新增函数
  34. //a.对 + 运算符进行重载,使之可将两个字符串合并成1个。
  35. String operator+(const String &s)const;
  36. String operator+(const char* s)const;
  37. friend String operator+(const char* s1, const String& s2);
  38. //b.提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写。
  39. void stringlow();
  40. //c.提供String()成员函数,将字符串中所有字母字符转换成大写。
  41. void stringup();
  42. //d.提供一个这样的成员函数,它接受一个char参数,返回该字符在字符串中出现的次数
  43. int has(char ch);
  44. };
  45. #endif // !STRING1_H_

2.2string.cpp

  1. #include <cstring>
  2. #include <cctype>
  3. #include "string122.h"
  4. using std::cin;
  5. using std::cout;
  6. int String::num_strings = 0;
  7. //static method
  8. int String::Howmany()
  9. {
  10. return num_strings;
  11. }
  12. String::String(const char* s)
  13. {
  14. len = std::strlen(s);
  15. str = new char[len + 1];
  16. strcpy_s(str,len+1, s);
  17. num_strings++;
  18. }
  19. String::String()
  20. {
  21. len = 4;
  22. str = new char[1];
  23. str[0] = '\0';
  24. num_strings++;
  25. }
  26. String::String(const String&st)
  27. {
  28. num_strings++;
  29. len = st.len;
  30. str = new char[len + 1];
  31. strcpy_s(str,len+1, st.str);
  32. }
  33. String::~String()
  34. {
  35. --num_strings;
  36. delete[] str;
  37. }
  38. //重载
  39. String& String::operator=(const String& st)
  40. {
  41. if (this == &st)
  42. return *this;
  43. delete[] str;
  44. len = st.len;
  45. str = new char[len + 1];
  46. strcpy_s(str,len+1, st.str);
  47. return *this;
  48. }
  49. String& String::operator=(const char* s)
  50. {
  51. delete[] str;
  52. len = std::strlen(s);
  53. str = new char[len + 1];
  54. strcpy_s(str, len+1,s);
  55. return *this;
  56. }
  57. char& String:: operator[](int i)
  58. {
  59. return str[i];
  60. }
  61. const char& String::operator[](int i)const
  62. {
  63. return str[i];
  64. }
  65. //友元
  66. bool operator<(const String& st1, const String& st2)
  67. {
  68. return(std::strcmp(st1.str, st2.str));
  69. }
  70. bool operator>(const String& st1, const String& st2)
  71. {
  72. return st2 < st1;
  73. }
  74. bool operator==(const String& st1, const String& st2)
  75. {
  76. return(std::strcmp(st1.str, st2.str) == 0);
  77. }
  78. ostream& operator<<(ostream& os, const String& st)
  79. {
  80. os << st.str;
  81. return os;
  82. }
  83. istream& operator>>(istream& is, String& st)
  84. {
  85. char temp[String::CINLIM];
  86. is.get(temp,String::CINLIM);
  87. if (is)
  88. st = temp;
  89. while (is && is.get() != '\n')
  90. continue;
  91. return is;
  92. }
  93. //新增函数
  94. String String::operator+(const String& s)const
  95. {
  96. int lens = s.len + len;
  97. char* temp = new char[lens + 1];
  98. strcpy(temp, str);
  99. strcpy(temp+len, s.str); //注意!!!
  100. return String(temp);
  101. }
  102. String String::operator+(const char* s)const
  103. {
  104. int lens = strlen(s) + len;
  105. char* temp = new char[lens + 1];
  106. strcpy(temp, str);
  107. strcpy(temp+len,s);
  108. return String(temp);
  109. }
  110. String operator+(const char* s1, const String& s2)
  111. {
  112. return String(s1) + s2;
  113. }
  114. //b.提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写。
  115. void String::stringlow()
  116. {
  117. for (int i = 0; i <= len; i++)
  118. {
  119. str[i] = tolower(str[i]);
  120. }
  121. }
  122. //c.提供String()成员函数,将字符串中所有字母字符转换成大写。
  123. void String::stringup()
  124. {
  125. for (int i = 0; i <= len; i++)
  126. {
  127. str[i] = toupper(str[i]);
  128. }
  129. }
  130. //d.提供一个这样的成员函数,它接受一个char参数,返回该字符在字符串中出现的次数
  131. int String::has(char ch)
  132. {
  133. int count = 0;
  134. for (int i = 0; i <= len; i++)
  135. {
  136. if (str[i] == ch)
  137. count++;
  138. }
  139. return count;
  140. }

 2.3测试类.cpp

  1. #include <iostream>
  2. using namespace std;
  3. #include "string122.h"
  4. int main()
  5. {
  6. String s1(" and I am a C++ student.");
  7. String s2 = "Please enter your name: ";
  8. String s3;
  9. cout << s2;
  10. cin >> s3;
  11. s2 = "My name is " + s3;
  12. cout << s2 << ".\n";
  13. s2 = s2 + s1;
  14. s2.stringup();
  15. cout << "The string\n" << s2 << "\ncontains " << s2.has('A')
  16. << " 'A' characters in it.\n";
  17. s1 = "red";
  18. String rgb[3] = { String(s1),String("green"),String("blue") };
  19. cout << "Enter the name of a primary color for mixing light: ";
  20. String ans;
  21. bool success = false;
  22. while (cin >> ans)
  23. {
  24. ans.stringlow();
  25. for (int i = 0; i < 3; i++)
  26. {
  27. if (ans == rgb[i])
  28. {
  29. cout << "That's right!\n";
  30. success = true;
  31. break;
  32. }
  33. }
  34. if (success)
  35. break;
  36. else
  37. cout << "Try again!\n";
  38. }
  39. cout << "Bye\n";
  40. return 0;
  41. }

3.新编写程序清单10.7和程序清单10.8描述的Stock类,使之使用动态内存分配的内存,而不是string类对象来存储股票名称。另外,使用重载的operator<<()定义代替show()成员函数。再使用程序清单10.9测试新的定义程序。

3.1头文件stock123.h

  1. #ifndef STOCK123_H_
  2. #define STOCK123_H_
  3. #pragma warning(disable:4996)
  4. #include <iostream>
  5. using std::ostream;
  6. class Stock
  7. {
  8. private:
  9. char* company;
  10. int shares;
  11. double share_val;
  12. double total_val;
  13. void set_tot() { total_val = shares * share_val; }
  14. public:
  15. Stock(); // default constructor
  16. Stock(const char* co, long n = 0, double pr = 0.0);
  17. ~Stock();
  18. void buy(long num, double price);
  19. void sell(long num, double price);
  20. void update(double price);
  21. friend ostream& operator<<(ostream& os, const Stock& st);
  22. const Stock& topval(const Stock& s) const;
  23. };
  24. #endif // !STOCK123_H_

3.2类定义.cpp

  1. #include <iostream>
  2. #include "stock123.h"
  3. #include <cstring>
  4. using namespace std;
  5. Stock::Stock()
  6. {
  7. company = new char[strlen("no name") + 1];
  8. strcpy(company, "no name");
  9. shares = 0;
  10. share_val = 0.0;
  11. total_val = 0.0;
  12. }
  13. Stock::Stock(const char* co, long n, double pr)
  14. {
  15. company = new char[strlen(co) + 1];
  16. strcpy(company, co);
  17. if (n < 0)
  18. {
  19. cout << "Number of shares can't be negative; "
  20. << company << " shares set to 0.\n";
  21. shares = 0;
  22. }
  23. else
  24. shares = n;
  25. share_val = pr;
  26. set_tot();
  27. }
  28. Stock::~Stock()
  29. {
  30. delete[] company;
  31. }
  32. void Stock::buy(long num, double price)
  33. {
  34. if (num < 0)
  35. {
  36. std::cout << "Number of shares purchased can't be negative. "
  37. << "Transaction is aborted.\n";
  38. }
  39. else
  40. {
  41. shares += num;
  42. share_val = price;
  43. set_tot();
  44. }
  45. }
  46. void Stock::sell(long num, double price)
  47. {
  48. if (num < 0)
  49. {
  50. cout << "Number of shares sold can't be negative. "
  51. << "Transaction is aborted.\n";
  52. }
  53. else if (num > shares)
  54. {
  55. cout << "You can't sell more than you have! "
  56. << "Transaction is aborted.\n";
  57. }
  58. else
  59. {
  60. shares -= num;
  61. share_val = price;
  62. set_tot();
  63. }
  64. }
  65. void Stock::update(double price)
  66. {
  67. share_val = price;
  68. set_tot();
  69. }
  70. ostream& operator<<(ostream& os, const Stock& st)
  71. {
  72. ios_base::fmtflags orig =
  73. os.setf(ios_base::fixed, ios_base::floatfield);
  74. std::streamsize prec = os.precision(3);
  75. os << "Company: " << st.company
  76. << " Shares: " << st.shares << '\n';
  77. os << " Share Price: $" << st.share_val;
  78. // set format to #.##
  79. os.precision(2);
  80. os << " Total Worth: $" << st.total_val << '\n';
  81. // restore original format
  82. os.setf(orig, ios_base::floatfield);
  83. os.precision(prec);
  84. return os;
  85. }
  86. const Stock& Stock::topval(const Stock& s) const
  87. {
  88. if (s.total_val > total_val)
  89. return s;
  90. else
  91. return *this;
  92. }

3.3测试类.cpp

  1. #include <iostream>
  2. #include "stock123.h"
  3. const int STKS = 4;
  4. int main()
  5. {
  6. {
  7. // create an array of initialized objects
  8. Stock stocks[STKS] = {
  9. Stock("NanoSmart", 12, 20.0),
  10. Stock("Boffo Objects", 200, 2.0),
  11. Stock("Monolithic Obelisks", 130, 3.25),
  12. Stock("Fleep Enterprises", 60, 6.5)
  13. };
  14. std::cout << "Stock holdings:\n";
  15. int st;
  16. for (st = 0; st < STKS; st++)
  17. std::cout << stocks[st];
  18. // set pointer to first element
  19. const Stock* top = &stocks[0];
  20. for (st = 1; st < STKS; st++)
  21. top = &top->topval(stocks[st]);
  22. // now top points to the most valuable holding
  23. std::cout << "\nMost valuable holding:\n";
  24. std::cout << *top; }
  25. return 0;
  26. }

4.请看下面程序清单10.10定义的Stack类的变量:

(……代码忽略……)

正如私有成员表明的,这个类使用动态内存分配的数组来保存栈项。请重新编写方法,以适应这种新的表示法,并编写一个程序来演示所有的方法,包括复制构造函数和赋值运算符。

4.1头文件stack.h

  1. #ifndef STACK124_H_
  2. #define STACK124_H_
  3. typedef unsigned long Item;
  4. class Stack
  5. {
  6. private:
  7. enum { MAX = 10 }; // constant specific to class
  8. Item* pitems; // holds stack items
  9. int size;
  10. int top; // index for top stack item
  11. public:
  12. Stack(int n = MAX);
  13. Stack(const Stack& st);
  14. ~Stack();
  15. bool isempty() const;
  16. bool isfull() const;
  17. // push() returns false if stack already is full, true otherwise
  18. bool push(const Item& item); // add item to stack
  19. // pop() returns false if stack already is empty, true otherwise
  20. bool pop(Item& item); // pop top into item
  21. Stack& operator=(const Stack& st);
  22. };
  23. #endif

4.2成员函数定义.cpp

  1. #include <iostream>
  2. #include "stack124.h"
  3. Stack::Stack(int n)
  4. {
  5. pitems = new Item[n];
  6. size = n;
  7. top = 0;
  8. }
  9. Stack::Stack(const Stack& st)
  10. {
  11. size = st.size;
  12. pitems = new Item[size];
  13. for (int i = 0; i < size; i++)
  14. {
  15. pitems[i] = st.pitems[i];
  16. }
  17. top = st.top;
  18. }
  19. Stack::~Stack()
  20. {
  21. delete[] pitems;
  22. }
  23. bool Stack::isempty() const
  24. {
  25. return top == 0;
  26. }
  27. bool Stack::isfull() const
  28. {
  29. return top == MAX;
  30. }
  31. // push() returns false if stack already is full, true otherwise
  32. bool Stack::push(const Item& item) // add item to stack
  33. {
  34. if (top < MAX)
  35. {
  36. pitems[top++] = item;
  37. return true;
  38. }
  39. else
  40. return false;
  41. }
  42. // pop() returns false if stack already is empty, true otherwise
  43. bool Stack::pop(Item& item) // pop top into item
  44. {
  45. if (top > 0)
  46. {
  47. item = pitems[--top];
  48. return true;
  49. }
  50. else
  51. return false;
  52. }
  53. Stack& Stack::operator=(const Stack& st)
  54. {
  55. if (this == &st)
  56. return *this;
  57. delete[]pitems;
  58. size = st.size;
  59. pitems = new Item[size];
  60. for (int i = 0; i < size; i++)
  61. {
  62. pitems[i] = st.pitems[i];
  63. }
  64. top = st.top;
  65. return *this;
  66. }

4.3 使用类.cpp

  1. #include <iostream>
  2. #include "stack124.h"
  3. using namespace std;
  4. int main(void)
  5. {
  6. Stack st1;
  7. Stack st2;
  8. Item p1[10] = { 12,20,3,0,2,2,3,5,8,9 };
  9. for (int i = 0; i < 10; i++)
  10. {
  11. st2.push(p1[i]);
  12. cout << p1[i]<<" ";
  13. }
  14. cout << endl;
  15. cout << "Is st2 empty: " << st2.isempty() << endl;
  16. cout << "Is st2 full: " << st2.isfull() << endl;
  17. st1 = st2;
  18. cout << "st1赋值后:" << endl;
  19. cout << "Is st1 empty: " << st1.isempty() << endl;
  20. cout << "Is st1 full: " << st1.isfull() << endl;
  21. Stack st3(st2);
  22. cout << "用st2构造st3后:" << endl;
  23. cout << "Is st3 empty: " << st3.isempty() << endl;
  24. cout << "Is st3 full: " << st3.isfull() << endl;
  25. for (int i = 0; i < 10; i++)
  26. {
  27. st2.pop(p1[i]);
  28. cout << p1[i] << " ";
  29. }
  30. cout << endl;
  31. cout << "st2全pop后:" << endl;
  32. cout << "Is st2 empty: " << st2.isempty() << endl;
  33. cout << "Is st2 full: " << st2.isfull() << endl;
  34. for (int i = 0; i < 6; i++)
  35. {
  36. st3.pop(p1[i]);
  37. cout << p1[i] << " ";
  38. }
  39. cout << endl;
  40. cout << "st3部分pop后:" << endl;
  41. cout << "Is st3 empty: " << st3.isempty() << endl;
  42. cout << "Is st3 full: " << st3.isfull() << endl;
  43. system("pause");
  44. return 0;
  45. }

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

  1. #ifndef CD131_H_
  2. #define CD131_H_
  3. #pragma warning(disable:4996)
  4. class Cd { //represents a CD disk
  5. private:
  6. char performers[50];
  7. char label[20];
  8. int selections; //number of selections
  9. double playtime; //playing time in minute
  10. public:
  11. Cd(const char * s1,const char* s2, int n, double x);
  12. Cd(const Cd& d);
  13. Cd();
  14. virtual ~Cd();
  15. virtual void Report() const; //reports all CD data
  16. virtual Cd& operator=(const Cd& d);
  17. };
  18. class Classic : public Cd
  19. {
  20. private:
  21. char mainworks[50];
  22. public:
  23. Classic(const char* m,const char* s1,const char* s2, int n, double x);
  24. Classic(const char* m,const Cd& rs);
  25. Classic();
  26. virtual ~Classic();
  27. virtual void Report() const;
  28. virtual Classic& operator=(const Classic& d);
  29. };
  30. #endif // !CD131_H_

1.2类函数定义.cpp

  1. #include "cd131.h"
  2. #include <iostream>
  3. using namespace std;
  4. #include <cstring>
  5. #include <cstdlib>
  6. Cd::Cd(const char* s1,const char* s2, int n, double x)
  7. {
  8. strncpy(performers, s1,49);
  9. performers[49] = '\0';
  10. strncpy(label, s2, 19);
  11. label[19] = '\0';
  12. selections = n;
  13. playtime = x;
  14. }
  15. Cd::Cd(const Cd& d)
  16. {
  17. strncpy(performers, d.performers, 49);
  18. performers[49] = '\0';
  19. strncpy(label, d.performers, 19);
  20. label[19] = '\0';
  21. selections = d.selections;
  22. playtime = d.playtime;
  23. }
  24. Cd::Cd()
  25. {
  26. strcpy(performers,"null");
  27. strcpy(label,"null");
  28. selections = 0;
  29. playtime = 0.0;
  30. }
  31. Cd::~Cd()
  32. {
  33. }
  34. void Cd::Report() const //reports all CD data
  35. {
  36. cout << "Performers: " << performers << endl;
  37. cout << "Label: " << label << endl;
  38. cout << "There are " << selections << " selections and lasts " << playtime << " minutes.\n";
  39. }
  40. Cd& Cd::operator=(const Cd& d)
  41. {
  42. strncpy(performers, d.performers, 49);
  43. performers[49] = '\0';
  44. strncpy(label, d.performers, 19);
  45. label[19] = '\0';
  46. selections = d.selections;
  47. playtime = d.playtime;
  48. return *this;
  49. }
  50. Classic::Classic(const char* m, const char* s1,const char* s2, int n, double x):Cd(s1, s2, n, x)
  51. {
  52. strncpy(mainworks,m, 49);
  53. mainworks[49] = '\0';
  54. }
  55. Classic::Classic(const char* m,const Cd& rs) : Cd(rs)
  56. {
  57. strncpy(mainworks, m, 49);
  58. mainworks[49] = '\0';
  59. }
  60. Classic::Classic() : Cd()
  61. {
  62. strcpy(mainworks,"null");
  63. }
  64. Classic::~Classic()
  65. {
  66. }
  67. void Classic::Report() const
  68. {
  69. Cd::Report();
  70. cout << "The main works of this disk are " << mainworks << endl;
  71. }
  72. Classic& Classic::operator=(const Classic& d)
  73. {
  74. if (this == &d)
  75. return *this;
  76. Cd::operator=(d);
  77. strncpy(mainworks, d.mainworks,49);
  78. mainworks[49] = '\0';
  79. return *this;
  80. }

1.3测试类.cpp

  1. #include<iostream>
  2. using namespace std;
  3. #include"cd131.h" //which will contain #include cd.h
  4. void Bravo(const Cd& disk);
  5. int main()
  6. {
  7. Cd c1("beatles", "Capitol", 14, 35.5);
  8. Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17);
  9. Cd* pcd = &c1;
  10. cout << "Using object directly:\n";
  11. c1.Report(); //use Cd method
  12. c2.Report(); //use Classic method
  13. cout << "Using type cd *pointer to objects:\n";
  14. pcd->Report(); //use Cd method for cd object
  15. pcd = &c2;
  16. pcd->Report(); //use Classic method for classic object
  17. cout << "Calling a function with a Cd reference argument:\n";
  18. Bravo(c1);
  19. Bravo(c2);
  20. cout << "Testing assignment: ";
  21. Classic copy;
  22. copy = c2;
  23. copy.Report();
  24. return 0;
  25. }
  26. void Bravo(const Cd& disk)
  27. {
  28. disk.Report();
  29. }

2..完成练习1,但让两个类使用动态内存分配而不是长度固定的数组来记录字符串。

答:

2.1头文件“cd132.h”(与上题相比,仅仅把数组改成指针形式)

  1. #ifndef CD132_H_
  2. #define CD132_H_
  3. #pragma warning(disable:4996)
  4. class Cd { //represents a CD disk
  5. private:
  6. char* performers;
  7. char* label;
  8. int selections; //number of selections
  9. double playtime; //playing time in minute
  10. public:
  11. Cd(const char* s1, const char* s2, int n, double x);
  12. Cd(const Cd& d);
  13. Cd();
  14. virtual ~Cd();
  15. virtual void Report() const; //reports all CD data
  16. virtual Cd& operator=(const Cd& d);
  17. };
  18. class Classic : public Cd
  19. {
  20. private:
  21. char* mainworks;
  22. public:
  23. Classic(const char* m, const char* s1, const char* s2, int n, double x);
  24. Classic(const char* m, const Cd& rs);
  25. Classic();
  26. virtual ~Classic();
  27. virtual void Report() const;
  28. virtual Classic& operator=(const Classic& d);
  29. };
  30. #endif // !CD131_H_

2.2类函数定义.cpp(有变化)

  1. #include "cd132.h"
  2. #include <iostream>
  3. using namespace std;
  4. #include <cstring>
  5. #include <cstdlib>
  6. Cd::Cd(const char* s1, const char* s2, int n, double x)
  7. {
  8. performers = new char[strlen(s1) + 1];
  9. strcpy(performers, s1);
  10. label = new char[strlen(s2) + 1];
  11. strcpy(label, s2);
  12. selections = n;
  13. playtime = x;
  14. }
  15. Cd::Cd(const Cd& d)
  16. {
  17. performers = new char[strlen(d.performers) + 1];
  18. strcpy(performers, d.performers);
  19. label = new char[strlen(d.label) + 1];
  20. strcpy(label, d.label);
  21. selections = d.selections;
  22. playtime = d.playtime;
  23. }
  24. Cd::Cd()
  25. {
  26. performers = new char[5];
  27. strcpy(performers, "null");
  28. label = new char[5];
  29. strcpy(label, "null");
  30. selections = 0;
  31. playtime = 0.0;
  32. }
  33. Cd::~Cd()
  34. {
  35. delete[] performers;
  36. delete[] label;
  37. }
  38. void Cd::Report() const //reports all CD data
  39. {
  40. cout << "Performers: " << performers << endl;
  41. cout << "Label: " << label << endl;
  42. cout << "There are " << selections << " selections and lasts " << playtime << " minutes.\n";
  43. }
  44. Cd& Cd::operator=(const Cd& d)
  45. {
  46. performers = new char[strlen(d.performers) + 1];
  47. strcpy(performers, d.performers);
  48. label = new char[strlen(d.label) + 1];
  49. strcpy(label, d.label);
  50. selections = d.selections;
  51. playtime = d.playtime;
  52. return *this;
  53. }
  54. Classic::Classic(const char* m, const char* s1, const char* s2, int n, double x) :Cd(s1, s2, n, x)
  55. {
  56. mainworks = new char[strlen(m) + 1];
  57. strcpy(mainworks, m);
  58. }
  59. Classic::Classic(const char* m, const Cd& rs) : Cd(rs)
  60. {
  61. mainworks = new char[strlen(m) + 1];
  62. strcpy(mainworks, m);
  63. }
  64. Classic::Classic() : Cd()
  65. {
  66. mainworks = new char[5];
  67. strcpy(mainworks, "null");
  68. }
  69. Classic::~Classic()
  70. {
  71. delete[] mainworks;
  72. }
  73. void Classic::Report() const
  74. {
  75. Cd::Report();
  76. cout << "The main works of this disk are " << mainworks << endl;
  77. }
  78. Classic& Classic::operator=(const Classic& d)
  79. {
  80. if (this == &d)
  81. return *this;
  82. Cd::operator=(d);
  83. mainworks = new char[strlen(d.mainworks) + 1];
  84. strcpy(mainworks, d.mainworks);
  85. return *this;
  86. }

2.3类测试.cpp(与上题相同,无变化)

  1. #include<iostream>
  2. using namespace std;
  3. #include"cd132.h" //which will contain #include cd.h
  4. void Bravo(const Cd& disk);
  5. int main()
  6. {
  7. Cd c1("beatles", "Capitol", 14, 35.5);
  8. Classic c2 = Classic("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Philips", 2, 57.17);
  9. Cd* pcd = &c1;
  10. cout << "Using object directly:\n";
  11. c1.Report(); //use Cd method
  12. c2.Report(); //use Classic method
  13. cout << "Using type cd *pointer to objects:\n";
  14. pcd->Report(); //use Cd method for cd object
  15. pcd = &c2;
  16. pcd->Report(); //use Classic method for classic object
  17. cout << "Calling a function with a Cd reference argument:\n";
  18. Bravo(c1);
  19. Bravo(c2);
  20. cout << "Testing assignment: ";
  21. Classic copy;
  22. copy = c2;
  23. copy.Report();
  24. return 0;
  25. }
  26. void Bravo(const Cd& disk)
  27. {
  28. disk.Report();
  29. }

3.修改baseDMA-lacksDMA-hasDMA类层次,让三个类都从一个ABC派生而来,然后使用与程序清单13.10相似的程序对结果进行测试。也就是说,它应使用ABC指针数组,并让用户决定要创建的对象类型。在类定义中添加virtual View()方法以处理数据显示。

答:

3.1头文件dma133.h

  1. #ifndef ABC133_H_
  2. #define ABC133_H_
  3. #include <iostream>
  4. #pragma warning(disable:4996)
  5. class ABC
  6. {
  7. public:
  8. ABC() {};
  9. ~ABC() {};
  10. virtual void View() = 0;
  11. };
  12. //Baseclass using DMA
  13. class baseDMA:public ABC
  14. {
  15. private:
  16. char* label;
  17. int rating;
  18. public:
  19. baseDMA(const char* l = "null", int r = 0);
  20. baseDMA(const baseDMA& rs);
  21. virtual ~baseDMA();
  22. baseDMA& operator=(const baseDMA& rs);
  23. friend std::ostream& operator<<(std::ostream& os, const baseDMA& rs);
  24. virtual void View();
  25. };
  26. class lacksDMA :public baseDMA
  27. {
  28. private:
  29. enum { COL_LEN = 40 };
  30. char color[COL_LEN];
  31. public:
  32. lacksDMA(const char* c = "blank", const char* l = "null", int r = 0);
  33. lacksDMA(const char* c, const baseDMA& rs);
  34. friend std::ostream& operator<<(std::ostream& os, const lacksDMA& rs);
  35. virtual void View();
  36. };
  37. class hasDMA :public baseDMA
  38. {
  39. private:
  40. char* style;
  41. public:
  42. hasDMA(const char* s = "none", const char* l = "null", int r = 0);
  43. hasDMA(const char* s, const baseDMA& rs);
  44. hasDMA(const hasDMA& hs);
  45. ~hasDMA();
  46. hasDMA& operator= (const hasDMA& hs);
  47. friend std::ostream& operator<<(std::ostream& os, const hasDMA& hs);
  48. virtual void View();
  49. };
  50. #endif // ! ABC

3.2类成员函数定义.cpp

  1. #include "ABC133.h"
  2. #include <cstring>
  3. //Baseclass methods
  4. baseDMA::baseDMA(const char* l, int r)
  5. {
  6. label = new char[std::strlen(l) + 1];
  7. std::strcpy(label, l);
  8. rating = r;
  9. }
  10. baseDMA::baseDMA(const baseDMA& rs)
  11. {
  12. label = new char[std::strlen(rs.label) + 1];
  13. std::strcpy(label, rs.label);
  14. rating = rs.rating;
  15. }
  16. baseDMA::~baseDMA()
  17. {
  18. delete[] label;
  19. }
  20. baseDMA& baseDMA::operator=(const baseDMA& rs)
  21. {
  22. if (this == &rs)
  23. return *this;
  24. delete[] label;
  25. label = new char[std::strlen(rs.label) + 1];
  26. strcpy(label, rs.label);
  27. rating = rs.rating;
  28. return *this;
  29. }
  30. std::ostream& operator<<(std::ostream& os, const baseDMA& rs)
  31. {
  32. os << "Label: " << rs.label << std::endl;
  33. os << "Rating: " << rs.rating << std::endl;
  34. return os;
  35. }
  36. void baseDMA::View()
  37. {
  38. std::cout<< "Label: " << label << std::endl;
  39. std::cout<< "Rating: " << rating << std::endl;
  40. }
  41. //lacksDMA methods
  42. lacksDMA::lacksDMA(const char* c, const char* l, int r) :baseDMA(l, r)
  43. {
  44. std::strncpy(color, c, 39); //用于指定长度的字符串赋值到字符数组中
  45. color[39] = '\0';
  46. }
  47. lacksDMA::lacksDMA(const char* c, const baseDMA& rs) : baseDMA(rs)
  48. {
  49. std::strncpy(color, c, COL_LEN - 1);
  50. color[COL_LEN - 1] = '\0';
  51. }
  52. std::ostream& operator<<(std::ostream& os, const lacksDMA& ls)
  53. {
  54. os << (const baseDMA&)ls;
  55. os << "Color: " << ls.color << std::endl;
  56. return os;
  57. }
  58. void lacksDMA::View()
  59. {
  60. baseDMA::View();
  61. std::cout << "Color: " <<color <<std:: endl;
  62. }
  63. //hasDMA mmethods
  64. hasDMA::hasDMA(const char* s, const char* l, int r) :baseDMA(l, r)
  65. {
  66. style = new char[std::strlen(s) + 1];
  67. std::strcpy(style, s);
  68. }
  69. hasDMA::hasDMA(const char* s, const baseDMA& rs) : baseDMA(rs)
  70. {
  71. style = new char[std::strlen(s) + 1];
  72. std::strcpy(style, s);
  73. }
  74. hasDMA::hasDMA(const hasDMA& hs) : baseDMA(hs)
  75. {
  76. style = new char[std::strlen(hs.style) + 1];
  77. std::strcpy(style, hs.style);
  78. }
  79. hasDMA::~hasDMA()
  80. {
  81. delete[]style;
  82. }
  83. hasDMA& hasDMA::operator= (const hasDMA& hs)
  84. {
  85. if (this == &hs)
  86. return *this;
  87. baseDMA::operator=(hs);
  88. delete[]style;
  89. style = new char[std::strlen(hs.style) + 1];
  90. std::strcpy(style, hs.style);
  91. return *this;
  92. }
  93. std::ostream& operator<<(std::ostream& os, const hasDMA& hs)
  94. {
  95. os << (const baseDMA&)hs;
  96. os << "Style: " << hs.style << std::endl;
  97. return os;
  98. }
  99. void hasDMA::View()
  100. {
  101. baseDMA::View();
  102. std::cout << "Style: " << style << std::endl;
  103. }

3.3测试类.cpp

  1. #include <iostream>
  2. #include <string>
  3. #include "ABC133.h"
  4. using namespace std;
  5. const int DMA = 6;
  6. int main(void)
  7. {
  8. using std::cin;
  9. using std::cout;
  10. using std::endl;
  11. ABC * p_dma[DMA];
  12. char *templabel = new char[50];
  13. int temprating;
  14. char kind;
  15. for (int i = 0; i < DMA; i++)
  16. {
  17. cout << "Enter label: ";
  18. cin.getline(templabel, 50);
  19. cout << "Enter rating: ";
  20. cin >> temprating;
  21. cout << "Enter 1 for baseDMA or 2 for lacksDMA or 3 for hasDMA: ";
  22. while (cin >> kind && kind != '1' && kind != '2' && kind!='3')
  23. cout << "Enter either 1 or 2 or 3: ";
  24. cin.ignore(); //这里很重要,墨迹了好久才解决呜呜,长记性啊!!!
  25. if (kind == '1')
  26. {
  27. p_dma[i] = new baseDMA(templabel, temprating);
  28. }
  29. else if(kind == '2')
  30. {
  31. char tempcolor[40];
  32. cout << "Enter color: ";
  33. cin.getline(tempcolor, 40);
  34. p_dma[i] = new lacksDMA(tempcolor,templabel, temprating);
  35. }
  36. else
  37. {
  38. char *tempstyle = new char[20];
  39. cout << "Enter style: ";
  40. cin.getline(tempstyle, 20);
  41. p_dma[i] = new hasDMA(tempstyle, templabel, temprating);
  42. }
  43. while (cin.get() != '\n')
  44. continue;
  45. }
  46. cout << endl;
  47. for (int i = 0; i < DMA; i++)
  48. {
  49. p_dma[i]->View();
  50. cout << endl;
  51. }
  52. for (int i = 0; i < DMA; i++)
  53. {
  54. delete p_dma[i];
  55. }
  56. cout << "Done.\n" << endl;
  57. system("pause");
  58. return 0;
  59. }

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 : 20

operator<<()函数按下面的格式显示信息(末尾没有换行符):
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方法定义,因为前任被开除时销毁了方法定义。

  1. Port::Port(const char* br, const char* st, int b )
  2. {
  3. brand = new char[strlen(br) + 1];
  4. strcpy(brand, br);
  5. strcpy(style, st);
  6. bottles = b;
  7. }
  8. Port::Port(const Port& p) //copy constructor
  9. {
  10. brand = new char[strlen(p.brand) + 1];
  11. strcpy(brand, p.brand);
  12. strcpy(style, p.style);
  13. bottles = p.bottles;
  14. }
  15. Port& Port::operator=(const Port& p)
  16. {
  17. if (this == &p)
  18. return *this;
  19. delete[]brand;
  20. brand = new char[strlen(p.brand) + 1];
  21. strcpy(brand, p.brand);
  22. strcpy(style, p.style);
  23. bottles = p.bottles;
  24. return *this;
  25. }
  26. Port& Port::operator+=(int b)//add b to bottles
  27. {
  28. bottles += b;
  29. return *this;
  30. }
  31. Port& Port::operator-=(int b) //subtracts b from bottles , if available
  32. {
  33. bottles -= b;
  34. return *this;
  35. }
  36. void Port::Show() const
  37. {
  38. cout << "Brand: " << brand << endl;
  39. cout << "Kind: " << style << endl;
  40. cout << "Bottles: " << bottles << endl;
  41. }
  42. ostream& operator<<(ostream& os, const Port& p)
  43. {
  44. os << p.brand << "," << p.style << ","<<p.bottles;
  45. }

b.第二个任务是解释为什么有的方法重新定义了,而有些没有重新定义。

当派生类成员函数需要处理派生类独有的成员变量时,需要重新定义方法,如果不需要处理派生类独有的成员变量,直接调用基类的方法即可。
c.第三个任务解释为何没有将operator = () 和operator << ()声明为虚的。

a).如果要在派生类中重新定义基类的方法,则将它设置为虚方法。但是基类的operator = () 和派生类的operator = () 形参不一样,根本不是一个类方法,不存在重新定义的问题,因从也不必声明为虚的。

b).operator<<()函数是友元函数,友元函数不能是虚函数,因为友元不是类成员,而只有类成员才能是虚函数。
d.第四个任务是提供VintagePort中各个方法的定义。

  1. VintagePort::VintagePort():Port()
  2. {
  3. }
  4. VintagePort::VintagePort(const char* br, const char* st, int b, const char* nn, int y)
  5. : Port(br, st, b)
  6. {
  7. nickname = new char[strlen(nn) + 1];
  8. strcpy(nickname, nn);
  9. int year = y;
  10. }
  11. VintagePort::VintagePort(const VintagePort& vp):Port(vp)
  12. {
  13. nickname = new char[strlen(vp.nickname) + 1];
  14. strcpy(nickname, vp.nickname);
  15. int year = vp.year;
  16. }
  17. VintagePort& VintagePort::operator = (const VintagePort& vp)
  18. {
  19. if (this == &vp)
  20. return *this;
  21. Port::operator=(vp);
  22. delete[]nickname;
  23. nickname = new char[strlen(vp.nickname) + 1];
  24. strcpy(nickname, vp.nickname);
  25. strcpy(nickname, vp.nickname);
  26. year = vp.year;
  27. return *this;
  28. }
  29. void VintagePort::show() const
  30. {
  31. Port::Show();
  32. cout << "nickname: " << nickname << endl;
  33. cout << "year: " << year << endl;
  34. }
  35. ostream& operator <<(ostream& os, const VintagePort& vp)
  36. {
  37. os << (const Port&)vp;
  38. os << vp.nickname << "," << vp.year ;
  39. return os;
  40. }

第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可能有助于简化编程工作:

  1. typedef std::valarry<int> ArrayInt;
  2. typedef Pair<ArrayInt, ArrayInt> PairArray;
这样,PairArray表示的类型是Pair<std::valarry<int>,std::valarray<int>>。使用包含来实现Wine类,并用一个简单的程序对其进行测试。Wine类应该有一个默认构造函数以及如下的构造函数:
  1. Wine(const char* l, int y, const int yr[], ocnst int bot[]);
  2. Wine(const char* l, int y);
Wine类应该有一个GetBottles()方法,它根据Wine对象能够存储集中年份(y),提示用户输入年份和瓶数。方法Label()返回一个指向葡萄酒名称的引用。sum()方法返回Pair对象中第二个valarray<int>对象中的瓶数总和。

测试程序应提示用户输入葡萄酒名称、元素个数以及每个元素存储的年份和瓶数等信息。程序将使用这些数据来构造一个Wine对象,然后显示对象中保存的信息。

下面是一个简单的测试程序:

int main()

  1. {
  2. cout << "Enter name of wine: ";
  3. char lab[50];
  4. cin.getline(lab, 50);
  5. cout << "Enter number of years: ";
  6. int yrs;
  7. cin >> yrs;
  8. Wine holding(lab, yrs);
  9. holding.GetBottles();
  10. holding.Show();
  11. const int YRS = 3;
  12. int y[YRS] = {1993, 1995, 1998};
  13. int b[YRS] = {48, 60, 72};
  14. Wine more("Gushing Grape Red", YRS, y, b);
  15. more.Show();
  16. cout << "Total bottle for " << more.Label()
  17. <<": " << more.sum() << endl;
  18. cout << "Bye\n";
  19. return 0;
  20. }
下面是该程序的运行情况:

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

  1. #ifndef WINEC141_H_
  2. #define WINEC141_H_
  3. #include <iostream>
  4. #include <string>
  5. #include <valarray>
  6. template<class T1,class T2>
  7. class Pair
  8. {
  9. private:
  10. T1 a;
  11. T2 b;
  12. public:
  13. Pair(const T1& aval, const T2& bval) :a(aval), b(bval) {}
  14. Pair() {}
  15. void set(const T1& yr, const T2& bot);
  16. int sum() const;
  17. void Show(int y) const;
  18. };
  19. typedef std::valarray<int> ArrayInt;
  20. typedef Pair<ArrayInt, ArrayInt> PairArray;
  21. class Wine
  22. {
  23. private:
  24. std::string name;
  25. PairArray b;
  26. int yrs;
  27. public:
  28. Wine(const char* l, int y, const int yr[], const int bot[]);
  29. Wine(const char* l, int y);
  30. void GetBottles();
  31. std::string& Label();
  32. int sum()const;
  33. void Show()const;
  34. };
  35. #endif // !WINEC141_H_

1.2wine.cpp

  1. #include <iostream>
  2. #include "winec141.h"
  3. #include <string>
  4. #include <valarray>
  5. using namespace std;
  6. template<class T1,class T2>
  7. void Pair<T1, T2>::set(const T1& yr, const T2& bot)
  8. {
  9. a = yr;
  10. b = bot;
  11. }
  12. template<class T1, class T2>
  13. int Pair<T1, T2>::sum() const
  14. {
  15. return b.sum();
  16. }
  17. template<class T1, class T2>
  18. void Pair<T1, T2>::Show(int y) const
  19. {
  20. for (int i = 0; i < y; i++)
  21. {
  22. cout << "\t\t" << a[i] << "\t\t" << b[i] << endl;
  23. }
  24. }
  25. Wine::Wine(const char* l, int y, const int yr[], const int bot[])
  26. {
  27. name = l;
  28. yrs = y;
  29. b.set(ArrayInt(yr, yrs), ArrayInt(bot, yrs));
  30. }
  31. Wine::Wine(const char* l, int y)
  32. {
  33. name = l;
  34. yrs = y;
  35. }
  36. void Wine::GetBottles()
  37. {
  38. ArrayInt yr(yrs), bot(yrs);
  39. cout << "Enter" << name << " data for " << yrs << " year(s):\n";
  40. for (int i = 0; i < yrs; i++)
  41. {
  42. cout << "Enter year: ";
  43. cin >> yr[i];
  44. cout << "Enter bottles for that year: ";
  45. cin >> bot[i];
  46. }
  47. b.set(yr, bot);
  48. }
  49. std::string& Wine::Label()
  50. {
  51. return name;
  52. }
  53. int Wine::sum()const
  54. {
  55. return b.sum();
  56. }
  57. void Wine::Show()const
  58. {
  59. cout << "Wine: " << name << endl;
  60. cout << "\t\tYear\t\tBottles\n";
  61. b.Show(yrs);
  62. }

1.3usewine.cpp

  1. #include "winec141.h"
  2. #include <iostream>
  3. int main()
  4. {
  5. using std::cin;
  6. using std::endl;
  7. using std::cout;
  8. cout << "Enter name of wine: ";
  9. char lab[50];
  10. cin.getline(lab, 50);
  11. cout << "Enter number of years: ";
  12. int yrs;
  13. cin >> yrs;
  14. Wine holding(lab, yrs);
  15. holding.GetBottles();
  16. holding.Show();
  17. const int YRS = 3;
  18. int y[YRS] = { 1993, 1995, 1998 };
  19. int b[YRS] = { 48, 60, 72 };
  20. Wine more("Gushing Grape Red", YRS, y, b);
  21. more.Show();
  22. cout << "Total bottle for " << more.Label()
  23. << ": " << more.sum() << endl;
  24. cout << "Bye\n";
  25. return 0;
  26. }

2.

2.采用私有继承而不是包含来完成编程练习1.同样,一些typedef可能会有所帮助,另外,您可能还需要考虑诸如下面这样的语句的含义:

  1. PairArray::operator=(PairArray(ArrayInt(), ArrayInt()));
  2. cout << (const string&)(*this);

您设计的类应该可以使用编程练习1中的测试程序进行测试。

答:

2.1头文件winep142.h

  1. #ifndef WINEP142_H
  2. #define WINEP142_H
  3. #include <iostream>
  4. #include <string>
  5. #include <valarray>
  6. template<class T1,class T2>
  7. class Pair
  8. {
  9. private:
  10. T1 a;
  11. T2 b;
  12. public:
  13. Pair(const T1& aval, const T2& bval) :a(aval), b(bval) {}
  14. Pair() {}
  15. void set(const T1& yr, const T2& bot);
  16. int sum() const;
  17. void Show(int y) const;
  18. };
  19. typedef std::valarray<int> ArrayInt;
  20. typedef Pair<ArrayInt, ArrayInt> PairArray;
  21. class Wine : private std::string, private PairArray
  22. {
  23. private:
  24. int yrs;
  25. public:
  26. Wine(const char* l,int y,const int yr[],const int bot[]);
  27. Wine(const char* l,int y);
  28. void GetBottles();
  29. std::string& Label();
  30. int sum() const;
  31. void Show() const;
  32. };
  33. #endif // !WINEP_142_H

2.2winep.cpp

  1. #include "winep142.h"
  2. #include <iostream>
  3. #include <string>
  4. #include <valarray>
  5. using std::cin;
  6. using std::cout;
  7. using std::string;
  8. using std::endl;
  9. template<class T1, class T2>
  10. void Pair<T1, T2>::set(const T1& yr, const T2& bot)
  11. {
  12. a = yr;
  13. b = bot;
  14. }
  15. template<class T1, class T2>
  16. int Pair<T1, T2>::sum() const
  17. {
  18. return b.sum();
  19. }
  20. template<class T1, class T2>
  21. void Pair<T1, T2>::Show(int y) const
  22. {
  23. for (int i = 0; i < y; i++)
  24. {
  25. cout << "\t\t" << a[i] << "\t\t" << b[i] << endl;
  26. }
  27. }
  28. Wine::Wine(const char* l, int y, const int yr[], const int bot[]):
  29. string(l), yrs(y), PairArray(ArrayInt(yr, yrs), ArrayInt(bot, yrs))
  30. {
  31. }
  32. Wine::Wine(const char* l, int y):string(l),yrs(y)
  33. {
  34. }
  35. void Wine::GetBottles()
  36. {
  37. ArrayInt yr(yrs), bot(yrs);
  38. cout << "Enter" << (const string&)(*this) << " data for " << yrs << " year(s):\n";
  39. for (int i = 0; i < yrs; i++)
  40. {
  41. cout << "Enter year: ";
  42. cin >> yr[i];
  43. cout << "Enter bottles for that year: ";
  44. cin >> bot[i];
  45. }
  46. PairArray::set(yr, bot);
  47. }
  48. std::string& Wine::Label()
  49. {
  50. return (string&)(*this);
  51. }
  52. int Wine::sum() const
  53. {
  54. return PairArray::sum();
  55. }
  56. void Wine::Show() const
  57. {
  58. cout << "Wine: " << (const string&)(*this) << std::endl;
  59. cout << "\t\tYear\t\tBottles\n";
  60. PairArray::Show(yrs);
  61. }

2.3usewinep.cpp

  1. #include "winep142.h"
  2. #include <iostream>
  3. int main()
  4. {
  5. using std::cin;
  6. using std::endl;
  7. using std::cout;
  8. cout << "Enter name of wine: ";
  9. char lab[50];
  10. cin.getline(lab, 50);
  11. cout << "Enter number of years: ";
  12. int yrs;
  13. cin >> yrs;
  14. Wine holding(lab, yrs);
  15. holding.GetBottles();
  16. holding.Show();
  17. const int YRS = 3;
  18. int y[YRS] = { 1993, 1995, 1998 };
  19. int b[YRS] = { 48, 60, 72 };
  20. Wine more("Gushing Grape Red", YRS, y, b);
  21. more.Show();
  22. cout << "Total bottle for " << more.Label()
  23. << ": " << more.sum() << endl;
  24. cout << "Bye\n";
  25. return 0;
  26. }

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.下面是一些类声明:

  1. class AbstrEmp
  2. {
  3. private:
  4. string _fname;
  5. string _lname;
  6. string _job;
  7. public:
  8. AbstrEmp();
  9. AbstrEmp(const std::string& fn, const string& ln, const string& j);
  10. virtual void showAll()const;
  11. virtual void setAll();
  12. friend ostream& operator<<(ostream& os, const AbstrEmp& e);
  13. virtual ~AbstrEmp() = 0;
  14. };
  15. class Employee : public AbstrEmp
  16. {
  17. public:
  18. Employee();
  19. Employee(const string& fn, const string& ln, const string& j);
  20. virtual void showAll()const;
  21. virtual void setAll();
  22. };
  23. class Manager : virtual public AbstrEmp
  24. {
  25. private:
  26. int _inchargeof;
  27. protected:
  28. int inChargeOf()const
  29. {
  30. return _inchargeof;
  31. }
  32. int& inChargeOf()
  33. {
  34. return _inchargeof;
  35. }
  36. public:
  37. Manager();
  38. Manager(const string& fn, const string& ln, const string& j0, int ico = 0);
  39. Manager(const AbstrEmp& e, int ico);
  40. Manager(const Manager& m);
  41. virtual void showAll()const;
  42. virtual void setAll();
  43. };
  44. class Fink : virtual public AbstrEmp
  45. {
  46. private:
  47. string _reportsto;
  48. protected:
  49. const string reportsTo() const{ return _reportsto; }
  50. string& reportsTo(){ return _reportsto; }
  51. public:
  52. Fink();
  53. Fink(const string& fn, const string& ln, const string& j, const string& rpo);
  54. Fink(const AbstrEmp& e, const string& rpo);
  55. Fink(const Fink& e);
  56. virtual void showAll()const;
  57. virtual void setAll();
  58. };
  59. class HighFink: public Manager, public Fink
  60. {
  61. public:
  62. HighFink();
  63. HighFink(const string& fn, const string& ln, const string& j, const string& rpo, int ico);
  64. HighFink(const AbstrEmp& e, const string& rpo, int ico);
  65. HighFink(const Fink& f, int ico);
  66. HighFink(const Manager& m, const string& rpo);
  67. HighFink(const HighFink& h);
  68. virtual void showAll()const;
  69. virtual void setAll();
  70. };
注意,该类层次结构使用了带虚基类的MI,所以要牢记这种情况下用于构造函数初始化列表的特殊规则。还需要注意的是,有些方法被声明为保护的。这可以简化一些HighFink方法的代码(例如,如果HightFink::showAll()只是调用Fink::showAll()和Manager::showAll(),则它将调用abstr_emp::ShowAll()两次)。提供类方法的实现,并在一个程序中对这些类进行测试。下面是一个小型测试程序:
  1. #include <iostream>
  2. #include "Test.h"
  3. #include <string>
  4. using namespace std;
  5. using namespace FableGame;
  6. int main(int argc, const char * argv[])
  7. {
  8. Employee em("Trip", "Harris", "Thumper");
  9. cout << em << endl;
  10. em.showAll();
  11. Manager ma("Amorphia", "Spindragon", "Nuancer", 5);
  12. cout << ma << endl;
  13. ma.showAll();
  14. Fink fi("Matt", "Oggs", "Oiler", "Juno Barr");
  15. cout << fi << endl;
  16. fi.showAll();
  17. HighFink hf(ma, "Curly Kew");
  18. hf.showAll();
  19. cout << "Press a key for next phase:\n";
  20. cin.get();
  21. HighFink hf2;
  22. hf2.setAll();
  23. cout << "Using an abstr_emp * pointer:\n";
  24. AbstrEmp* tri[4] = { &em, &fi, &hf, &hf2 };
  25. for (int i = 0; i < 4; ++i)
  26. {
  27. tri[i]->showAll();
  28. }
  29. return 0;
  30. }

为什么没有定义赋值运算符?
为什么要将ShowAll()和SetAll()定义为虚的?
为什么要将abstr_emp定义为虚基类?
为什么highfink类没有数据部分?
为什么只需一个operator << ()版本?
如果使用下面的代码替换程序的结尾部分,将会发生什么情况?

  1. abstr_emp str[4] = {em, fi, hf, hf2};
  2. for(int i = 0; i < 4; ++i)
  3. tr[i].showAll()
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/497682
推荐阅读
  

闽ICP备14008679号