数组
数组的定义
一、定长数组
要注意定长数组的长度与内容要匹配
uint[3] memory a = [uint(1), 2, 3]; //这是正确定义
uint[3] memory a = [1, 2, 3]; //这样也不行
string[2] memory b = ["a"]; //错误的定义
二、变长数组
对于变长数组,在初始化分配空间前不可使用,可以通过new关键字来初始化一个数组。
memory:
uint[] memory memVar; //通过new初始化一个memory的变长数组 memVar = new uint[](2);
storage:
uint[] stateVar; stateVar = new uint[](2);
三、多维数组
我们要创建一个长度为5的uint数组,每个元素又是一个变长数组。将被声明为uint[][5](注意,定义方式对比大多数语言来说是反的,使用下标访问元素时与其它语言一致)。
pragma solidity ^0.4.6;
contract ArrayMD{
//一个变长的数组,里面的每个元素是一个长度为2的数组。
//定义方式与常规语言相反
bool[2][] flags;
function appendFlag() returns(uint length) {
//添加一个新元素到二维数组中
return flags.push([true,true]);
}
function getFlag(uint dynamicIndex, uint lengthTwoIndex) constant returns(bool flag) {
//访问数组,第一个为变长数组的序号,第二个为长度为2的数组序号
return flags[dynamicIndex][lengthTwoIndex];
}
}
属性和方法
1、length属性【表示数组长度】
storage属性的数组:
storage属性下的数组可以通过length查询数组长度以及调整数组长度。
看下面例子:
- 先定义一个storage属性的数组stateVar,并初始化长度为1
- 在autoExendArray函数中,stateVar[stateVar.length++]=a; 对数组对应长度的元素进行赋值,同时又增加数组长度,以便下一次赋值。
pragma solidity ^0.4.0; contract AutoExtendArray{ uint[] stateVar = new uint[](1); function autoExendArray(uint a) returns (uint){ //stateVar.length++语句会修改数组的长度加1 stateVar[stateVar.length++] = a; return stateVar[stateVar.length - 1]; } }
执行结果:
第一次:
第二次:
memory属性的数组:
- 对于memory的变长数组,不支持修改length属性,来调整数组大小。
- memory的变长数组虽然可以通过参数灵活指定大小,但一旦创建,大小不可调整。
2、 push方法(仅支持storage属性和bytes数组)
可以将一个新元素附加到数组末端,返回值为当前长度。
bytes和string
- bytes和string是一种特殊的数组。
- bytes类似byte[],但在外部函数作为参数调用中,会进行压缩打包,更省空间,所以应该尽量使用bytes。
- string类似bytes,但不提供长度和按序号的访问方式。
- 由于bytes与string,可以自由转换,你可以将string s通过bytes(s)转为一个bytes。但需要注意的是通过这种方式访问到的是UTF-8编码的码流,并不是独立的一个个字符
pragma solidity ^0.4.0;
contract bytes_string{
string s='a';
function bytes_2_string() returns(bytes) {
bytes a;
a=bytes(s);
return a;
}
}
3、EVM的限制
不能通过外部函数返回变长的数据
对于这样的问题的一种临时的解决办法,是使用一个非常大的定长数组。
不过现在的版本好像是已经解决了这个问题。