首页 > 编程语言 >程序设计与算法(三)C++:第四章poj代码

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

时间:2024-06-10 20:59:16浏览次数:13  
标签:return int C++ 运算符 重载 poj operator 程序设计 CHugeInt

课程:北京大学程序设计与算法(三)     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;
}

标签:return,int,C++,运算符,重载,poj,operator,程序设计,CHugeInt
From: https://blog.csdn.net/qq_74924951/article/details/139534846

相关文章

  • OpenCV RotatedRect类中angle参数解析 C++
    0.前言本文主要探讨RotatedRect类angle的实际含义,为后续学者提供一定的参考。1.官方手册RotatedRect其一构造函数如下图(图1-1)所示。在OpenCV图形坐标系中,水平方向向右为x轴正方向,垂直方向向下为y轴正方向,左上角为(0,0)点。center表示矩形的中心坐标,size中包含了矩形的宽度......
  • DAQmx数据采集---C++版本
    (一)效果展示:(二)采集流程:检索采集设备检索采集通道创建DAQ任务创建采集通道配置采集频率开始采集任务读取采集数据停止采集任务清空采集任务(三)相关接口:该接口可以检测系统已连接的相关采集卡的设备名称paramdata:分配的空间用来存储系统识别到的设备名称......
  • vscode运行C++20,支持模块的实现。
    C++是一个古老的语言,为了跟上时代,一直进行缓慢的演化。在2011年,C++11的发布让这个语言进入21世纪,可以现代化的使用。它有着lambda表达式,auto类型推断。此外使用容器替代低级语言结构,智能指针或其他RAII技术加强了安全编程。我们在编写C++代码应多使用现代化的函数。C++20让编程更......
  • 牛客周赛 Round 46 题解 C++
    目录 A 乐奈吃冰B 素世喝茶C 爱音开灯D 小灯做题E 立希喂猫F 祥子拆团 A 乐奈吃冰#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<queue>#include<set>#include<vector>#include<unordered_map>......
  • C++缺省参数、缺省参数的概念、缺省参数的分类、函数重载、函数重载的概念、C++支持函
    文章目录前言一、缺省参数1.缺省参数的概念2.缺省参数的分类二、函数重载1.函数重载的概念2.C++支持函数重载的原理三、引用1.引用的概念2.引用的特性3.常引用4.引用的使用场景5.传值和传引用效率比较6.引用和指针的区别总结前言C++缺省参数、缺省参数......
  • C语言 & 图形化界面方式连接MySQL【C/C++】【图形化界面组件分享】
      博客主页:花果山~程序猿-CSDN博客文章分栏:MySQL之旅_花果山~程序猿的博客-CSDN博客关注我一起学习,一起进步,一起探索编程的无限可能吧!让我们一起努力,一起成长!目录一.配置开发环境 二,接口介绍1.mysql_init2.mysql_real_connect3.mysql_query4.对select结果分析......
  • 【四种语言一网打尽(C\C++\Python\Golang)】L1-006 连续因子
    L1-006连续因子一个正整数N的因子中可能存在若干连续的数字。例如630可以分解为3×5×6×7,其中5、6、7就是3个连续的数字。给定任一正整数N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。输入格式:输入在一行中给出一个正整数N(1<N<2^31)。输......
  • 从零手写实现 nginx-15-nginx.conf 解析处理转换为 POJO
    前言大家好,我是老马。很高兴遇到你。我们为java开发者实现了java版本的nginxhttps://github.com/houbb/nginx4j如果你想知道servlet如何处理的,可以参考我的另一个项目:手写从零实现简易版tomcatminicat手写nginx系列如果你对nginx原理感兴趣,可以阅读:从零......
  • C++~~期末复习题目讲解---lijiajia版本
    目录1.类和对象(3)创建对象的个数(3)全局变量,局部变量(4)构造函数的执行次数(5)静态动态析构和构造顺序(6)初始化顺序和声明顺序(7)构造和复制构造(8)拷贝构造的三种情况和例题讲解2.继承和派生(1)派生的构造和析构(2)赋值的兼容性规则3.虚函数1.类和对象(1)类和对象的三个特征:封......
  • 2024年华为OD机试真题-快递员的烦恼-C++-OD统一考试(C卷D卷)
     2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集) 题目描述:快递公司每日早晨,给每位快递员推送需要送到客户手中的快递以及路线信息,快递员自己又查找了一些客户与客户之间的路线距离信息,请你依据这些信息,给快递员设计一条最短路径,告诉他最短路......