Coursera课程笔记----C++程序设计----Week4
运算符重载(week 4)
运算符重载-基本概念
运算符
- C++预定义表示对数据的运算
- +,-,*,/.....
- 只能用于基本的数据类型
- 整形,实型,字符型,逻辑型等
- C++提供了数据抽象的手段➡️用户自己定义数据类型--类
- 调用类的成员函数,操作它的对象
- 类的成员函数操作对象时,有时候会很不方便
- 在数学上,两个复数可以直接进行+/-等
- 在C++中,直接将+和-用于复数是不允许的
运算符重载
-
对抽象数据类型也能够直接使用C++提供的运算符
- 程序更简洁
- 代码更容易理解
-
举例:
- complex_a和complex_b两个复数对象
- 求两个复数的和,希望能直接写成:complex_a +
-
对已有运算符赋予多重的含义
- 使同一运算符作用于不同类型的数据时,产生不同的行为
-
目的是扩展C++中提供的运算符的适用范围,以用于类所表示的抽象数据类型
-
实质是函数重载
返回值类型 operator 运算符 (形参表)
{
......
}
-
在程序编译时
- 把含运算符的表达式,当作对运算符函数的调用
- 把运算符的操作数,当作运算符函数的参数
- 运算符多次被重载时,根据实参的类型决定调用哪个运算符函数
- 运算符可以被重载为普通函数,也可以被重载为类的成员函数
- 重载为普通函数时,参数个数为运算符目数
- 重载为成员函数时,参数个数为运算符目数-1
class Complex{
public:
Complex(double r = 0.0, double i = 0.0)
{
real = r;
imaginary = i;
}
double real; //real part
double imaginary; //imaginary part
};
Complex operator+ (const Complex &a,const Complex &b)
{
return Complex(a.real+b.real,a.imaginary+b.imaginary);
} //“类名(参数表)”就代表一个对象
Complex a(1,2),b(2,3),c;
c = a + b;
class Complex{
public:
Complex(double r =0.0,double m = 0.0):
real(r),imaginary(m){}
Complex operator+ (const Complex &);
Complex operator-(const Complex &);
}
Complex Complex::operator+(const Complex & operand2){
return Complex(real + operand2.real,
imaginary + operand2.imaginary);
}
Complex Complex::operator-(const Complex & operand2){
return Complex(real - operand2.real,
imaginary - operand2.imaginary);
}
int main(){
Complex x,y(4.3,8.2),z(3.3,1,1);
x = y + z;
x = y - z;
return 0;
}
赋值运算符的重载
赋值运算符‘=’重载
- 赋值运算符两边类型可以不匹配
- 把一个int类型变量赋值给一个Complex对象
- 把一个char* 类型的字符串赋值给一个字符串对象
- 需要重载赋值运算符‘=’
- 只能重载为成员函数
- 例:编写一个长度可变的字符串类String
- 包含一个char *类型的成员变量,指向动态分配的存储空间
- 该存储空间用于存放'\0'结尾的字符串
class String{
private:
char* str;
public:
String():str(NULL){ }//构造函数,初始化str为NULL
const char* c_str() {return str;}
char* operator = (const char* s);
~String();
}
//重载'='->obj="hello"能够成立
char *String::operator = (const char* s)
{
if(str) delete[] str;
if(s){ //s不为空时才执行拷贝
str = new char[strlen[s]+1];
strcpy(str,s);
}
else
str = NULL;
return str;
};
String::~String(){
if(str) delete [] str;
};
int main(){
String s;
s = "Good Luck,";
cout<<s.c_str()<<endl;
//String s2 = "hello!"; 此条语句不注释掉会报错
//因为这句是初始化语句而不是赋值语句,所以不会调用=的重载函数
s = "Shenzhou 8!";
cout<<s.c_str()<<endl;
return 0;
}
重载赋值运算符的意义——浅复制和深复制
-
S1 = S2;
-
浅复制/浅拷贝(如果不进行重构,系统会系统生成一个缺省的,会发生浅拷贝现象)
- 执行逐个字节的复制工作
- 会产生内存垃圾or内存错误
-
深复制/深拷贝
-
将一个对象中指针变量指向的内容,复制到另一个对象中指针成员对象所指的对象
-
如何实现:在class String里添加成员函数
-
在成员变量中包含指针的情况下,都应该主动重载赋值运算符和复制构造函数。
//使S1=S2不再是浅拷贝而是深拷贝 String & operator = (const String & s){ if(str) delete[] str; str = new char[strlen(s.str)+1]; strcpy(str,s.str); return *this; }
-
自身给自身赋值时,该怎么处理?
*添加一句:if(str == s.str) return this
-
对operator = 返回值类型的讨论
- void 好不好?
- NO.考虑a = b = c
- String 好不好?(而不是String &)
- 可以是可以,但是不好
- 运算符重载时,要求一个好的风格,尽量保留运算符原本的特性
- 考虑:(a=b)=c; //会修改a的值
- 分别等价于:(a.operator=(b)).operator(c); 在该式中,只有(a=b)返回的对象类型为引用时,才能顺利成为下一个operator函数作用的对象,进行进一步赋值的工作
以上String类的问题
-
为String类编写复制构造函数时,会面临和赋值运算符‘=’同样的问题(浅拷贝or深拷贝),也用同样的方法去处理
String::String(String &s) { if(s.str){ str = new char[strlen(s.str)+1]; strcpy(str,s.str); } else str = NULL; }
运算符重载外友元函数
- 通常,将运算符重载为类的成员函数
- 重载为友元函数的情况:
- 成员函数不能满足使用要求
- 普通函数,不能访问类的私有成员
class Complex{
double real,imag;
public:
Complex(double r, double i):real(r),imag(i){ };
Complex operator+(double r)
};
Complex Complex::operator+(double r){//能解释c+5
return Complex(real + r, imag);
}
- 经过上述重载后:
int main()
{
Complex c;
c = c + 5;//有定义,相当于c = c.operator + (5);
c = 5 + c;//编译出错
}
- 为了使上述表达式能成立,需要将+重载为普通函数
Complex operator+(double r, const Complex & c){
return Complex(c.real+r,c.imag)
}
- 但普通函数不能访问私有成员,因此只能将运算符+重载为友元函数
class Complex{
double real,imag;
public:
Complex(double r, double i):real(r),imag(i){ };
Complex operator+(double r)
friend Complex operator+(double r, const Complex & c);
};
实例:长度可变的整形数组类
int main(){//要编写可变长整形数组类,使之能如下使用:
CArray a;//开始里的数组是空的
for(int i = 0;i < 5;++i)
a.push_back(i); //要用动态分配的内存来存放数组元素,需要一个指针成员变量
CArray a2,a3;
a2 = a;//要重载“=”
for( int i = 0; i < a.klength();++i)
cout<<a2[i]<<" ";
a2 = a3;//a2是空的
for(int i = 0; i < a2.length();++i)//a2.length()返回0
cout<<a2[i]<<" ";//要重载"[]"
cout<<endl;
a[3] = 100;
CArray a4(a);//要自己写复制构造函数
for(int i = 0; i < a4.length();++i)
cout<<a4[i]<<" ";
return 0;
//输出结果为 0 1 2 3 4
//0 1 2 100 4
}
class CArray{
int size;//数组元素的个数
int *ptr;//指向动态分配的数组
public:
CArray(int s = 0); //s代表数组元素的个数
CArray(CArray &a);
~CArray();
void push_back(int v);//用于在数组尾部添加一个元素v
CArray & operator=(const CArray & a); //用于数组对象间的赋值
int length(){return size;}//返回数组元素个数
int & CArray::operator[](int i) //返回值为int不行,不能支持a[i] = 4
{//用以支持根据下标访问数组元素,n=a[i] 和a[i]=4这样的语句,如果一个函数调用的返回值不是引用,我们不能把它写在等号左边(非引用的函数返回值不可以作为左值使用)
return ptr[i];
}
};
CArray::CArray(int s):size(s)
{
if(s == 0)
ptr == NULL;
else
ptr = new int[s];
}
CArray::CArray(CArray &a){
if(!a.ptr){
ptr = NULL;
size = 0;
return;
}
ptr = new int[a.size];
memcpy(ptr,a.ptr,sizeof(int) * a.size);//? 哦这个是个乘号不是指针!!!把我看懵了都!!
size = a.size;
}
CArray::~CArray()
{
if(ptr) delete []ptr;
}
CArray & CArray::operator=(const CArray &a)
{//赋值号的作用是使等号左边对象里存放的数组,大小和内容都和右边的对象一样
if(ptr == a.ptr)//防止a=a这样的赋值导致出错
return *this;
if(a.ptr == NULL){//若a为空
if(ptr) delete[] ptr;
ptr = NULL;
size = 0;
return *this;
}
if(size<a.size){//如果原有空间足够大,就不用分配新的空间
if(ptr)
delete[] ptr;
ptr = new int[a.size];
}
memcpy(ptr,a.ptr,sizeof(int) * a.size);
size = a.size;
return *this;
}//CArray & CArray::operator=(const CArray &a)
void CArray::push_back(int v)//写起来简单但是效率较低的做法,比较好的做法是预先分配稍多的空间,也就是vetcor
{ //在数组尾部添加一个元素
if(ptr)
{
int * tmpPtr = new int[size+1]; //重新分配空间
memcpy(tmpPtr,ptr,sizeof(int)*size); //拷贝原数组内容
delete []ptr;
ptr = tmpPtr
}
else//数组本来是空的
ptr = new int[1];
ptr[size++] = v;//加入新的数组元素
}
流插入运算符和流提取运算符的重载
问题引入
- cout<<5<<"this" 为什么能够成立
- cout是什么?"<<"为什么能用在cout上
流插入&流提取运算符的重载
-
cout是在iostream中定义的,ostream类的对象
-
"<<"能用在cout上是因为,在iostream里对"<<"进行了重载
-
如何重载才能使得cout << 5;//等价于cout.operator<<(5);
和 cout<< "this"//等价于cout.operator<<("this");
都能成立?
-
重载成ostream类的成员函数
void ostream::operator<<(int n) { ...//输出n的代码 return; }
-
-
如何重载才能使得cout<<5<<"this"//连续书写
能够成立?
-
重载成ostream类的成员函数
ostream & ostream::operator<<(int n)//和上面那个单独实现的返回值是不同的 { ...//输出n的代码 return *this; } ostream & ostream::operator<<(const char* n) { ...//输出n的代码 return *this; }
-
-
cout<<5<<"this" 本质上的函数调用的形式是什么?
- cout.operator<<(5).operator<<("this");
例题
-
假定下面程序输出为5hello,应该补写什么
class CStudent{ public: int nAge; }; int main(){ CStudent s; s.nAge = 5; cout << s << "hello"; return 0; } //这里只能重载为全局函数,因为cout对象的ostream类已经在iostream里写好了
-
答案
ostream & operator <<(ostream & o, const CStudent & s){//重载成全局函数,操作数数目=函数的参数个数 o<<s.nAge; return o; }
-
假定c是Complex复数类的对象,现在希望写"cout << c;",就能以"a+bi"的形式输出c的值,写"cin>>c;",就能从键盘接受"a+bi"形式的输入,并且使得c.real = a, c.imag = b;
-
答案:
#include <iostream> #include <string> #include <cstdlib> using namespace std; class Complex{ double real,imag; public: Complex(double r = 0, double i = 0):real(r),imag(i){}; friend ostream & operator << (ostream & os, const Complex &c); friend istream & operator >> (istream & is, const Complex &c); }; ostream & operator << (ostream & os, const Complex &c) { os << c.real << "+" <<c.imag << "i"; //以"a+bi的形式输出 return os; } istream & operator >> (istream & is, const Complex &c) { string s; is >> s;//将"a+bi"作为字符串读入,"a+bi"中间不能有空格 int pos = s.find("+",0); string sTmp = s.substr(0,pos);//分离出代表实部的字符串 c.real = atof(sTmp.c_str());//atof库函数能将const char*指针指向的内容转换成float sTmp = s.substr(pos+1,s.length()-pos-2);//分离出代表虚部的字符串 c.imag = atof(sTmp.c_str()); return is; }
自增&自减运算符的重载
基本概念
- 自加++/自减--运算符有前置/后置之分
- 前置运算符作为一元运算符重载
- 重载为成员函数
- T operator++();
- T operator--();
- 重载为全局函数
- T operator++(T);
- T operator--(T);
- ++obj,obj.operator++(),operator++(obj)都调用上述函数
- 重载为成员函数
- 后置运算符作为二元运算符重载
- 多写一个参数,参数本身是无意义的,只是为了区别前置后置
- 重载为成员函数
- T operator++(int);
- T operator--(int);
- 重载为全局函数
- T operator++(T,int);
- T operator--(T,int);
- obj++,obj.operator++(0),operator++(obj,0)都调用上述函数
举例
-
int main(){ CDemo d(5); cout << (d++) <<","; //=d.operator++(0); cout << d << ","; cout << (++d) << ","; //=d.operator++(); cout << d << endl; cout << (d--) <<","; //=operator--(d,0) cout<< d << ","; cout << (--d) << ","; //=operator--(d); cout << d << endl; return 0; //输出结果 5,6,7,7\n7,6,5,5 }
-
答案:
class CDemo{ private: int n; public: CDemo(int i = 0):n(i){ } CDemo operator++(); CDemo operator++(int); operator int(){return n;} //强制类型转换符的重载 friend CDemo operator--(CDemo &); friend CDemo operator--(CDemo &, int); }; CDemo CDemo::operator++(){//前置++ n++; return *this; } CDemo CDemo::operator++(int k){//后置++ CDemo tmp(*this);//记录修改前的对象,因为成员变量无指针,所以此时复制构造函数不需要重载 n++; return tmp;//返回修改前的对象 } CDemo operator--(CDemo &d){//前置-- d.n--; return d; } CDemo operator--(CDemo &d, int k){//后置-- CDemo tmp(d); d.n--; return tmp; }
-
注意:
operator int(){ return n;} //int 所为一个类型强制转换运算符被重载 Demo s; (int) s; //等效于s.int();
- 类型强制转换运算符被重载时
- 不能写返回值类型
- 实际上其返回值类型为类型强制转换运算符所代表的类型
- 类型强制转换运算符被重载时
运算符重载注意事项
- C++不允许定义新的运算符
- 重载后运算符的含义应该符合日常习惯
- complex_a + complex_b
- word_a > word_b
- data_b = data_a + n
- 运算符重载不改变运算符的优先级
- 以下运算符不能重载: "."".*"::""?:""sizeof"
- 重载运算符()[]->或者赋值运算符=时,重载函数必须声明为类的成员函数
习题
Choice1
- 如果将运算符 “ * ” 重载为某个类的成员运算符(也即成员函数),则该成员函数的参数个数是?
- 0个(指针的解引用运算)或1个(算数乘法运算)
注:填空题在Coursera提交时,文件中只需出现填进去的内容即可
Quiz 1
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class Complex {
private:
double r,i;
public:
void Print() {
cout << r << "+" << i << "i" << endl;
}
Complex & operator = (string s){
int pos = s.find("+",0);
string sTmp = s.substr(0,pos);//分离出代表实部的字符串
r = atof(sTmp.c_str());//atof库函数能将const char*指针指向的内容转换成float
sTmp = s.substr(pos+1,s.length()-pos-2);//分离出代表虚部的字符串
i = atof(sTmp.c_str());
return *this;
}
};
int main() {
Complex a;
a = "3+4i"; a.Print();
a = "5+6i"; a.Print();
return 0;
}
Quiz 2
#include <iostream>
using namespace std;
class MyInt {
int nVal;
public:
MyInt(int n) { nVal = n; }
int ReturnVal() { return nVal; }
// 在此处补充你的代码
MyInt & operator- (int i){
nVal-= i;
return *this;
}
};
int main () {
MyInt objInt(10);
objInt-2-1-3;
cout << objInt.ReturnVal();
cout <<",";
objInt-2-1;
cout << objInt.ReturnVal();
return 0;
}
Quiz 3
#include <iostream>
#include <cstring>
using namespace std;
// 在此处补充你的代码
class Array2{
private:
int *p;
int x,y;
public:
Array2(int i, int j) :x(i),y(j){p = new int[i*j];}
Array2():x(0),y(0),p(NULL){}
int* operator[](int i) {
return (p + i * y);
}//注意!这里是返回指针而不是返回对象的引用!这样第二个[]就能直接取出数值了!!
int& operator()(int i,int j){
return p[i*y + j];
}
Array2& operator=(const Array2& a){
if(a.p == NULL){
p = NULL;
return *this;
}
if(p) delete[] p;
x = a.x;
y = a.y;
p = new int[x*y];
memcpy(p,a.p,sizeof(int)*x*y);
return *this;
}
};
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;
}
Quiz4 大整数的加减乘除
#include <iostream>
#include <string>
#include <cstdlib>
#include <algorithm> //reverse函数所需的头文件
using namespace std;
class BigInt
{
private:
string values;//保存所有位上的数字
bool flag;//true表示正数,false表示负数,0默认为正数
inline int compare(string s1,string s2)
{
if(s1.size() < s2.size())
return -1;
else if(s1.size() > s2.size())
return 1;
else return s1.compare(s2);
}
public:
BigInt():values("0"),flag(true){ };
BigInt(string str)//类型转换构造函数(默认为正整数)
{
values = str;
flag = true;
}
public:
friend ostream& operator << (ostream& os,const BigInt& bigInt);//重载输出操作符
friend istream& operator >> (istream& is,BigInt& bigInt);//重载输入操作符
BigInt operator+ (const BigInt& rhs);//加法操作符重载
BigInt operator- (const BigInt& rhs);//减法操作符重载
BigInt operator* (const BigInt& rhs);//乘法操作符重载
BigInt operator/ (const BigInt& rhs);//除法操作符重载
};
/*
* 重载流提取运算符'>>',输出一个整数
*/
ostream& operator << (ostream& os, const BigInt& bigInt)
{
if(!bigInt.flag)
{
os << '-';
}
os << bigInt.values;
return os;
}
/*
* 重载流插入运算符'>>',输入一个正整数
*/
istream& operator >> (istream& is, BigInt& bigInt)
{
string str;
is >> str;
bigInt.values = str;
bigInt.flag = true;
return is;
}
/*
* 两个正整数相加
*/
BigInt BigInt::operator+(const BigInt &rhs)
{
BigInt ret;
ret.flag = true;//正数相加恒为正数
string lvalues(values),rvalues(rhs.values);
//特殊情况处理
if(lvalues == "0")
{
ret.values = rvalues;
return ret;
}
if(rvalues == "0")
{
ret.values = lvalues;
return ret;
}
//调整s1与s2的长度
unsigned int i, lsize, rsize;
lsize = lvalues.size();
rsize = rvalues.size();
if(lsize < rsize)
{
for (i = 0; i < rsize - lsize; i++)//在lvalues左边补0
{
lvalues = "0" + lvalues;
}
}
else
{
for (i = 0; i < lsize - rsize; i++)//在rvalues左边补0
{
rvalues = "0" + rvalues;
}
}
//处理本质情况
int n1,n2;
n2 = 0;
lsize = lvalues.size();
string res = "";
reverse(lvalues.begin(),lvalues.end());//颠倒字符串,方便从低位起计算
reverse(rvalues.begin(),rvalues.end());
for (int i = 0; i < lsize; i++) {
n1 = (lvalues[i] - '0' + rvalues[i] - '0' + n2) % 10; //n1代表当前位的值
n2 = (lvalues[i] - '0' + rvalues[i] - '0' + n2) / 10; //n2代表进位
res = res + char(n1 + '0');
}
if(n2 == 1) //当计算完毕后,最终还留有一个进位的时候
{
res = res + "1";
}
reverse(res.begin(), res.end());
ret.values = res;
return ret;
}
/*
* 两个正整数相减
*/
BigInt BigInt::operator-(const BigInt &rhs)
{
BigInt ret;
string lvalues(values), rvalues(rhs.values);
//处理特殊情况
if(rvalues == "0")
{
ret.values = lvalues;
ret.flag = true;
return ret;
}
if(lvalues == "0")
{
ret.values = rvalues;
ret.flag = false;
return ret;
}
//调整s1与s2的长度
unsigned int i, lsize, rsize;
lsize = lvalues.size();
rsize = rvalues.size();
if(lsize < rsize)
{
for (i = 0; i < rsize - lsize; i++)//在lvalues左边补0
{
lvalues = "0" + lvalues;
}
}
else
{
for (i = 0; i < lsize - rsize; i++)//在rvalues左边补0
{
rvalues = "0" + rvalues;
}
}
//调整使被减数大于减数
int t = lvalues.compare(rvalues);//相等返回0,str1<str2返回负数,str1>str2返回正数
if(t<0)
{
ret.flag = false;
string tmp = lvalues;
lvalues = rvalues;
rvalues = tmp;
}
else if(t == 0)
{
ret.values = "0";
ret.flag = true;
return ret;
}
else
{
ret.flag = true;
}
//处理本质情况
unsigned int j;
lsize = lvalues.size();
string res = "";
reverse(lvalues.begin(),lvalues.end());//颠倒字符串,方便从低位开始计算
reverse(rvalues.begin(),rvalues.end());
for (int i = 0; i < lsize; i++)
{
if(lvalues[i] < rvalues[i])//若不足,向前借一位
{
j = 1;
while (lvalues[i+j] == '0')
{
lvalues[i+j] = '9';
j++;
}
lvalues[i+j] -= 1;
res = res + char(lvalues[i] + ':' - rvalues[i]);
}
else
{
res = res + char(lvalues[i] - rvalues[i] + '0');
}
}
reverse(res.begin(),res.end());
res.erase(0,res.find_first_not_of('0'));//去掉前导0
ret.values = res;
return ret;
}
/*
两个正整数相乘
*/
BigInt BigInt::operator*(const BigInt &rhs)
{
BigInt ret;
string lvalues(values),rvalues(rhs.values);
//处理特殊情况
if(lvalues == "0" || rvalues == "0")
{
ret.values = "0";
ret.flag = true;
return ret;
}
unsigned int lsize, rsize;
lsize = lvalues.size();
rsize = rvalues.size();
string temp;
BigInt res,itemp;
//让lvalues的长度最长
if (lvalues < rvalues)
{
temp = lvalues;
lvalues = rvalues;
rvalues = temp;
lsize = lvalues.size();
rsize = rvalues.size();
}
//处理本质情况
int i, j, n1, n2, n3, t;
reverse(lvalues.begin(),lvalues.end());//颠倒字符串,方便从低位开始计算
reverse(rvalues.begin(),rvalues.end());
for (i = 0; i < rsize; i++) {
temp = "";
n1 = n2 = n3 = 0;
for (j = 0; j < i; j++)
{
temp = temp + "0";
}
n3 = rvalues[i] - '0'; //n3记录乘数的字面值
for (j = 0; j < lsize; j++) {
t = (n3*(lvalues[j] - '0') + n2);
n1 = t % 10;//n1记录当前位置的值
n2 = t / 10;//n2记录进位的值
temp = temp + char(n1 + '0');
}
if(n2)
{
temp = temp + char(n2 + '0');
}
reverse(temp.begin(), temp.end());
itemp.values = temp;
res = res + itemp; //直接就用上了刚刚重构的加法~~~
}
ret = res;
return ret;
}
/*
* 两个正整数相除
*/
BigInt BigInt::operator/(const BigInt &rhs)
{
BigInt ret;
string lvalues(values),rvalues(rhs.values);
string quotient;
//处理特殊情况
if(rvalues == "0")
{
ret.values = "error";//输出错误
ret.flag = true;
return ret;
}
if(lvalues == "0")
{
ret.values = "0";
ret.flag = true;
return ret;
}
if(compare(lvalues, rvalues) < 0)
{
ret.values = "0";
ret.flag = true;
return ret;
}
else if(compare(lvalues,rvalues) == 0)
{
ret.values = "1";
ret.flag = true;
return ret;
}
else
{
//处理本质情况
string temp;
unsigned int lsize,rsize;
lsize = lvalues.size();
rsize = rvalues.size();
int i;
if(rsize > 1) temp.append(lvalues,0,rsize-1); //如果除数的位数大于1,从被除数中取出除数个位数的数(从大到小)
for (int i = rsize - 1; i < lsize; i++) {
temp = temp + lvalues[i];//一个一个往上补
//试商
for (char c = '9'; c >= '0' ; c--)
{
BigInt t = (BigInt)rvalues * (BigInt)string(1,c);
BigInt s = (BigInt) temp - t;
if(s.flag == true)
{
temp = s.values;
quotient = quotient + c;
break;
}
}
}
}
//去除前导0
quotient.erase(0,quotient.find_first_not_of('0'));
ret.values = quotient;
ret.flag = true;
return ret;
}
int main()
{
BigInt a,b,result;
char op;
cin >> a >> op >> b;
switch(op)
{
case '+':result = a + b; break;
case '-':result = a - b; break;
case '*':result = a * b; break;
case '/':result = a / b; break;
default:break;
}
cout << result << endl;
return 0;
}
//这个答案也是抄写的别人的,抄下来感觉受益匪浅,写的真好!
//就是不知道自己啥时候能有写这种代码的水平啊!:(