结构体概念
在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类。结构体可以被声明为变量、指针或数组等,用以实现较复杂的数据结构。结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问。
在C语言中,可以定义结构体类型,将多个相关的变量包装成为一个整体使用。在结构体中的变量,可以是相同、部分相同,或完全不同的数据类型。在C语言中,结构体不能包含函数。在面向对象的程序设计中,对象具有状态(属性)和行为,状态保存在成员变量中,行为通过成员方法(函数)来实现。C语言中的结构体只能描述一个对象的状态,不能描述一个对象的行为。在C++中,考虑到C语言到C++语言过渡的连续性,对结构体进行了扩展,C++的结构体可以包含函数,这样,C++的结构体也具有类的功能,与class不同的是,结构体包含的函数默认为public,而不是private。
声明
struct node{
int data1,data2;
bool vis;
double score;
char a[100];
};
struct结构体就相当于一个大箱子,里面什么也能放。但是一定要加分号(;)!
包括函数。
struct node{
int data1,data2;
bool vis;
double score;
char a[100];
void init(int x){data1=x;}
bool cmp(){return data1>data2;}
};
定义
可以采用node x
或下列方式。
struct node{
int data1,data2;
bool vis;
double score;
char a[100];
void init(int x){data1=x;}
bool cmp(){return data1>data2;}
}x;
赋值
直接x.data2=100;
即可。调用函数:
int main()
{
int a;
scanf("%d%d",&a,&x.data2);
x.init(a);
if(x.cmp()) puts("1");
else puts("0");
}
构造函数
构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们即构造函数的重载。
如果你没有增加构造函数,也没有修改默认构造函数,默认构造函数便可以省略,但如果你自己定义了构造函数,则默认构造函数必须写上。
也就是说你可以这样写:
struct num{
int len,a[100];
num(){len=0x7fffffff;memset(a,0x7f,sizeof(a));}
};
当你定义num A;
时,A里面的len和a都被设置为了最大值。
重载运算符
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
重载运算符有什么用呢?最常用的是高精度运算,以前我们经常用数组来写高精度,有了重载运算符和结构体后,就意味着你的main函数中只需要这样写:
Bignum A,B,C;
A.read();
B.read();
C=A+B;
C.print();
C=A*B;
C.print();
规则
重载是有规则的,首先,“重载运算符”是“重载”,而不是“定义”,所以你只能改变一个C++中已有的运算符,而不是定义一个本来没有的运算符,如果你真的想这样,请搜索define。C++重载运算符也只能在结构体(struct)中。
1.C++只能重载C++中已有的运算符;除了少数几个运算符不能重载外,全部可以重载,不能重载的操作符是类属关系运算符”.”、成员指针运算符“*”(当这个作乘号时是可以重载的)、作用域分辨符“::”和三目运算符“? :”。
2.重载运算符后的优先级和结合性都不会改变。
3.重载的运算符要与该运算本身的含义一致,不能导致混乱。 (当然你可以骗过编译器,但是别人看不懂你的代码)
注意:重载运算符时,其参数个数比实际上参与运算的个数少一个。因为该对象自身也将参与运算。
模板
重载类型(返回值的类型) operator /*这是一个重载运算符的关键字*/ 重载符号 (参数)
{
要执行的内容
return X;//返回一个值(void则不用返回,可写return;)
}
如:
bool operator + (node x){return data1+x.data1;}
赋值运算符重载
在主函数中我们肯定不能运用下面这种写法,但是非要实现,那怎么办呢?那就要重载运算符。
int a;
Bignum A;
A=a;
这种写法是对的,同种结构体可以互相赋值。
Bignum A,B;
A=B;
赋值重载代码框架:
struct Bignum{
void operator =(int x){//赋值没有返回值
//赋值的内容...
}
};
关系运算符重载
这里要重载的十分多:>,>=,<,<=,==…那么是不是要一一写呢?答案是不用的,实际上你只需要写出一个<重载,然后其他运算符都可以用逻辑运算和已经重载的<表示出。
例如判断>=X可以这样写:return !(*this<X);
就是不小于X的意思,可就是大于等于X。
关系运算符重载代码框架:
struct Bignum{
bool operator >(Bignum X){//关系的返回值只能是TRUE和FALSE
//判断的内容...
}
bool operator <=(Bignum &x){return !(x<*this);}//不>,反过来就是<=
};
算术运算符重载
这个就要一个一个写了,除了加减乘除模,你甚至可以写一个开方乘方,这是算法的事情,我们不说。相信经过前面的代码,大体实现大家已经明白。
算术运算符重载代码框架:
struct Bignum{
bool Bignum +(Bignum X){//关系就是Bignum
//内容...
}
};
输入输出
这个非常简单,成员函数void print()
和void read()
即可。
打包程序
#include<cstdio>
#include<iostream>
using namespace std;
#define LL long long
const LL maxn=10101;
struct Bigint{
LL a[maxn];
void Print(){//输出
for(LL i=a[0];i>=1;i--)printf("%lld",a[i]);
puts("");
}
void Init(string s){//赋值
memset(a,0,sizeof(a));
a[0]=s.size();
for(LL i=1;i<=a[0];i++)a[i]=s[a[0]-i]-'0';
while(a[0]>1 && a[a[0]]==0)a[0]--;
}
Bigint operator + (const Bigint & b)const{//高精加高精
Bigint c;memset(c.a,0,sizeof(c.a));
c.a[0]=max(a[0],b.a[0]);
for(LL i=1;i<=c.a[0];i++){
c.a[i]+=a[i]+b.a[i];
if(c.a[i]>9){
c.a[i+1]++;
c.a[i]-=10;
}
}
if(c.a[c.a[0]+1])c.a[0]++;
return c;
}
Bigint operator - (const Bigint & b)const{//高精减高精
Bigint c;memset(c.a,0,sizeof(c.a));
c.a[0]=max(a[0],b.a[0]);
for(LL i=1;i<=c.a[0];i++){
c.a[i]+=a[i]-b.a[i];
if(c.a[i]<0){
c.a[i+1]--;
c.a[i]+=10;
}
}
while(c.a[0]>1 && c.a[c.a[0]]==0)c.a[0]--;
return c;
}
Bigint operator * (const Bigint & b)const{//高精乘高精
Bigint c;memset(c.a,0,sizeof(c.a));
c.a[0]=a[0]+b.a[0]-1;
for(LL i=1;i<=a[0];i++){
for(LL j=1;j<=b.a[0];j++){
c.a[i+j-1]+=a[i]*b.a[j];
if(c.a[i+j-1]>9){
c.a[i+j]+=c.a[i+j-1]/10;
c.a[i+j-1]%=10;
}
}
}
if(c.a[c.a[0]+1])c.a[0]++;
while(c.a[0]>1 && c.a[c.a[0]]==0)c.a[0]--;
return c;
}
bool operator < (const Bigint & b)const{//重载小于号
if(a[0]<b.a[0])return true;
if(a[0]>b.a[0])return false;
for(LL i=a[0];i;i--){
if(a[i]>b.a[i])return false;
if(a[i]<b.a[i])return true;
}
return false;
}
bool operator == (const Bigint & b)const{//重载等于号
if(a[0]^b.a[0])return false;
for(LL i=a[0];i;i--)if(a[i]^b.a[i])return false;
return true;
}
bool operator > (const Bigint & b)const{//重载大于号
if(a[0]<b.a[0])return false;
if(a[0]>b.a[0])return true;
for(LL i=a[0];i;i--){
if(a[i]>b.a[i])return true;
if(a[i]<b.a[i])return false;
}
return false;
}
Bigint operator / (const LL & temp)const{//高精除低精
Bigint b; memset(b.a,0,sizeof(b.a));
b.a[0]=a[0];
LL x=0;
for(LL i=a[0];i>=1;i--){
b.a[i]=(x*10+a[i])/temp;
x=(x*10+a[i])%temp;
}
while(b.a[0]>1 && b.a[b.a[0]]==0)b.a[0]--;
return b;
}
Bigint operator * (const LL & temp)const{//高精乘低精
Bigint b;memset(b.a,0,sizeof(b.a));
b.a[0]=a[0];
for(LL i=1;i<=a[0];i++)b.a[i]=a[i]*temp;
for(LL i=1;i<=b.a[0];i++){
if(b.a[i]>9){
b.a[i+1]+=b.a[i]/10;
b.a[i]%=10;
if(i==b.a[0])b.a[0]++;
}
}
while(b.a[0]>1 && b.a[b.a[0]]==0)b.a[0]--;
return b;
}
LL operator % (const LL & temp)const{//高精模低精
LL date=0;
for(LL i=a[0];i>=1;i--){
date=date*10+a[i];
date%=temp;
}
return date;
}
};
Bigint numcpy(const Bigint p,LL pos){//从pos开始的地方复制p数组到q数组
Bigint a;memset(a.a,0,sizeof(a.a));
for(LL i=1;i<=p.a[0];i++)a.a[i+pos-1]=p.a[i];
a.a[0]=p.a[0]+pos-1;
return a;
}
Bigint operator / (Bigint & a,Bigint & b){//高精除高精
Bigint c;memset(c.a,0,sizeof(c.a));
if(a==b){c.Init("1");return c;}
if(a<b){c.Init("0");return c;}
c.a[0]=a.a[0]-b.a[0]+1;
for(LL i=c.a[0];i>0;i--){
Bigint temp=numcpy(b,i);
while(a>temp || a==temp){c.a[i]++;a=a-temp;}
}
while(c.a[0]>1 && c.a[c.a[0]]==0)c.a[0]--;
return c;
}
Bigint operator % (Bigint & a,Bigint & b){//高精模高精
Bigint c;memset(c.a,0,sizeof(c.a));
if(a==b){c.Init("0");return c;}
if(a<b)return a;
c.a[0]=a.a[0]-b.a[0]+1;
for(LL i=c.a[0];i>0;i--){
Bigint temp=numcpy(b,i);
while(a>temp || a==temp){
c.a[i]++;
a=a-temp;
}
}
return a;
}
Bigint qpow(Bigint a,int k){//高精快速幂
Bigint ans;ans.Init("1");
while(k){
if(k&1)ans=ans*a;
a=a*a;k>>=1;
}
return ans;
}
int main(){
//在这里写上你想使用的东西
//-----------大整数开方--------//
/*Bigint a,l,r,yi;
string s;cin>>s;
a.Init(s);
l.Init("0");r.Init(s);yi.Init("1");
while(l<r || l==r){
Bigint mid=l+r;mid=mid/2;
Bigint ans;ans=mid*mid;
if(ans==a){mid.Print();return;}
if(ans<a)l=mid+yi;
else r=mid-yi;
}
r.Print(); */
//----------高精乘高精-------------//
/*Bigint a,b;string s1,s2;cin>>s1>>s2;
a.Init(s1);b.Init(s2);a=a*b;a.Print(); */
//----------高精乘低精-----------//
/*Bigint a;string s;LL x;cin>>s>>x;
a.Init(s);a=a*x;a.Print();*/
//----------高精除高精-------------//
/*Bigint a,b;string s1,s2;cin>>s1>>s2;
a.Init(s1);b.Init(s2);a=a/b;a.Print(); */
//----------高精除低精-----------//
/*Bigint a;string s;LL x;cin>>s>>x;
a.Init(s); a=a/x;a.Print();*/
//----------高精模高精-------------//
/*Bigint a,b;string s1,s2;cin>>s1>>s2;
a.Init(s1);b.Init(s2);a=a%b;a.Print(); */
//----------高精模低精-----------//
/*Bigint a;string s;LL x;cin>>s>>x;
a.Init(s); LL ans=a%x;printf("%lld\n",ans);*/
//----------高精减高精----------//
/*Bigint a,b;string s1,s2;cin>>s1>>s2;
a.Init(s1);b.Init(s2);
if(a>b || a==b){a=a-b;a.Print();}
else {a=b-a;printf("-");a.Print();}*/
//----------高精加高精----------//
/*Bigint a,b;string s1,s2;;cin>>s1>>s2;
a.Init(s1);b.Init(s2);a=a+b;a.Print();*/
}