程序设计与算法(三)C++:第四章poj代码

课程:北京大学程序设计与算法(三)     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;      
	}
  1. 构造函数,参数为字符数组 
  2. 构造函数,参数为int
  3. 重载加法运算符,对象加对象
  4. 重载输出运算符
  5. 重载加法运算符,数+对象
  6. 重载加法运算符,对象+数
  7. 重载+=运算符
  8. 重载前自增运算符
  9. 重载后自增运算符

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

相关推荐

  1. 程序设计算法C++:poj代码

    2024-06-10 22:08:01       27 阅读
  2. C++程序设计语言-郑莉 实验报告及代码

    2024-06-10 22:08:01       59 阅读
  3. C++程序设计版郑莉)-------

    2024-06-10 22:08:01       30 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-10 22:08:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-10 22:08:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-10 22:08:01       82 阅读
  4. Python语言-面向对象

    2024-06-10 22:08:01       91 阅读

热门阅读

  1. selenium的使用教程

    2024-06-10 22:08:01       35 阅读
  2. 编译与链接

    2024-06-10 22:08:01       32 阅读
  3. Vue 路由实现组件切换

    2024-06-10 22:08:01       29 阅读
  4. C++设计模式---工厂模式

    2024-06-10 22:08:01       23 阅读
  5. 使用Spring Boot设计对象存储系统

    2024-06-10 22:08:01       30 阅读
  6. MySQL实体类框架

    2024-06-10 22:08:01       25 阅读
  7. 修复www服务trace漏洞

    2024-06-10 22:08:01       36 阅读
  8. Qt中图表图形绘制类介绍

    2024-06-10 22:08:01       23 阅读