课程:北京大学程序设计与算法(三) MOOC
OJ: OpenJudge
014:MyString
这个题需要写的函数有点多我们来分析一下。
char w1[200],w2[100];
while( cin >> w1 >> w2) {
MyString s1(w1),s2 = s1; //构造函数题目有了,不用写
//复制构造函数没有,需要写
MyString s3(NULL);
s3.Copy(w1); //Copy函数需要写
cout << s1 << "," << s2 << "," << s3 << endl;
//重载输出运算符需要写
s2 = w2; //重载赋值运算需要写,参数为指向字符数组的指针
s3 = s2; //重载赋值运算需要写,参数为MyString类型的对象
s1 = s3;
cout << s1 << "," << s2 << "," << s3 << endl;
有复制构造函数、Copy函数、重载输出运算符、两个重载赋值运算符需要写,一共5个。
复制构造函数
MyString(const MyString& mystr)
{
if (!mystr.p) {
p = NULL;
}
p = new char[strlen(mystr.p) + 1];
strcpy(p, mystr.p);
}
如果参数中p指向的为空单独判断,不为空就new然后复制
Copy函数
void Copy(const char* w)
{
if (!w) {
p = NULL; return;
}
if (this->p != NULL)
delete[]p;
p = new char[(strlen(w) + 1)];
strcpy(p, w);
}
如果参数为空,则p为空;若参数不为空,如果p不为空,需要delete [] p,然后再new并复制
重载输出运算符
friend ostream& operator<< (ostream& o,MyString & mystr)
{
cout << mystr.p;
return o;
}
这个代码较容易一些,注意是友元函数,并且都用的引用。
两个重载赋值运算符
MyString& operator=(const char* s)
{
if (s == this->p)return *this;
if (!s)
{
if (this->p != NULL)delete[]p;
p = NULL;
return *this;
}
if (p)delete[] p;
p = new char[strlen(s) + 1];
strcpy(p, s);
return *this;
}
MyString& operator=(MyString& mystr)
{
if (mystr.p == p)return *this;
if (mystr.p == NULL)
{
if (!p)delete[] p;
p = NULL;
return *this;
}
if (p)delete[] p;
p = new char[strlen(mystr.p) + 1];
strcpy(p, mystr.p);
return *this;
}
这两个函数除了参数不一样,编写思路都大同小异:
如果参数与=左边指向同一处,直接return *this;
如果不一样,若参数为NULL,看p,若p不为NULL ,需要delete ,再赋值NULL
若p为NULL,正常赋值NULL。
若参数不为NULL ,看p,若p不为NULL,需要delete,再new,复制。
小结
该题函数中判断较多,如果只是为了AC这道题的话中间很多判断可以不写,但此处我们考虑全面一些可以锻炼思维,加强分析能力。
完整代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
class MyString {
char* p;
public:
MyString(const char* s) {
if (s) {
p = new char[strlen(s) + 1];
strcpy(p, s);
}
else
p = NULL;
}
~MyString() { if (p) delete[] p; }
// 在此处补充你的代码
MyString(const MyString& mystr)
{
if (!mystr.p) {
p = NULL;
}
p = new char[strlen(mystr.p) + 1];
strcpy(p, mystr.p);
}
void Copy(const char* w)
{
if (!w) {
p = NULL; return;
}
if (this->p != NULL)delete[]p;
p = new char[(strlen(w) + 1)];
strcpy(p, w);
}
friend ostream& operator<< (ostream& o,MyString & mystr)
{
cout << mystr.p;
return o;
}
MyString& operator=(const char* s)
{
if (s == this->p)return *this;
if (!s)
{
if (this->p != NULL)delete[]p;
p = NULL;
return *this;
}
if (p)delete[] p;
p = new char[strlen(s) + 1];
strcpy(p, s);
return *this;
}
MyString& operator=(MyString& mystr)
{
if (mystr.p == p)return *this;
if (mystr.p == NULL)
{
if (!p)delete[] p;
p = NULL;
return *this;
}
if (p)delete[] p;
p = new char[strlen(mystr.p) + 1];
strcpy(p, mystr.p);
return *this;
}
};
int main()
{
char w1[200], w2[100];
while (cin >> w1 >> w2) {
MyString s1(w1), s2 = s1;
MyString s3(NULL);
s3.Copy(w1);
cout << s1 << "," << s2 << "," << s3 << endl;
s2 = w2;
s3 = s2;
s1 = s3;
cout << s1 << "," << s2 << "," << s3 << endl;
}
}
015:看上去好坑的运算符重载
这个题我们先从主函数分析一下:
int n;
while(cin >>n) {
MyInt objInt(n); //构造函数,已写
objInt-2-1-3; //重载-
cout << Inc(objInt); //类型转换
cout <<",";
objInt-2-1;
cout << Inc(objInt) << endl;
}
由此可分析出需要重载-、并重载int,允许将MyInt转换为int
代码 如下:
MyInt& operator-(int a)
{
nVal -= a;
return *this;
}
operator int()
{
return this->nVal;
}
重载减号很容易,减一下参数就行,重载int使MyInt可以转换为int,返回成员变量即可。
完整代码如下:
#include <iostream>
using namespace std;
class MyInt
{
int nVal;
public:
MyInt(int n) { nVal = n; }
// 在此处补充你的代码
MyInt& operator-(int a)
{
nVal -= a;
return *this;
}
operator int()
{
return this->nVal;
}
};
int Inc(int n) {
return n + 1;
}
int main() {
int n;
while (cin >> n) {
MyInt objInt(n);
objInt - 2 - 1 - 3;
cout << Inc(objInt);
cout << ",";
objInt - 2 - 1;
cout << Inc(objInt) << endl;
}
return 0;
}
016:惊呆!Point竟然能这样输入输出
这个题就是需要重载输入输出运算符,比较容易。
friend istream& operator>>(istream& i,Point& point)
{
cin >> point.x >> point.y;
return i;
}
friend ostream& operator<<(ostream& o,Point& point)
{
cout << point.x << ',' << point.y;
return o;
}
完整代码如下:
#include <iostream>
using namespace std;
class Point {
private:
int x;
int y;
public:
Point() { };
// 在此处补充你的代码
friend istream& operator>>(istream& i,Point& point)
{
cin >> point.x >> point.y;
return i;
}
friend ostream& operator<<(ostream& o,Point& point)
{
cout << point.x << ',' << point.y;
return o;
}
};
int main()
{
Point p;
while (cin >> p) {
cout << p << endl;
}
return 0;
}
017:二维数组类
我们从主函数来分析一下:
Array2 a(3, 4); //构造函数
int i, j;
for (i = 0; i < 3; ++i)
for (j = 0; j < 4; j++)
a[i][j] = i * 4 + j;//重载[]运算符
for (i = 0; i < 3; ++i) {
for (j = 0; j < 4; j++) {
cout << a(i, j) << ","; //重载()运算符
}
cout << endl;
}
cout << "next" << endl;
Array2 b; b = a; //此处拷贝深浅没有影响,无需重写
for (i = 0; i < 3; ++i) {
for (j = 0; j < 4; j++) {
cout << b[i][j] << ",";
}
cout << endl;
}
需要写默认构造函数、含参构造函数、重载[]、重载() 四个函数
此处说一下两个重载函数吧
int * operator [](int i)
{
return arr[i];
}
int operator()(int i, int j)
{
return arr[i][j];
}
我们重载[]时,程序将第一个[]读懂时,第二个[]根据返回地址自然按照数据的方式来访问。也就是此处只有i调用了该函数,返回之后剩下的式子跟表达式没什么区别。
重载()时,返回当前存的数字,便不用重载输出运算符了。
完整代码如下:
#include <iostream>
#include <cstring>
using namespace std;
class Array2 {
private:
int x; //行数
int y;//列数
int arr[10][10];
public:
Array2(int x1, int y1)
{
x = x1; y = y1;
}
Array2(){}
int * operator [](int i)
{
return arr[i];
}
int operator()(int i, int j)
{
return arr[i][j];
}
};
int main() {
Array2 a(3,4);
int i,j;
for( i = 0;i < 3; ++i )
for( j = 0; j < 4; j ++ )
a[i][j] = i * 4 + j;
for( i = 0;i < 3; ++i ) {
for( j = 0; j < 4; j ++ ) {
cout << a(i,j) << ",";
}
cout << endl;
}
cout << "next" << endl;
Array2 b; b = a;
for( i = 0;i < 3; ++i ) {
for( j = 0; j < 4; j ++ ) {
cout << b[i][j] << ",";
}
cout << endl;
}
return 0;
}
018:别叫,这个大整数已经很简化了!
这个题也是需要写的函数非常多,我们从主函数来分析一下:
char s[210];
int n;
while (cin >> s >> n) {
CHugeInt a(s); //构造函数,参数为字符数组
CHugeInt b(n); //构造函数,参数为int
cout << a + b << endl; //重载加法运算符,对象加对象;重载输出运算符
cout << n + a << endl; //重载加法运算符,数+对象
cout << a + n << endl; //重载加法运算符,对象+数
b += n; //重载+=运算符
cout << ++b << endl; //重载前自增运算符
cout << b++ << endl; //重载后自增运算符
cout << b << endl;
}
- 构造函数,参数为字符数组
- 构造函数,参数为int
- 重载加法运算符,对象加对象
- 重载输出运算符
- 重载加法运算符,数+对象
- 重载加法运算符,对象+数
- 重载+=运算符
- 重载前自增运算符
- 重载后自增运算符
一共8个函数,但其中最最最核心的是对象加对象的运算。
下面我们一点点来说明:
构造函数,参数为字符数组 \ 构造函数,参数为int
private:
int cbig[210] = { 0 }; //数组存放每一位
int len=0; //总长度
public:
CHugeInt(int smallint,int l=0)
{
for(int i=0;smallint>0;i++)
{
cbig[i] = smallint % 10; //int转数组
smallint /= 10;
len++;
}
if (l)len = l; //此L仅仅用于对象+对象运算时,下面再说
}
CHugeInt(char* bigint)
{
len = strlen(bigint);
for (int i = len - 1,j=0; i >= 0; i--,j++)
{
cbig[j] = bigint[i]-'0'; //反过来存
}
}
首先成员变量有整型数组和长度。
先看参数为int:
这个构造函数实际是将整数转化为数组存放,数组0为存整数的个位,以此类推。
通过循环取模求出每一位的数,再放入数组中,原本的数除以10,直到没有了。
其中 l 仅仅为了后面对象+对象用,后面再说。
再看参数为字符数组:
首先取一下参数的长度存起来,然后用i,j两个指针扫描将参数下标为len-1的存入该数组中下标为0处,注意字符转int减去‘0’。
之所以要这么存,是因为这道题实际上是高精度加法,如果学过那么就能理解了。
(没学过可以搜一下看看,是一种算法,也可以看我下面的讲解,因为比较简单)
这里我简单说一下算法的思想,因为非常的简单,就是让计算机模拟竖式运算,就是小学学的竖式,从个位开始每一位相加,多的进位,把个位存到数组下标0处是为了符合该操作,1+1的话数字肯定存在数组0位吖。
(重点)重载加法运算符,对象加对象!!!!!!
先看代码:
CHugeInt operator +(CHugeInt ch2)
{
int l = (len > ch2.len) ? len : ch2.len;//取相加的数组位较长的
CHugeInt c(0, ++l); //初始化每一位为0,长度l+1
int i;
for ( i = 0; i < l; i++)
{
c.cbig[i] += ch2.cbig[i] + cbig[i]; //每一位相加
if (c.cbig[i] >= 10) //进位
{
c.cbig[i + 1] += c.cbig[i] / 10; //高位加
c.cbig[i] = c.cbig[i] % 10; //低位留
}
}
if (c.cbig[l - 1] == 0)c.len--; //看看进没进位
return c;
}
先存一下两个对象较长的那个数组长度,然后建立临时对象,存一下相加的结果。
临时对象每一位初始化0,长度为l+1(考虑可能进位,比如99+9=108,结果长度为3,多了1)
然后循环将两对象每一位加到临时对象的对应位上,再判断需不需要进位(是否大于10)
若要进位,将结果十位上的数字加到临时对象高一位上,保留个位。
最后判断一下进没进位,最高位是不是0,不是就长度-1
最后临时对象返回,会调用复制构造函数,但此处不涉及深浅拷贝不同,不影响,不用自己写。
重载输出运算符
friend ostream& operator <<(ostream& o, CHugeInt bigint)
{
for (int i = bigint.len - 1; i >= 0; i--)
{
cout << bigint.cbig[i];
}
return o;
}
这个就容易了,有数组下标最尾端输出,因为存的是高位。
重载加法运算符,数+对象 、重载加法运算符,对象+数
friend CHugeInt operator+(CHugeInt bigint, int smallint)
{
CHugeInt newbigint(smallint);
return newbigint + bigint;
}
friend CHugeInt operator+( int smallint,CHugeInt bigint )
{
CHugeInt newbigint(smallint);
return newbigint + bigint;
}
这两个函数大同小异,将参数中的int通过创建新对象的方法转化为数组,再相加就行。
因为前面写了重载加法,所以很方便。
重载+=运算符 、重载前自增运算符 、重载后自增运算符
CHugeInt operator +=(int n)
{
CHugeInt newbigint(n);
*this=this->operator+(newbigint);
return newbigint;
}
CHugeInt operator++()
{
CHugeInt c(1);
*this=this->operator+(c);
return *this;
}
CHugeInt operator++(int k)
{
CHugeInt c(1),d(0);
d = *this;
*this=this->operator+(c);
return d;
}
这三个函数也很像,都调用前面写过的对象+对象,较为方便,不用再写了。
+=:将int存到临时对象,this所指对象与之相加
前++:建立一个临时对象初始化为1,this所指对象与之相加,返回this所指对象
后++:建立一个临时对象初始化为1,,再建立一个初始化为0.
初始化为0的对象保存this,为了返回,因为是返回后才+1
this所指对象与之相加,返回初始化为0的对象
完整代码如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int MAX = 110;
class CHugeInt {
// 在此处补充你的代码
private:
int cbig[210] = { 0 };
int len=0;
public:
CHugeInt(int smallint,int l=0)
{
for(int i=0;smallint>0;i++)
{
cbig[i] = smallint % 10;
smallint /= 10;
len++;
}
if (l)len = l;
}
CHugeInt(char* bigint)
{
len = strlen(bigint);
for (int i = len - 1,j=0; i >= 0; i--,j++)
{
cbig[j] = bigint[i]-'0';
}
}
CHugeInt operator +(CHugeInt ch2)
{
int l = (len > ch2.len) ? len : ch2.len;
CHugeInt c(0, ++l);
int i;
for ( i = 0; i < l; i++)
{
c.cbig[i] += ch2.cbig[i] + cbig[i];
if (c.cbig[i] >= 10)
{
c.cbig[i + 1] += c.cbig[i] / 10;
c.cbig[i] = c.cbig[i] % 10;
}
}
if (c.cbig[l - 1] == 0)c.len--;
return c;
}
friend CHugeInt operator+(CHugeInt bigint, int smallint)
{
CHugeInt newbigint(smallint);
return newbigint + bigint;
}
friend CHugeInt operator+( int smallint,CHugeInt bigint )
{
CHugeInt newbigint(smallint);
return newbigint + bigint;
}
friend ostream& operator <<(ostream& o, CHugeInt bigint)
{
for (int i = bigint.len - 1; i >= 0; i--)
{
cout << bigint.cbig[i];
}
return o;
}
CHugeInt operator +=(int n)
{
CHugeInt newbigint(n);
*this=this->operator+(newbigint);
return newbigint;
}
CHugeInt operator++()
{
CHugeInt c(1);
*this=this->operator+(c);
return *this;
}
CHugeInt operator++(int k)
{
CHugeInt c(1),d(0);
d = *this;
*this=this->operator+(c);
return d;
}
};
int main()
{
char s[210];
int n;
while (cin >> s >> n) {
CHugeInt a(s);
CHugeInt b(n);
cout << a + b << endl;
cout << n + a << endl;
cout << a + n << endl;
b += n;
cout << ++b << endl;
cout << b++ << endl;
cout << b << endl;
}
return 0;
}
标签:return,int,C++,运算符,重载,poj,operator,程序设计,CHugeInt
From: https://blog.csdn.net/qq_74924951/article/details/139534846