从零构建以太坊(Ethereum)智能合约到项目实战——学习笔记8

P35 、Solidity Types - 字符串(String Literals)

Solidity中的string字符串不像C语言一样以\0结束。

pragma solidity ^0.4.4;

contract StringLiterals{
    string _name;//状态变量
    
    //构造函数
    function StringLiterals(){
        _name = "this is a girl!";
    }
    
    function setName(string name){
        _name = name;
    }
    
    function name() constant returns(string){
        return _name;
    }
}

备注:string字符串不能通过length方法获取其长度。

 

P36 、1-固定大小字节数组(Fixed-size byte arrays) bytes1 ~P 、 bytes32

固定大小字节数组(Fixed-size byte arrays)

固定大小字节数组可以通过bytes1,bytes2,bytes3,....,bytes32来进行声明。PS:byte的别名就是byte1。

  • bytes1只能存储一个字节,也就是二进制8位的内容。
  • bytes2只能存储两个字节,也就是二进制16位的内容。
  • bytes3只能存储三个字节,也就是二进制24位的内容。
  • ........
  • bytes32只能存储三十二个字节,也就是二进制256位的内容。
pragma solidity ^0.4.4;

contract C{
    byte public a = 0x6c;
    bytes1 public b = 0x6c;
    bytes2 public c = 0x6c69;
    bytes3 public d = 0x6c6979;
    bytes4 public e = 0x6c697975;
}


P37 、2-Solidity Types - 固定大小字节数组(Fixed-size byte arrays) - 比较运算符

操作运算符

  • 比较运算符:<=、<、==、!=、>=、>
  • 位运算符:&、|、^(异或)、~(取反)、<<(左移)、>>(右移)
  • 索引访问:如果x是一个bytesI,那么可以通过X[k](0<k<I)获取对应索引的字节,PS:X[k]是只读,不可写。
pragma solidity ^0.4.4;

contract C{
    bytes1 b10 = 0x6c; //  l 
    bytes2 b11 = 0x69; //  i 
    
    //  <=、<、==、!=、>=、>
    
    function test1() constant returns(bool){
        return b10<=b11;
    }
    
    function test2() constant returns(bool){
        return b10<b11;
    }
    
    function test3() constant returns(bool){
        return b10==b11;
    }
    
    function test4() constant returns(bool){
        return b10!=b11;
    }
    
    function test5() constant returns(bool){
        return b10>=b11;
    }
    
    function test6() constant returns(bool){
        return b10>b11;
    }
    
}

 

 

P38 、3-Solidity Types - 固定大小字节数组(Fixed-size byte arrays) - 位操作符

操作运算符

  • 比较运算符:<=、<、==、!=、>=、>
  • 位运算符:&、|、^(异或)、~(取反)、<<(左移)、>>(右移)
  • 索引访问:如果x是一个bytesI,那么可以通过X[k](0<k<I)获取对应索引的字节,PS:X[k]是只读,不可写。
pragma solidity ^0.4.4;

contract C{
    bytes1 b10 = 0x6c; //  l 
    bytes1 b11 = 0x69; //  i 
    
    // &、|、^(异或)、~(取反)、<<(左移)、>>(右移)
    
    function test1() constant returns(bytes1){
        return b10 & b11;
        //0110 1100 -> 0x6c
        //0110 1001 -> 0x69
        //0110 1000 -> 0x68
    }
    
    function test2() constant returns(bytes1){
        return b10 | b11;
        //0110 1100 -> 0x6c
        //0110 1001 -> 0x69
        //0110 1101 -> 0x6d
    }
    
    function test3() constant returns(bytes1){
        return ~ b10;
        //0110 1100 -> 0x6c
        //1001 0011 -> 0x93
    }
    
    function test4() constant returns(bytes1){
        return b10 << 1;
        //0110 1100 -> 0x6c
        //1101 1000 -> 0xd8
    }
    
    function test5() constant returns(bytes1){
        return b10 >> 1;
        //0110 1100 -> 0x6c
        //0011 0110 -> 0x36
    }
    
}


P39 、4-Solidity Types - 固定大小字节数组(Fixed-size byte arrays) - 索引访问

操作运算符

  • 比较运算符:<=、<、==、!=、>=、>
  • 位运算符:&、|、^(异或)、~(取反)、<<(左移)、>>(右移)
  • 索引访问:如果x是一个bytesI,那么可以通过x[k](0<k<I)获取对应索引的字节,PS:x[k]是只读,不可写。
pragma solidity ^0.4.4;

contract C{
    bytes9 b9 = 0x6c6979756563687563;
    
    function test(uint index) constant returns(byte){
        return b9[index];
    }
}

 

 

P40 、5-Solidity Types - 固定大小字节数组(Fixed-size byte arrays) - length

操作运算符

  • 比较运算符:<=、<、==、!=、>=、>
  • 位运算符:&、|、^(异或)、~(取反)、<<(左移)、>>(右移)
  • 索引访问:如果x是一个bytesI,那么可以通过X[k](0<k<I)获取对应索引的字节,PS:X[k]是只读,不可写。

成员函数

  • .length返回字节的个数。(只读)
pragma solidity ^0.4.4;

contract C{
    bytes9 b9 = 0x6c6979756563687563;
    
    function test() constant returns(uint){
        return b9.length;
    }
}

 


P41 、6-Solidity Types - 固定大小字节数组(Fixed-size byte arrays) - 不可变深度理解

不可变深度解析

长度不可变

pragma solidity ^0.4.4;

contract C{
    bytes9 name = 0x6c6979756563687563;
    
    function setNameLength(uint length) {
        //报错
        name.length = length;
    }
}

 

内部字节不可修改

pragma solidity ^0.4.4;

contract C{
    bytes9 name = 0x6c6979756563687563;
    
    function setNameFirstByte(byte b) {
        //报错
        name[0] = b;
    }
}

 

总结:bytesI (1<= I <= 32)可以声明固定字节大小的字节数组变量,一旦声明,内部的字节和字节数组长度不可修改,当然可以通过索引读取(只读)对应索引的字节,或者通过length读取字节数组的字节数。

 

P42 、1-Solidity Types - 动态大小字节数组(Dynamically-sized byte array)

一、Dynamically-sized byte array

  • string是一个动态尺寸的utf-8编码字符串,它其实是一个特殊的可变字节数组,string是引用类型,而非值类型。
  • bytes动态字节数组、引用类型。

根据经验,在我们不确定字节数据大小的情况下,我们可以使用string或者bytes,而如果我们清楚知道或者能够将字节数控制在bytes1~bytes32,那么我们就使用bytes1~bytes32,这样的话能够降低存储成本。

 

P43 、2-Solidity Types - 动态大小字节数组(Dynamically-sized byte array) - string to bytes

二、常规字符串string转换为bytes

string字符串中没有提供length方法获取字符串长度,也没有提供方法修改某个索引的字节码,不过我们可以将string转换为bytes,再调用length方法获取字节长度,当然可以修改某个索引的字节码。

pragma solidity ^0.4.4;

contract C{
    bytes9 g = 0x6c697975656368756e;
    string 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;
    }
}


P44 、3-Solidity Types - 动态大小字节数组(Dynamically-sized byte array) - 特殊字符对应的字节数

三、汉字字符串或特殊字符的字符串转换为bytes

1、特殊字符

pragma solidity ^0.4.4;

contract C{
    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(字节)。


P45 、4-Solidity Types - 动态大小字节数组(Dynamically-sized byte array) - 汉字对应的字节数

2、中文字符串

pragma solidity ^0.4.4;

contract C{
    string public name = "黎跃春";
    
    function nameBytes() constant returns(bytes){
        return bytes(name);
    }
    
    function nameLength() constant returns(uint){
        return bytes(name).length;
    }
}

 

在上面的代码中,我们不难看出,黎跃春 转换为bytes以后的内容为0xe9bb8ee8b783e698a5,一共9个字节。也就是一个汉字需要通过3个字节来进行存储。


P46 、5-Solidity Types - 动态大小字节数组(Dynamically-sized byte array) - 创建bytes字节数组

pragma solidity ^0.4.4;

contract C{
    bytes public name = new bytes(1);
    
    function nameBytes() constant returns(bytes){
        return bytes(name);
    }
    
    function setNameLength(uint length){
        name.length = length;
    }
    
    function nameLength() constant returns(uint){
        return name.length;
    }
}

 

P47 、6-Solidity Types - 动态大小字节数组(Dynamically-sized byte array) - 可变字节数组和不可变字节数组深度对比

 

pragma solidity ^0.4.4;

contract C{
    bytes public name = new bytes(1);
    
    function nameBytes() constant returns(bytes){
        return bytes(name);
    }
    
    function setNameLength(uint length){
        name.length = length;
    }
    
    function nameLength() constant returns(uint){
        return name.length;
    }
    
    function setIndexByte(byte data, uint index){
        name[index] = data;
    }
    
    function clearBytes(uint len){
        name.length = len;
        //清空数组
        //name.length = 0;
        //或者delete清空
        //delete name;
    }
}

 


P48 、7-Solidity Types - 动态大小字节数组(Dynamically-sized byte array) - 可变字节数组中push方法的使用

pragma solidity ^0.4.4;

contract C{
    //0x6c697975656368756e
    //初始化一个两个字节空间的字节数组
    bytes public name = new bytes(2);

    function setNameLength(uint length){
        name.length = length;
    }
    
    function nameLength() constant returns(uint){
        return name.length;
    }
    
    function pushAByte(byte b){
        name.push(b);
    }
}

 

说明:当字节数组的长度只有2时,如果你通过push往里面添加一个字节,那么它的长度将变为3,当字节数组里面有3个字节,但是你通过length方法将其长度修改为2时,字节数组中最后一个字节将被从字节数组中移除。


P49 、8-Solidity Types - 动态大小字节数组(Dynamically-sized byte array) - 小结

对比分析:

  • 不可变字节数组

  我们之前的文章中提到过如果我们清楚我们存储的字节大小,那么我们可以通过bytes1,bytes2,bytes3,。。。,bytes32来声明字节数组变量,不过通过bytes1来声明的字节数组为不可变字节数组,字节不可修改,字节数组长度不可修改。

  • 可变字节数组

  我们可以通过bytes name = new bytes(length)-length为字节数组长度,来声明可变大小和修改字节内容的可变字节数组。

posted @ 2019-01-29 13:08  m0w3n  阅读(405)  评论(0编辑  收藏  举报