羅韭菜的solidity學(xué)習(xí)(七)字節(jié)數(shù)組

可變長(zhǎng)度的字節(jié)數(shù)組

1.string

  • 字符串可以通過(guò)" "或者' '來(lái)表示字符串的值,solidity中的string不像c語(yǔ)言一樣以\0結(jié)束。
  • 它是可變長(zhǎng)度的字節(jié)數(shù)組,為引用類型
  • string字符串不能通過(guò)length方法取其長(zhǎng)度

2.byte

  • 動(dòng)態(tài)字節(jié)數(shù)組,引用類型

3.string to byte
string字符串中沒(méi)有提供length方法獲取字符串長(zhǎng)度,也沒(méi)有提供方法修改某個(gè)索引的字節(jié)碼,不過(guò)我們可以將string轉(zhuǎn)換為bytes,再調(diào)用length方法獲取字節(jié)長(zhǎng)度,當(dāng)然可以修改某個(gè)索引的字節(jié)碼。

pragma solidity ^0.4.4;

contract C {
    
    bytes9 public g = 0x6c697975656368756e;
    
    string public name = "melodyluo";
    
    function gByteLength() constant returns (uint) {
        
        return g.length;
    }
    
// 轉(zhuǎn)換string 到 bytes, 返回字節(jié)如g的內(nèi)容,一共9字節(jié),
// 也就是一個(gè)英文字母對(duì)應(yīng)一個(gè)字節(jié)
function nameBytes() constant returns (bytes) {
        
        return bytes(name);
    }
    // 通過(guò)轉(zhuǎn)換string to byte來(lái)調(diào)用length
    function nameLength() constant returns (uint) {
        
        return bytes(name).length;
    }
    
    function setNameFirstByteForL(bytes1 z) {
        
        // 0x4c => "L"
        bytes(name)[0] = z;
    }
}

4.漢字對(duì)應(yīng)的字節(jié)數(shù)

  • 1個(gè)漢字對(duì)應(yīng)3個(gè)字節(jié)
  • 1個(gè)英文字母、數(shù)字、特殊符號(hào) 對(duì)應(yīng)1個(gè)字節(jié)
pragma solidity ^0.4.4;

contract C {
    
    
    string public name = "羅雪";
    

    function nameBytes() constant returns (bytes) {
        
        return bytes(name);//0x e7 bd 97 e9 9b aa 
        // 1 chinese word equals to 3 bytes
    }
    
    function nameLength() constant returns (uint) {
        
        return bytes(name).length;
    }
    
}
  • so不要混用字母、漢字之類的

5.創(chuàng)建bytes字節(jié)數(shù)組

  • new bytes(想要的字節(jié)長(zhǎng)度)
  • 長(zhǎng)度可變, length
  • 內(nèi)容可變, name[index] = data
  • 可以通過(guò)讓length=0來(lái)清空bytes數(shù)組,也可以直接delete;
pragma solidity ^0.4.4;

contract C {
    
    
    bytes public name = new bytes(1);
    
    
    function setNameLength(uint length) {
        
        name.length = length;
    }
    
    function nameLength() constant returns (uint) {
        
        return name.length;
    }
    
    function setIndextyte(byte data, uint indxe){
        name[indxe] = data;
    }
    
    function clearBBytes(uint len){
        delete name;
    }
    
}

6.push

  • 在字節(jié)數(shù)組的最后插入("0xbb")
pragma solidity ^0.4.4;

contract C {
    
    // 0x6c697975656368756e
    // 初始化一個(gè)兩個(gè)字節(jié)空間的字節(jié)數(shù)組
    bytes public name = new bytes(2);
    
    // 設(shè)置字節(jié)數(shù)組的長(zhǎng)度
    function setNameLength(uint len) {
        
        name.length = len;
    }
    
    // 返回字節(jié)數(shù)組的長(zhǎng)度
    function nameLength() constant returns (uint) {
        
        return name.length;
    }
    
    // 往字節(jié)數(shù)組中添加字節(jié)
    function pushAByte(byte b) {
        
        name.push(b);
    }
    
}

-說(shuō)明:當(dāng)字節(jié)數(shù)組的長(zhǎng)度只有2時(shí),如果你通過(guò)push往里面添加了一個(gè)字節(jié),那么它的長(zhǎng)度將變?yōu)?,當(dāng)字節(jié)數(shù)組里面有3個(gè)字節(jié),但是你通過(guò)length方法將其長(zhǎng)度修改為2時(shí),字節(jié)數(shù)組中最后一個(gè)字節(jié)將被從字節(jié)數(shù)組中移除


固定長(zhǎng)度的字節(jié)數(shù)組(byte1-byte32)

固定大小字節(jié)數(shù)組可以通過(guò) bytes1, bytes2, bytes3, …, bytes32來(lái)進(jìn)行聲明。PS:byte的別名就是 byte1。

bytes1只能存儲(chǔ)一個(gè)字節(jié),也就是二進(jìn)制8位的內(nèi)容。
bytes2只能存儲(chǔ)兩個(gè)字節(jié),也就是二進(jìn)制16位的內(nèi)容。
bytes3只能存儲(chǔ)三個(gè)字節(jié),也就是二進(jìn)制24位的內(nèi)容。
……
bytes32能存儲(chǔ)三十二個(gè)字節(jié),也就是二進(jìn)制32 * 8 = 256 位的內(nèi)容。

  • 根據(jù)經(jīng)驗(yàn),在我們不確定字節(jié)數(shù)據(jù)大小的情況下,我們可以使用string或者bytes,而如果我們清楚的知道或者能夠?qū)⒆止?jié)書控制在bytes1 ~ bytes32,那么我們就使用bytes1 ~ bytes32,這樣的話能夠降低存儲(chǔ)成本。

運(yùn)算

  • 比較運(yùn)算符:<=, <, ==, !=, >=, >
  • 位操作符:&, |, ^(異或), ~ (取反), << (左移), >> (右移)
  • 注意左移與右移,如下
pragma solidity ^0.4.4;

 contract test{
 bytes1 b10 = 0x6c;
 bytes1 b11 = 0x69;
 
 function leftshift1() constant returns(bytes1) {
     return b10 << 1;
     // 0110 1100 -> 0x6c
     // 1101 1000 -> 0xd8
 }
 
  function fightshift1() constant returns(bytes1) {
     return b10 >> 1;
     // 0110 1100 -> 0x6c
     // 0011 0110 -> 0x36
 }
 
 }
 
  • 索引訪問(wèn):如果x是一個(gè)bytes I,那么可以通過(guò)x[k](0 < k < I)獲取對(duì)應(yīng)索引的字節(jié),PS:x[k]是只讀,不可寫。
pragma solidity ^0.4.4;

contract c{
    bytes9 b9 = 0x6c697975656368756e;
    function readIndex5Byte() constant returns(byte){
        return b9[5];
    }
}

成員函數(shù)

length

  • 返回字節(jié)的個(gè)數(shù)
  • 只可讀不可寫
pragma solidity ^0.4.4;

contract C {
    
    bytes9 public g = 0x6c697975656368756e;
    
    function gByteLength() constant returns (uint) {
        
        return g.length;
    }
    
}
image.png

固定大小深度理解

  • 存儲(chǔ)的字節(jié)數(shù)不可修改(不能通過(guò)length修改)
  • 內(nèi)部字節(jié)不可修改
pragma solidity ^0.4.4;

contract C {
    
    
    bytes9  name = 0x6c697975656368756e;
    
    function setNameFirstByte(byte b) {
        
        name[0] = b;
    }
    
}
image.png

總結(jié)

bytesI(1 <= I <= 32)可以聲明固定字節(jié)大小的字節(jié)數(shù)組變量,一旦聲明,內(nèi)部的字節(jié)和字節(jié)數(shù)組長(zhǎng)度不可修改,當(dāng)然可以通過(guò)索引讀取(只讀)對(duì)應(yīng)索引的字節(jié),或者通過(guò)length讀取字節(jié)數(shù)組的字節(jié)數(shù)。


不可變字節(jié)數(shù)組
我們之前的文章中提到過(guò)如果我們清楚我們存儲(chǔ)的字節(jié)大小,那么我們可以通過(guò)bytes1,bytes2,bytes3,bytes4,……,bytes32來(lái)聲明字節(jié)數(shù)組變量,不過(guò)通過(guò)bytesI來(lái)聲明的字節(jié)數(shù)組為不可變字節(jié)數(shù)組,字節(jié)不可修改,字節(jié)數(shù)組長(zhǎng)度不可修改。

可變字節(jié)數(shù)組
我們可以通過(guò)bytes name = new bytes(length) - length為字節(jié)數(shù)組長(zhǎng)度,來(lái)聲明可變大小和可修改字節(jié)內(nèi)容的可變字節(jié)數(shù)組。


固定與可變字節(jié)數(shù)組之間的轉(zhuǎn)換

1.固定字節(jié)數(shù)組之間的轉(zhuǎn)換

  • 賦值是在最后,如
pragma solidity ^0.4.4;

contract C {
    bytes10 public b1 = 0x6c;
    
    function b_length() constant returns(uint){
        return b1.length;
    }
}
image.png
  • byte9 -> byte2 的轉(zhuǎn)換, 低位截?cái)?,后面截?/li>
  • byte9 -> byte12 的轉(zhuǎn)換,低位補(bǔ)齊,后面補(bǔ)零


    image.png

2.固定轉(zhuǎn)可變

  • 不能直接強(qiáng)轉(zhuǎn)成動(dòng)態(tài)數(shù)組
  • 正確姿勢(shì)如下
pragma solidity ^0.4.4;

contract C {
    
   bytes9 name9 = 0x6c697975656368756e;
   
   function transfer(bytes9) constant returns(bytes) {
       bytes memory names = new bytes(name9.length);
       for (uint i =0;i<name9.length;i++){
           names[i] = name9[i];
       }
       return names;
   }
    
}

3.固定不能直接轉(zhuǎn)string
需要先固定轉(zhuǎn)動(dòng)態(tài),動(dòng)態(tài)轉(zhuǎn)string
但是這種方法會(huì)有問(wèn)題,如果將一個(gè)byte32(實(shí)際內(nèi)容為9個(gè)字節(jié))轉(zhuǎn)string,string長(zhǎng)度也是32,會(huì)有很多00000。這樣不好,標(biāo)準(zhǔn)方法見(jiàn)5

pragma solidity ^0.4.4;

contract C {
    
   bytes9 name9 = 0x6c697975656368756e;
 
   function bytes9transfertostring(byte9 name9) constant returns(string){
       bytes memory names = new bytes(name9.length);
       
       for (uint i =0; i<name9.length; i++){
           names[i]=name9[i];
       }
       return string(names);
   }
}

4.動(dòng)態(tài)字節(jié)轉(zhuǎn)string

  • 如果有現(xiàn)成的動(dòng)態(tài)字節(jié)數(shù)組如names,直接強(qiáng)轉(zhuǎn)
pragma solidity ^0.4.4;

contract C {
    
   bytes9 name9 = 0x6c697975656368756e;
   
   bytes names = new bytes(2);
   
   function C(){
       names[0]=0x6c;
       names[1]=0x69;
   }
   
   function transfer() constant returns(string){
       return string(names);
   }
}

5.標(biāo)準(zhǔn)的固定字節(jié)轉(zhuǎn)string方法
注意當(dāng)要改變狀態(tài)變量時(shí)不能用constant

pragma solidity ^0.4.4;

contract C {
    
    function bytes32ToString(bytes32 x) constant returns (string) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

    function bytes32ArrayToString(bytes32[] data) constant returns (string) {
        bytes memory bytesString = new bytes(data.length * 32);
        uint urlLength;
        for (uint i = 0; i< data.length; i++) {
            for (uint j = 0; j < 32; j++) {
                byte char = byte(bytes32(uint(data[i]) * 2 ** (8 * j)));
                if (char != 0) {
                    bytesString[urlLength] = char;
                    urlLength += 1;
                }
            }
        }
        bytes memory bytesStringTrimmed = new bytes(urlLength);
        for (i = 0; i < urlLength; i++) {
            bytesStringTrimmed[i] = bytesString[i];
        }
        return string(bytesStringTrimmed);
    }    
}
  • bytes32(uint(0x6c) * 2 ** (8 * 31));左移31位
    bytes32(uint(0x6c) * 2 ** (8 * 1)); 左移1位
  • 通過(guò)byte(bytes32(uint(x) * 2 ** (8 * j)))獲取到的始終是第0個(gè)字節(jié)。

string本身是一個(gè)特殊的動(dòng)態(tài)字節(jié)數(shù)組,所以它只能和bytes之間進(jìn)行轉(zhuǎn)換,不能和固定大小字節(jié)數(shù)組進(jìn)行直接轉(zhuǎn)換,如果是固定字節(jié)大小數(shù)組,需要將其轉(zhuǎn)換為動(dòng)態(tài)字節(jié)大小數(shù)組才能進(jìn)行轉(zhuǎn)換。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容