2022级吉林大学面向对象第三次上机测试
【注:解答全部为本人所写,仅供同学们学习时参考使用,请勿照搬抄袭!】
运算符重载、动态内存管理
1.已知字符串类MyString的定义为:
class MyString
{
public:
MyString(const char* pData= NULL); // 普通构造函数
MyString(const MyString &); // 拷贝构造函数
~ MyString(); // 析构函数
MyString & operator =(const MyString &); // 赋值函数
MyString& operator += (const MyString &);
operator char* () const; // 自动转换函数
private:
char *mpData; // 用于保存字符串
};
全局函数:
const MyString operator + (const MyString &,const MyString &);//字符串连接
ostream& operator<<(ostream& os, const MyString& str); //定向输出
请完整实现MyString类和指定的全局函数。(可以使用new,delete运算以及strcpy,strlen,…等库函数,还可以定义其他辅助函数)。
#include <iostream>
#include <string.h>
using namespace std;
class MyString {
friend ostream& operator<<(ostream& os, const MyString& str);
friend const MyString operator+(const MyString &s1,const MyString &s2);
public:
MyString(const char* pData = NULL) {
this->mpData = new char[5];
strcpy(this->mpData, pData);
} // 普通构造函数
MyString(const MyString &s) {
this->mpData = new char[10];
strcpy(this->mpData, s.mpData);
} // 拷贝构造函数
~ MyString() { delete this->mpData;} // 析构函数
MyString& operator=(const MyString &s) {
this->mpData = new char[10];
strcpy(this->mpData, s.mpData);
return *this;
} // 赋值函数
MyString& operator+=(const MyString &s) {
int len=strlen(mpData)+strlen(s.mpData)+1;
char *tmp = new char[len];
strcpy(tmp, mpData);
strcat(tmp, s.mpData);
strcpy(mpData, tmp);
delete[] tmp;
return *this;
}
operator char* () const; // 自动转换函数
private:
char* mpData; // 用于保存字符串
};
const MyString operator+(const MyString &s1,const MyString &s2) {
return MyString(s1)+=s2;
}//字符串连接
ostream& operator<<(ostream& os, const MyString& str) {
os << str.mpData << endl;
return os;
} //定向输出
int main()
{
MyString a1("123");
MyString a2("456");
MyString c = a1 + a2;
cout << c << endl;
return 0;
}
2.对任意一个正的实数,总可以唯一地表示成a0+1/(a1+1/(a2+1/(a3+1/…)))的形式,简记为a0+a1+a2+a3+…+ak。(ai为大于0 的正整数,长度为k。若数为无理数,则k为无穷大) ,并称这种形式的数为连分数。
a)请使用类的自关联方式设计并实现连分数类, 此类的每个对象代表一个有理数的连分数形式,且假定连分数的长度均小于MAXLEN(MAXLEN设为数30)。
该类主要功能有:
1)对指定的i,返回ai值;
2)计算连分数的前q项(a0+a1+a2+a3+…+aq)所对应分数的分子和分母;
3)输出此分数的前q项,格式为:a0+a1+a2+a3+…+aq;
b)给出主程序,使用该类计算连分数的前n项对应的分数逼近PI值的程度(计算差即可。PI可用math.h中的M_PI常量)。
(由此可见祖老师给出的约率和密率是多么地精确!连分数的收敛速度多么地快!)
例如主程序的输出可能如下:
PI=3.141592653589793
前1项为3
前1项对应分数为3/1
前1项对应分数的值为3
前1项对应分数与3.141592653589793的差为0.1415926535897931
前2项为3+7
前2项对应分数为22/7
前2项对应分数的值为3.142857142857143
前2项对应分数与3.141592653589793的差为-0.001264489267349741
前3项为3+7+15
前3项对应分数为333/106
前3项对应分数的值为3.141509433962264
前3项对应分数与3.141592653589793的差为8.321962752896503e-005
前4项为3+7+15+1
前4项对应分数为355/113
前4项对应分数的值为3.141592920353983
前4项对应分数与3.141592653589793的差为-2.667641891848736e-007
前5项为3+7+15+1+292
前5项对应分数为103993/33102
前5项对应分数的值为3.141592653011902
前5项对应分数与3.141592653589793的差为5.778905119192823e-010
前6项为3+7+15+1+292+1
前6项对应分数为104348/33215
前6项对应分数的值为3.141592653921421
前6项对应分数与3.141592653589793的差为-3.316279286770529e-010
前7项为3+7+15+1+292+1+1
前7项对应分数为208341/66317
前7项对应分数的值为3.141592653467437
前7项对应分数与3.141592653589793的差为1.223564103768754e-010
前8项为3+7+15+1+292+1+1+1
前8项对应分数为312689/99532
前8项对应分数的值为3.141592653618936
前8项对应分数与3.141592653589793的差为-2.914350748575711e-011
前9项为3+7+15+1+292+1+1+1+2
前9项对应分数为833719/265381
前9项对应分数的值为3.141592653581078
前9项对应分数与3.141592653589793的差为8.715344852056051e-012
前10项为3+7+15+1+292+1+1+1+2+1
前10项对应分数为1146408/364913
前10项对应分数的值为3.141592653591404
前10项对应分数与3.141592653589793的差为-1.610862485068587e-012
…
#include <iostream>
#include <vector>
using namespace std;
const int MAXLEN = 30;
class CFraction {
private:
vector<int> ai; // 存储a0,a1,a2,...,ak
public:
int length() { // 返回连分数的长度
return ai.size();
}
void add(int a) { // 添加下一个ai
ai.push_back(a);
}
void print(int q) { // 输出连分数的前q项
cout << ai[0];
for (int i = 1; i < q; i++) {
cout << "+" << ai[i];
}
cout << endl;
}
void fraction(int q, int& num, int& den) { // 计算连分数的前q项所对应的分数
num = ai[q - 1];
den = 1;
for (int i = q - 2; i >= 0; i--) {
int tmp = num;
num = ai[i] * num + den;
den = tmp;
}
}
};
CFraction getCFraction(double x, int maxLen) { // 将实数转化为连分数
CFraction cf;
int a = int(x);
cf.add(a);
double r = x - a;
while (r > 0 && cf.length() < maxLen) {
r = 1 / r;
a = int(r);
cf.add(a);
r -= a;
}
return cf;
}
int main()
{
double pi = 3.14159265358979323;
for (int i = 1; i <= 10; i++) {
CFraction cf = getCFraction(pi, i);
int num = 0, den = 0;
cf.fraction(i, num, den);
double approx = double(num) / den;
cout << "前" << i << "项为";
cf.print(i);
cout << "前" << i << "项对应分数为" << num << "/" << den << endl;
cout << "前" << i << "项对应分数的值为" << approx << endl;
cout << "前" << i << "项对应分数与" << pi << "的差为" << pi - approx << endl << endl;
}
return 0;
}
3、在全局函数void f(int n,int m)中动态建立一个大小为nxm的二维整数数组,并对每个数组元素依次赋值为1,2,3,…,m*n, 再输出每行和每列元素的和,退出函数前释放此数组。
#include <bits/stdc++.h>
using namespace std;
void f(int n, int m) {
int ** array = new int* [n];
for (int i = 0; i < n; i++) {
array[i] = new int [m];
}
int count = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
array[i][j] = count;
count++;
}
}
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = 0; j < m; j++) {
sum += array[i][j];
}
cout << "Row " << i + 1 << " : sum = " << sum << endl;
}
puts("");
for (int j = 0; j < m; j++) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += array[i][j];
}
cout << "Col " << j + 1 << " : sum = " << sum << endl;
}
for (int i = 0; i < n; i++) {
delete[] array[i];
}
delete[] array;
}
int main()
{
f(3, 4);
return 0;
}
4、已有类A声明如下:
class A
{
public:
A(int n):data(n) {}
int Data() const {return data;}
private:
int data;
};
在全局函数void g(int n) 中动态建立一个大小为n的一维指针数组, 数组元素指向A类对象,各对象的data数据成员各不相同, 分别为1,2,3,…,n。创建数组后,使用(例如输出)各对象的data值,最后释放此数组。
#include <bits/stdc++.h>
using namespace std;
class A {
public:
A(int n) : data(n) {}
int Data() const {
return data;
}
private:
int data;
};
void g(int n) {
A** array = new A*[n];
for (int i = 0; i < n; i++) {
array[i] = new A(i + 1);
cout << array[i]->Data() << endl;
}
for (int i = 0; i < n; i++) {
delete[] array[i];
}
delete[] array;
}
int main()
{
g(5);
return 0;
}
5、如何建立一个二维整数数组类,使得其大小可动态决定,并且访问时,可像普通数组一样使用。如 建立这个二维整数数组类的一个对象obj后, 访问其第二行、第三列元素,可写成:
obj[1][2] = 5;
cout<<obj[1][2];
#include <bits/stdc++.h>
using namespace std;
class Array{
public:
Array(int row, int col) {
m_row = row;
m_col = col;
m_data = new int* [m_row];
for (int i = 0; i < m_row; i++) {
m_data[i] = new int [m_col];
}
}
~Array() {
for (int i = 0; i < m_row; i++) {
delete[] m_data[i];
}
delete[] m_data;
}
int* operator[] (int index) {
return m_data[index];
}
private:
int m_row;
int m_col;
int** m_data;
};
int main()
{
Array obj(2, 3);
obj[1][2] = 2;
cout << obj[1][2];
return 0;
}