Solidity語言學習筆記————14、動態位元組陣列

FLy_鵬程萬里發表於2018-06-21

構建大小可變的動態陣列

陣列的大小即可以有固定的,也可以實現動態改變。在不同的場景使用不同的型別才是最正確的選擇。

String ——是一個動態尺寸的UTF-8編碼字串,它其實是一個特殊的可變的位元組陣列,string是引用型別,而非值型別。

bytes——動態位元組陣列,引用型別。

根據經驗,在我們不能夠確定位元組資料大小的情況下,我們可以使用string或者bytes,而如果我們清楚的知道或者能夠將位元組控制在byte1~byte32,那麼我們就使用byte1~byte32,這樣的話能夠降低儲存空間的消耗。

常規字串String轉換為bytes

String字串中沒有提供length方法獲取字串長度,也沒有提供方法修改某個索引的位元組碼,不過我們可以將String轉換為bytes,之後再呼叫length方法獲取位元組長度,當然可以修改某個索引的位元組碼。

原始碼如下:

pragma solidity ^0.4.4;
contract test {

    bytes9 public g = 0x6c697975656368756e;
    string public name = "liyuechun";
    function gByteLength() constant returns (uint) {
        return g.length;
    }

    function nameBytes() constant returns (bytes) {
        return bytes(name);
    }

    function nameLength() constant returns (uint) {
        return bytes(name).length;
    }

    function setNameFirstByteForL(bytes1 z) {
        // 0x4c => "L"
        bytes(name)[0] = z;
    }
}

測試效果:

說明

function nameBytes() constant returns (bytes) {
    return bytes(name);
}
namebytes這個函式的功能是將字串name轉換成bytes,並且返回的結果為0x6c697975656368756e即將字串轉換為對應的16進位制數。0x6c697975656368756e一共有9個位元組,也就是一個英文字母對應一個位元組。
function nameLength() constant returns (uint) {
    return bytes(name).length;
}

我們之前講過,string字串它並不提供length方法幫助我們返回字串長度,所以在namelength方法中,我們將name轉換為bytes,然後再呼叫length方法來返回位元組數,因為一個位元組對應一個英文字母,所以返回的位元組數量剛好等於這個字串的長度。

function setNameFirstByteForL(bytes1 z) {
    // 0x4c => "L"
    bytes(name)[0] = z;
}

如果我們想將name字串中的某個字母進行修改,那麼我們直接通過x[k]=z的形式進行修改即可。x是bytes型別的位元組陣列,k是索引,z是byte1型別的變數值。

setNameFirstByteForL方法中,我們就將Liyuechun中的首字母修改成L,我傳入的z的值為0x4c,即大寫的L。

漢字字串或特殊字元的字串轉換為bytes

特殊字元
pragma solidity ^0.4.4;

contract test {

    string public name = "a!+&520";
    function nameBytes() constant returns (bytes) {
        return bytes(name);
    }

    function nameLength() constant returns (uint) {
        return bytes(name).length;
    }

}


在這個案例中,我們宣告瞭一個name字串,值為a!+&520,根據nameBytes和namelength返回的結果中,我們不難看出不管是字母,數字還是特殊字元,每一個字母對應一個byte(位元組)。

中文字串
pragma solidity ^0.4.4;

contract test {
    string public name = "黎躍春";

    function nameBytes() constant returns (bytes) {
        return bytes(name);
    }
    function nameLength() constant returns (uint) {

        return bytes(name).length;
    }

}

在上面的程式碼中,我們不難看出,黎躍春轉換為bytes之後的內容為0xe9bb8ee8b783e698a5一共是9個位元組,也就是一個漢字,需要通過3個位元組來進行儲存。那麼問題來了,以後我們取字串時,字串中最好不要帶漢字,否則計算字串的長度的時候還需要特殊處理。

建立bytes位元組陣列

pragma solidity ^0.4.4;

contract test {
    bytes public name = new bytes(1);

    function setNameLength(uint length) {

        name.length = length;
    }
    function nameLength() constant returns (uint) {

        return name.length;
    }

}

Bytes可變陣列length和push兩個函式的使用例項

pragma solidity ^0.4.4;

contract test {

    // 0x6c697975656368756e
    // 初始化一個兩個位元組空間的位元組陣列
    bytes public name = new bytes(2);

    // 設定位元組陣列的長度
    function setNameLength(uint len) {

        name.length = len;
    }

    // 返回位元組陣列的長度
    function nameLength() constant returns (uint) {

        return name.length;
    }

    // 往位元組陣列中新增位元組
    function pushAByte(byte b) {

        name.push(b);
    }

}

說明:new bytes(2)的意思是新建一個長度為2的可變陣列。當位元組陣列的長度只有2時,如果你通過push往裡面新增了一個位元組,那麼他的長度就會變為3,當位元組陣列裡面有3個位元組,但是你通過length方法將其長度修改為2時,位元組陣列中最後一個位元組將被從位元組陣列中移除(如果將長度修改為0,那麼陣列將被清空)。

總結

對比分析:

不可變位元組陣列:可以用關鍵詞byte來進行宣告,但是陣列長度、陣列內容不可修改

可變位元組陣列:可以通過bytes name=new bytes(length)來宣告可變大小,並且可以修改位元組內容的可變陣列。



相關文章