智能合約語言 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;
}

}

相關文章
相關標籤/搜索