06 Solidity中的枚举、映射、结构体、全局变量、元祖

2018年5月30日 作者 jacky

枚举

下面的代码是我对官方案例作了简单的修改而成。ActionChoices就是一个自定义的整型,当枚举数不够多时,它默认的类型为uint8,当枚举数足够多时,它会自动变成uint16,下面的GoLeft == 0,GoRight == 1, GoStraight == 2, SitStill == 3。在setGoStraight方法中,我们传入的参数的值可以是0 – 3当传入的值超出这个范围时,就会中断报错。

pragma solidity ^0.4.4;

contract test {
    enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
    ActionChoices _choice;
    ActionChoices constant defaultChoice = ActionChoices.GoStraight;

    function setGoStraight(ActionChoices choice) public {
        _choice = choice;
    }

    function getChoice() constant public returns (ActionChoices) {
        return _choice;
    }

    function getDefaultChoice() pure public returns (uint) {
        return uint(defaultChoice);
    }
}

语法

mapping(_KeyType => _ValueType)

字典/映射其实就是一个一对一键值存储关系。

举个例子:

{age: 28, height: 172, name: jacky}

这就是一个映射,满足_KeyType => _ValueType之间的映射关系,age对应一个28的值,height对应160,name对应jacky

PS:同一个映射中,可以有多个相同的值,但是键必须具备唯一性。

案例

pragma solidity ^0.4.4;

contract MappingExample {
    
    // 测试账号
    
    // 0xca35b7d915458ef540ade6068dfe2f44e8fa733c
    
    // 0x14723a09acff6d2a60dcdf7aa4aff308fddc160c
    
    // 0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db
    
    mapping(address => uint)  balances;

    function update(address a,uint newBalance) public {
        balances[a] = newBalance;
    }
    
    // {0xca35b7d915458ef540ade6068dfe2f44e8fa733c: 100,0x14723a09acff6d2a60dcdf7aa4aff308fddc160c: 200,0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db: 300 }
    
    function searchBalance(address a) constant public returns (uint) {
        
        return balances[a];
    }
}

结构体和字典综合案例

pragma solidity ^0.4.4;

contract CrowdFunding {
    // Defines a new type with two fields.
    struct Funder {
        address addr;
        uint amount;
    }

    struct Campaign {
        address beneficiary;
        uint fundingGoal;
        uint numFunders;
        uint amount;
        mapping (uint => Funder) funders;
    }

    uint numCampaigns;
    mapping (uint => Campaign) campaigns;

    function newCampaign(address beneficiary, uint goal) public returns (uint campaignID) {
        campaignID = numCampaigns++; // campaignID is return variable
        // Creates new struct and saves in storage. We leave out the mapping type.
        campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
    }

    function contribute(uint campaignID) public payable {
        Campaign storage c = campaigns[campaignID];
        // Creates a new temporary memory struct, initialised with the given values
        // and copies it over to storage.
        // Note that you can also use Funder(msg.sender, msg.value) to initialise.
        c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
        c.amount += msg.value;
    }

    function checkGoalReached(uint campaignID) public returns (bool reached) {
        Campaign storage c = campaigns[campaignID];
        if (c.amount < c.fundingGoal)
            return false;
        uint amount = c.amount;
        c.amount = 0;
        c.beneficiary.transfer(amount);
        return true;
    }
}

Ether Units

一个整数的后面可以跟一个单位,ether,finney,szabo或者wei。

他们的单位换算如下:

  • 1 ether = 1000 finney
  • 1 ether = 1000000 szabo
  • 1 ether = 10 ** 18 wei
pragma solidity ^0.4.4;

contract C {
    
    uint a = 1 ether;
    uint b = 10 ** 18 wei;
    uint c = 1000 finney;
    uint d = 1000000 szabo;
    
    function isTrueAEquleToB() view public returns (bool) {
        
        return a == b;
    }
    
    function isTrueAEquleToC() view public returns (bool) {
        
        return a == c;
    }
    
    function isTrueAEquleToD() view public returns (bool) {
        
        return a == d;
    }

}

Time Units

时间的单位有seconds, minutes, hours, days, weeks 和 years。换算如下:

  • 1 == 1 seconds
  • 1 minutes == 60 seconds
  • 1 hours == 60 minutes
  • 1 days == 24 hours
  • 1 weeks == 7 days
  • 1 years == 365 days
pragma solidity ^0.4.4;

contract C {
    
    // 1 == 1 seconds
    // 1 minutes == 60 seconds
    // 1 hours == 60 minutes
    // 1 days == 24 hours
    // 1 weeks == 7 days
    // 1 years == 365 days
    
    function test1() pure public returns (bool) {
        
        return 1 == 1 seconds;
    }
    
    function test2() pure public returns (bool) {
        
        return 1 minutes == 60 seconds;
    }
    
    function test3() pure public returns (bool) {
        
        return 1 hours == 60 minutes;
    }
    
    function test4() pure public returns (bool) {
        
        return 1 days == 24 hours;
    }
    
    function test5() pure public returns (bool) {
        
        return 1 weeks == 7 days;
    }
    
    function test6() pure public returns (bool) {
        
        return 1 years == 365 days;
    }
}

特殊的变量和函数和函数
有一些特殊的变量和函数存在于全局的命名空间以提供区块相关信息。

区块和交易属性

  • block.blockhash(uint blockNumber) returns (bytes32): 某个区块的区块链hash值
  • block.coinbase (address): 当前区块的挖矿地址
  • block.difficulty (uint): 当前区块的难度
  • block.gaslimit (uint): 当前区块的gaslimit
  • block.number (uint): 当前区块编号
  • block.timestamp (uint): 当前区块时间戳
  • msg.data (bytes): 参数
  • msg.gas (uint): 剩余的gas
  • msg.sender (address): 当前发送消息的地址
  • msg.sig (bytes4): 方法ID
  • msg.value (uint): 伴随消息附带的以太币数量
  • now (uint): 时间戳,等价于block.timestamp (uint)
  • tx.gasprice (uint): 交易的gas单价
  • tx.origin (address):交易发送地址

错误处理

  • assert(bool condition):不满足条件,将抛出异常

  • require(bool condition):不满足条件,将抛出异常

  • revert() 抛出异常

在Solidity 0.4.10版本之前,使用throw来处理异常。如下所示:

contract HasAnOwner {

    address owner;
    
    function useSuperPowers(){ 
        if (msg.sender != owner) { 
            throw; 
        }
    }
}

在Solidity 0.4.10版本之后,我们通常如下使用:

  • if(msg.sender != owner) { revert(); }
  • assert(msg.sender == owner);
  • require(msg.sender == owner);

元祖

1,元祖: 同时返回多个值,值的类型是相同的
2,mapping(字典) 是不能返回字典的,只能返回字典中的一个值

pragma solidity ^0.4.4;

contract C {
    
    uint[] data = [1,2,3,4,5];
    
    function f() constant returns (uint[]){
        return data;   
    }
    
}
pragma solidity ^0.4.4;

contract Somple {
    
    function arithmetics(uint _a , uint _b) constant returns (uint , uint){
        return (_a + _b , _a * _b);
    }
    
    
    /**
    如果返回名字是一样,可以不需要写return
    **/
    function arithmetics2(uint _a , uint _b) constant returns (uint value1, uint value2){
        value1 = (_a + _b); 
        value2 = (_a * _b);
    }
    
    function f() constant returns (uint , bool, uint ){
        return (7,true,2);
    }
    
    function g1() constant returns (uint,bool,uint) {
        var (x,b,y) = f();
        return (x,b,y);
    }
    
    function g2() constant returns (uint,uint) {
        var (x,b,y) = f();
        (x,y) = (y,x);
        return (x,y);
    }
}

参考:
solidity在线文档