智能合约语言 Solidity 教程系列5 - 数组介绍

想知道更多关于区块链技术知识,请百度【链客区块链技术问答社区】
链客,有问必答!!

Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,
若是你还不了解,建议你先看以太坊是什么
数组(Arrays)
数组能够声明时指定长度,也能够是动态变长。对storage存储的数组来讲,元素类型能够是任意的,类型能够是数组,映射类型,结构体等。但对于memory的数组来讲。若是做为public函数的参数,它不能是映射类型的数组,只能是支持ABI的类型。
一个元素类型为T,固定长度为k的数组,能够声明为T[k],而一个动态大小(变长)的数组则声明为T[]。
还能够声明一个多维数组,如声明一个类型为uint的数组长度为5的变长数组(5个元素都是变长数组),能够声明为uint[][5]。(注意,相比非区块链语言,多维数组的长度声明是反的。)
要访问第三个动态数组的第二个元素,使用x2。数组的序号是从0开始的,序号顺序与定义相反。
bytes和string是一种特殊的数组。bytes相似byte[],但在外部函数做为参数调用中,bytes会进行压缩打包。string相似bytes,但不提供长度和按序号的访问方式(目前)。
因此应该尽可能使用bytes而不是byte[]。
能够将字符串s经过bytes(s)转为一个bytes,能够经过bytes(s).length获取长度,bytes(s)[n]获取对应的UTF-8编码。经过下标访问获取到的不是对应字符,而是UTF-8编码,好比中文编码是多字节,变长的,因此下标访问到的只是其中的一个编码。
类型为数组的状态变量,能够标记为public,从而让Solidity建立一个访问器,若是要访问数组的某个元素,指定数字下标就行了。(稍后代码事例)
建立内存数组
可以使用new关键字建立一个memory的数组。与stroage数组不一样的是,你不能经过.length的长度来修改数组大小属性。咱们来看看下面的例子:
pragma solidity ^0.4.16;web

contract C {编程

function f(uint len) public pure {
    uint[] memory a = new uint[](7);
            
    //a.length = 100; // 错误
    bytes memory b = new bytes(len);
    // Here we have a.length == 7 and b.length == len
    a[6] = 8;
}

}
数组常量及内联数组
数组常量,是一个数组表达式(尚未赋值到变量)。下面是一个简单的例子:
pragma solidity ^0.4.16;数组

contract C {编程语言

function f() public pure {
    g([uint(1), 2, 3]);
}
function g(uint[3] _data) public pure {
    // ...
}

}
经过数组常量,建立的数组是memory的,同时仍是定长的。元素类型则是使用恰好能存储的元素的能用类型,好比[1, 2, 3],只须要uint8便可存储,它的类型是uint8[3] memory。
因为g()方法的参数须要的是uint(默认的uint表示的实际上是uint256),因此须要对第一个元素进行类型转换,使用uint(1)来进行这个转换。
还需注意的一点是,定长数组,不能与变长数组相互赋值,咱们来看下面的代码:
// 没法编译
pragma solidity ^0.4.0;ide

contract C {函数

function f() public {
    // The next line creates a type error because uint[3] memory
    // cannot be converted to uint[] memory.
    uint[] x = [uint(1), 3, 4];
}

}
已经计划在将来移除这样的限制。当前由于ABI传递数组还有些问题。
成员
length属性
数组有一个.length属性,表示当前的数组长度。storage的变长数组,能够经过给.length赋值调整数组长度。memory的变长数组不支持。
不能经过访问超出当前数组的长度的方式,来自动实现改变数组长度。memory数组虽然能够经过参数,灵活指定大小,但一旦建立,大小不可调整。
push方法
storage的变长数组和bytes都有一个push方法(string没有),用于附加新元素到数据末端,返回值为新的长度。
限制状况
当前在external函数中,不能使用多维数组。
另外,基于EVM的限制,不能经过外部函数返回动态的内容。
contract C {区块链

function f() returns (uint[]) { ... }
  }

在这个的例子中,若是经过web.js调用能返回数据,但从Solidity中调用不能返回数据。一种绕过这个问题的办法是使用一个很是大的静态数组。ui

pragma solidity ^0.4.16;编码

contract ArrayContract {code

uint[2**20] m_aLotOfIntegers;
// 这里不是两个动态数组的数组,而是一个动态数组里,每一个元素是长度为二的数组。
bool[2][] m_pairsOfFlags;
// newPairs 存在 memory里,由于是函数参数
function setAllFlagPairs(bool[2][] newPairs) public {
    m_pairsOfFlags = newPairs;
}

function setFlagPair(uint index, bool flagA, bool flagB) public {
    // 访问不存在的index会抛出异常
    m_pairsOfFlags[index][0] = flagA;
    m_pairsOfFlags[index][1] = flagB;
}

function changeFlagArraySize(uint newSize) public {
    // 若是新size更小, 移除的元素会被销毁
    m_pairsOfFlags.length = newSize;
}

function clear() public {
    // 销毁
    delete m_pairsOfFlags;
    delete m_aLotOfIntegers;
    // 同销毁同样的效果
    m_pairsOfFlags.length = 0;
}

bytes m_byteData;

function byteArrays(bytes data) public {
    // byte arrays ("bytes") are different as they are stored without padding,
    // but can be treated identical to "uint8[]"
    m_byteData = data;
    m_byteData.length += 7;
    m_byteData[3] = byte(8);
    delete m_byteData[2];
}

function addFlag(bool[2] flag) public returns (uint) {
    return m_pairsOfFlags.push(flag);
}

function createMemoryArray(uint size) public pure returns (bytes) {
    // Dynamic memory arrays are created using `new`:
    uint[2][] memory arrayOfPairs = new uint[2][](size);
    // Create a dynamic byte array:
    bytes memory b = new bytes(200);
    for (uint i = 0; i < b.length; i++)
        b[i] = byte(i);
    return b;
}

}

相关文章
相关标签/搜索