结构体
特点:结构体也是solidity中的自定义数据,它包含基本类型与复杂类型。
注:在solidity中结构体类型不能作为返回值来进行返回,只能是返回其指定属性。
案例:
pragma solidity ^0.4.18;
contract structdemo{
struct Bank{
address addr;
uint balance;
Person p;
}
struct Person{
string name ;
uint8 age;
string sex;
}
Person p1 = Person({
name : "wek",
age : 18,
sex : "nan"
});
Bank bank = Bank({
addr : 0x8cC758f5a41bdF6Ab749944c737F86e6a4B4070B,
balance : 999999999,
p :p1
});
function getbank()view returns(address,uint,string,uint8,string){
return (bank.addr,bank.balance,bank.p.name,bank.p.age,bank.p.sex);
}
}
结果为:
另一种定义方法为:
function getbank()view returns(address,uint,string,uint8,string){
return (bank.addr,bank.balance,bank.p.name,bank.p.age,bank.p.sex);
}
Person p2 = Person("wek1",200,"nan");
function getperson()view returns(string,uint8,string){
return (p2.name,p2.age,p2.sex);
}
结果为:
数组
数组分为定长与不定长(变长),注:对于storage数组来说,元素类型可以为任意类型,但是在memory数组中,元素的类型与函数的可见性有关,因此,如果函数是外部可见的,那么函数的参数就不能是映射类型的数组。
function Wai( mapping[5]){},这样的就是错误的。
声明方式:
定长:array[5]
不定长:array[] 可以通过关键字new进行初始化,uint [] array= new uint[](10);不过这种方式其实是分配内存,就是memory类型的数组,所以它不能通过.length来修改其数组的长度。
如果状态变量类型是一个public的数组,那么solidity会自动创建一个访问器,就可以通过下标直接访问这个变量。
数组的字面量:是指表达式的方式声明一个数组,并作为一个数组变量的使用方式,通过这种方式只能声明一个memory类型的数组,其元素类型正好是指能存储元素的长度。
案例:
function g()view returns(uint8[3]){
return f([1,2,3]);
}
function f(uint8[3] a)view returns(uint8[3]){
return a ;
}
结果为:
数组的属性和方法:
数组拥有.length属性,可以获取其长度。对于定长数组来说,数组的长度不可更改。变长数组可以更改,其更改长度长于原数组的话会用0补,若小于原数组,则剪去多余下标的元素。
而且变长数组拥有push方法,可以利用这个方法添加新元素到数组末尾,其返回值是新的数组长度。
案例:
contract Array{
uint8[5] a = [1,2,3,4,5];
function getarray()view returns(uint8[5]){
return a;
}
function Updata(uint8 index, uint8 value){
a[index]=value;
}
}
结果为:
数组也可以获取其长度。
function getlength()view returns(uint){
return a.length;
}
不定长数组操作:
contract Barray{
uint8 [] a= [1,2,3,4,5];
function getlength()view returns(uint){
return a.length;
}
function pushlast(uint8 value)view returns(uint8[]){
a.push(value);
return a;
}
function updata(uint8 index,uint8 value)view returns(uint8[]){
a[index]=value;
return a;
}
}
结果为:
二维数组
数组元素一维数组一样,不一样的是二维数组的行列与其他大多数语言是相反的。
uint[3][5] x ,这里的x代表的是5行3列的一个二维数组。
uint[][5] y 这里y的代表的是一个5行没有列的数组,但每一行都是一个数组。
映射
字典,键值对的映射关系存储结构mapping[keytype =>keyvalue];
映射本身,动态数组,合约,结构体,枚举都不能够作为映射类型的键值。但映射的值可以是任意类型。
在solidity中,映射的长度是没有的,也没有键集合,值集合这样的概念。
在solidity中,mapping并不支持遍历,但是可以自己写一个。在后面我会将写出来的代码呈上。
案例:
contract map{
mapping(address=>uint8) balances;
function set(address addr, uint8 balance ){
balances[addr]=balance;
}
function get(address addr)view returns(uint8){
return balances[addr];
}
//并没有真正的删除addr的map,而是将其还原成初始化状态。
function del(address addr){
delete balances[addr];
}
}
结果为: 注:如果要查找的地址不存在则会返回0
类型转换
隐式转换:如果运算符两边支持要转换的类型,则编译器会自动转换。隐式转换时要注意防止数据丢失。任何无符号整数都可以转化为更大类型的值,比如说任何一个可以转换位uint160的类型都可以转换为address类型。
如果向高位转,没有达到的位值会自动进行补0。
显示转换:在不允许转换的条件下,但能确定转换后数据不会丢失,可以转换的条件下,进行强制转换。注意uint32高位转换位uint16时,会导致高位截断。
案例:
pragma solidity ^0.4.18;
contract YTrans {
uint8 a = 1;
uint16 b = 2;
// 低位转高位
function ltoh() view public returns(uint16) {
b = a ;
return b;
}
// 高位转低位
// 报错,不允许
// function htol() view public returns(uint8) {
// a = b;
// return b;
// }
// uint160->address
// 高位补0
uint160 d = 10000000000;
address to;
function utoa() view public returns(address) {
to = d;
return to;
}
}
结果为: