41. 声明一个哺乳动物 Mammal 类,再由此派生出狗 Dog 类,二者都定义 speak( ) 成员函数,基类中定义为虚函数。声明一个 Dog 类的对象,调用 speak()函数, 观察运行结果。
#include <iostream>
#include <string>
using namespace std;
class Mammel
{
public:
virtual void speak()
{
cout << "Mammel" << endl;
}
};
class Dog : public Mammel
{
public:
void speak()
{
cout << "汪汪队立大功" << endl;
}
};
int main() {
Dog my_dog;
my_dog.speak(); //"汪汪队立大功"
Mammel* animal1 = &my_dog;
(*animal1).speak(); //"汪汪队立大功"
Mammel& animal2 = my_dog;
animal2.speak(); //"汪汪队立大功"
Mammel animal3 = my_dog;
animal3.speak(); //"Mammel"
//通过以上测试我们可以看出派生类转化为基类的三种方法:赋值、指针、引用
//通过基类对象的指针或者引用调用虚函数,
//因为派生类对基类中的虚函数进行重写,使用派生类的虚函数替换相同偏移量位置的基类虚函数
//所以基类对象的指针或者引用,可以调用派生类的函数
return 0;
}
42. 编写一个程序计算“三角形、正方形、圆形”三种图形的面积,要求:
a) 抽象出一个基类 Base;
b) 在其中说明一个虚函数用来求面积;
c) 利用派生类定义“三角形、正方形、圆形”;
d) 编写主函数并测试。
#include<iostream>
#include<cmath>
#define PI 3.14
using namespace std;
class Base
{
public:
virtual void calculateArea() {}
};
//正方形
class Square : public Base
{
public:
Square(int a)
{
L = a;
}
virtual void calculateArea()
{
int s = L * L;
cout << "Square_s:" << s << endl;
}
int L;
};
//三角形
class Triangle : public Base
{
public:
Triangle(double a, double b, double c)
{
A = a;
B = b;
C = c;
}
virtual void calculateArea()
{
double s, p;
p = (this->A + this->B + this->C) / 2;
s = sqrt(p * (p - this->A) * (p - this->B) * (p - this->C));
cout << "Triangle_s:" << s << endl;
}
double A, B, C;
};
//圆形
class Circle : public Base
{
public:
Circle(double r)
{
R = r;
}
virtual void calculateArea()
{
double s;
s = PI * R * R;
cout << "Circle_s:" << s << endl;
}
double R;
};
int main()
{
//正方形
Square s(4);
Base* s1 = &s;
s1->calculateArea();
//三角形
Triangle t(3, 4, 5);
Base* s2 = &t;
s2->calculateArea();
//圆形
Circle c(4.1);
Base *s3 = &c;
s3->calculateArea();
return 0;
}
43. 编写一段程序,从标准输入中一次读入一整行,存入 std::string 中,然后 修改该程序,使其一次读入一个词。
#include<iostream>
#include<string>
using namespace std;
//getline会读取换行符,但是不会存储在最后的字符串中
//int main()
//{
// cout << "一次读入一整行" << endl;
// string line;
// while (getline(cin, line))
// {
// cout << line << endl;
// }
// return 0;
//}
//会忽略字符串开头的空白
int main()
{
cout << "一次读入一个词" << endl;
string word;
while (cin >> word)
{
cout << word << endl;
}
return 0;
}
44. 请说明std::string类的输入运算符和getline函数分别是如何处理空白字符的。
#include<iostream>
#include<string>
using namespace std;
/*标准库string的输入运算符自动忽略字符串开头的空白,
从第一个真正的字符起,到遇到下一处空白为止*/
/*getline会保留字符串开头的空白,读取数据直到遇到换行符,
会读取换行符,但是不会存储在最后的字符串中*/
int main()
{
string word, line;
cout << "读取字符串的方式:1、逐词读取,2、整行读取" << endl;
char ch;
cin >> ch;
if (ch == '1')
{
cout << "输入:";
cin >> word;
cout << "输出:";
cout << word << endl;
return 0;
}
cin.clear();//用来更改cin的状态标示符的。
cin.sync();//用来清除缓存区的数据流的。
if (ch == '2')
{
cout <<"输入:";
getline(cin, line);
cout << "输出:";
cout << line << endl;
return 0;
}
cout << "error" << endl;
return -1;
}
45. 编写一段程序从标准输入中读入多个字符串并将它们连接在一起,输出连接 成的大字符串。然后修改上述程序,用空格把输入的多个字符串分隔开来。
#include<iostream>
#include<string>
using namespace std;
//int main()
//{
// char cont = 'y';
// string s, result;
// cout << "请输入第一个字符串:" << endl;
// while (cin >> s)
// {
// result += s;
// cout << "是否继续(y or n)?" << endl;
// cin >> cont;
// if (cont == 'y' || cont == 'Y')
// cout << "请输入下一个字符串:" << endl;
// else
// break;
// }
// cout << "拼接后的字符串:" << result << endl;
// return 0;
//}
int main()
{
char cont = 'y';
string s, result;
cout << "请输入第一个字符串:" << endl;
while (cin >> s)
{
if (!result.size())
result += s;
else
result = result + " " + s;
cout << "是否继续(y or n)?" << endl;
cin >> cont;
if (cont == 'y' || cont == 'Y')
cout << "请输入下一个字符串:" << endl;
else
break;
}
cout << "拼接后的字符串:" << result << endl;
return 0;
}
46. 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字 符串剩余的部分。
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
string s;
//空格不算标点符号
cout << "请输入一个包含标点符号的字符串:" << endl;
getline(cin, s);
for (auto c : s)
{
//ispunct(c) 当c是标点符号时为真
if (!ispunct(c))
cout << c;
}
cout << endl;
return 0;
}
47. 编写一段程序,创建一个含有 10 个整数的 vector 对象,然后使用迭代器将 所有元素的值都变成原来的两倍。输出 vector 对象的内容,检验程序是否正确。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v{ 1,2,3,4,5,6,7,8,9,10 };
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
*it *= 2;
}
for (auto it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
return 0;
}
48. 编写一段程序,比较两个 std::string 对象。再编写一段程序,比较两个 C 风格字符串的内容。
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int main()
{
string s1, s2;
char c1[100], c2[100];
cout << "string:" << endl;
cin >> s1 >> s2;
cout << "c string:" << endl;
cin >> c1 >> c2;
if (s1 > s2)
{
cout << s1 << ">" << s2 << endl;
}
else if(s1 < s2)
{
cout << s1 << "<" << s2 << endl;
}
else
{
cout << s1 << "=" << s2 << endl;
}
if (strcmp(c1, c2) > 0)
{
printf("%s>%s\n", c1, c2);
}
else if (strcmp(c1, c2) < 0)
{
printf("%s<%s\n", c1, c2);
}
else
{
printf("%s=%s\n", c1, c2);
}
return 0;
}
49. 对于下面的程序任务,vector、deque 和 list 哪种容器最为合适?解释你
的选择的理由。如果没有哪一种容器优于其他容器,也请解释理由。
(1) 读取固定数量的单词,将他们按字典序插入到容器中。
(2) 读取未知数量的单词,总是将新单词插入到末尾。删除操作在头部进行。
(3) 从一个文件读取未知数量的整数。将这些数排序,然后将他们打印到标
准输出。
/*
(1)“按字典序插入到容器中”意味着进行插入排序操作,即需要在容器内部频繁进行插入操作,
vector在尾部之外的位置插入与删除很慢,deque在头部和尾部之外的位置插入与删除很慢,
而list在任何位置插入与删除都很快,因此选择list合适。
如果不是必须边读取单词边插入到容器中,可以用vector,将读入的单词依次追加到尾部,
读取完毕后,调用标准库排序算法将单词重排为字典序。
(2)由于需要在头尾分别进行插入、删除操作,因此将vector排除在外,
deque和list都可以用。如果还需要频繁进行随机访问,选择deque。
(3)由于整数占用空间很小,且快速的排序算法需频繁随机访问,将list排除。
由于不需要在头部进行插入与删除,使用vector。
*/
50. 对 6 种创建和初始化 vector 对象的方法,每一种都给出一个实例。解释每 个 vector 包含什么值。
#include<iostream>
#include<vector>
using namespace std;
void printVector(vector<int>& v)
{
for (auto c : v)
{
cout << c << " ";
}
cout << endl;
}
int main()
{
//默认初始化,vector为空
vector<int> v1;
cout << "1." << endl;
printVector(v1);
//拷贝初始化,v2与v1一致
vector<int> v2(v1);
//vector<int> v2 = v1;
cout << "2." << endl;
printVector(v2);
//列表初始化
vector<int> v3{ 1,2,3,4,5,6 };
//vector<int> v3 = { 1,2,3,4,5,6 };
cout << "3." << endl;
printVector(v3);
//迭代器范围初始化
vector<int> v4(v3.begin() + 1, v3.end() - 1);
cout << "4." << endl;
printVector(v4);
//默认值初始化,即6个0
vector<int> v5(6);
cout << "5." << endl;
printVector(v5);
//指定值初始化,即7个3
vector<int> v6(7, 3);
cout << "6." << endl;
printVector(v6);
}