solidity中所支持的控制语句:
if else , for , while,do while,三目运算符。不支持switch语句。
直接通过案例学:
// for
contract For {
// 等差数列求和
function getSum(uint n, uint x) public returns(uint sum) {
for (uint index = 0; index < n; index+=x) {
sum += index;
if (index > 50) {
break;
}
}
}
}
contract While {
function getSum (uint n, uint x) view public returns(uint sum) {
uint i = 0;
while(i < n) {
sum += i;
i += x;
}
}
}
contract DoWhile {
function getSum(uint n, uint x) view public returns (uint sum) {
uint i = 0;
do {
sum += i;
i += x;
}while(i < n);
}
}
contract condition {
// 条件控制
function getT(uint x,uint y) view public returns(string) {
return mulmod(x, y, 2) == 0 ? "偶数":"奇数";
}
}
结果为:
合约for
合约While
合约do-while
货币单位:
wei:1wei
kwei:1000wei
gwei:10的6次方wei
mwei:10的9次方位
mircroether:10的12次方位
millierther(finnry):10的15次方位
ether:10的18次方位
案例:
// 货币单位
contract Money {
uint a = 1 ether;
uint b = 1 finney;
function compare() view public returns(bool) {
if (a == 1000 * b) {
return true;
}
return false;
}
}
结果为:
时间单位:
Seconds,minutes,hours,days,weeks,years。
案例:
// 时间单位
contract tm {
uint a = 1;
uint b = a * 1 seconds;
// seconds,minutes,hours,days,weeks, years 时间单位
function getTime() view public returns(uint) {
return b;
}
}
结果为:
内建的全局变量
在solidity中,内建的全局变量,可以在合约脚本的任何地方使用。
solidity本身呢也是一门函数型语言,函数可以做参数,变量,返回值。
函数属于值类型,支持多返回值。
调用方式:
内部调用:不copy数据,采用EVM跳转调用,所有能够直接使用和更改上下文的数据,所以在数据传递时非常的高效,
对合约内的函数,引入的库函数和从父合约中继承的函数都可以进行内部调用。
外部调用:使用外部调用得方式,进行调用,函数的所有参数都会先拷贝到内存中,使用external。
案例:
pragma solidity ^0.4.18;
contract Func {
uint x = 100;
uint y = 200;
function add() returns(uint) {
return x + y;
}
// 内部调用
function display() public view returns(uint) {
return add();
}
// 多返回值
mapping(addres => uint) balances;
function insert() public {
balances[0xDF5EB3d771DACaD2dA5E8Cb5ae4ccc16BF6D514E] = 100;
}
function get() public view returns(address, uint) {
return(0xDF5EB3d771DACaD2dA5E8Cb5ae4ccc16BF6D514E, balances[0xDF5EB3d771DACaD2dA5E8Cb5ae4ccc16BF6D514E]);
}
}
结果为:
函数定义类型:
view :只读,不改变合约的内部状态
注: 1.写入状态变量,2.触发事件 3.创建合约,4.使用自毁函数,5.发送以太币,6.调用任何一个没有被view或者pure的函数,7.底层的调用。
pure:不会修改合约的状态,也不会读合约的状态,基本上就是费用。所以用它读取与合约状态无关的数据。
1.不能读取状态变量,2.不能访问this.balance或者address.balance,3.不能访问block.msg的大多数成员(可以访问msg.sig,msg.data),4.调用任何一个没有被标记为pure的函数。
注:如果需要更改状态变量,就不要使用view不然会出现不会报错,但会出警告这样的。
1.回退函数:在每个合约中都有一个没名字的函数,该函数没有名字,没参数,没有返回值,这个就是回退函数。
作用:给合约发送eth时也会调用,需要注意的是,如果合约没有定义回调函数的话,接收ether会触发异常。
如果回调函数要接受ether,必须payable修改饰符。
2.自毁函数:自会函数可以摧毁当前合约,如果合约中含有以太币,则会将以太币转移到指定的地址。如果合约在被自毁之后还有人向合约中发送eth,则这些以太币就会消失,无法赎回。
3.常函数:不会修改区块链中的任何状态,没有强制的规定,但是会给警告。关键字为:constant
4.访问器:编译器为自动为所有的public状态变量创建访问器。访问函数具有外部可见性,如果通过内部方式访问,可以直接当成一个变量,但如果通过外部方式进行访问,比如通过this,那么必须通过函数的方式调用。注:只要使用this,它就变成了外部的一个东西。
// 访问器
contract C {
uint public c = 10;
function accessInternal() returns(uint) {
return c; // 内部方式访问
}
// 通过external(外部)的方式访问
function accessExternal() returns(uint) {
return this.c();
}
}
// 调用其它合约的访问器
contract D {
C c = new C(); // 实例化其它合约对象
function getData() returns(uint) {
return c.c();
}
}
结果为:
调用一个不存在的函数
pragma solidity ^0.4.18;
// 1. 实现回退函数
// 调用一个不存在的函数
contract ExecuteFallback {
// 新建一个事件,把调用的数据打印出来
event FallbackCalled(bytes data);
// fallback函数
function() {
// 调用回退事件
FallbackCalled(msg.data);
}
// existFunc事件
event ExistFuncCalled(bytes data, uint256 para);
// 写一个已经存在的函数
function existFunc(uint256 para) {
ExistFuncCalled(msg.data, para);
}
// 调用一个已经存在的函数
function callExistFunc() {
bytes4 funcIdentifier = bytes4(keccak256("existFunc(uint256)"));
this.call(funcIdentifier, uint256(1));
}
// 调用一个不存在的函数
function callNotExistFunc() {
bytes4 funcIdentifier = bytes4(keccak256("functionNotExist"));
this.call(funcIdentifier)
}
// 数据验证
function getExist() view returns(bytes32) {
return keccak256("existFunc(uint256)");
}
function getNotExist() view returns(bytes32) {
return keccak256("functionNotExist");
}
}
// 2. 实现自毁合约
contract SelfDestructionContract {
// 权限限制
modifier ownerRestricted {
require(owner == msg.sender);
_;
}
// 一般来说,能够销毁合约的人必须是合约的所有者
address public owner; // 所有人
string public someValue; // 值的设置
// 构造函数
function SelfDestructionContract() {
owner = msg.sender;
}
// 设置一个值
function setSomeValue(string value) {
someValue = value;
}
// 调用自毁函数
function destroyContract() ownerRestricted {
// 自毁函数
selfdestruct(owner);
}
}
函数的可见性与权限:
内部函数:internal:不能够在当前合约的上下文环境之外执行,只能在当前合约内进行调用,比如当前的代码块,内部的库函数,继承的合约中。在外部调用内部函数会报错。
// 内部函数
function internalFun() view internal returns(string){
return "internal func";
}
// 在当前合约内进行内部函数的调用
function callInternalFunc() view public returns(string) {
return internalFun();
}
外部函数:external:可以用从外部函数调用的参数,或者有外部函数调用返回,还可以通过其他合约进行调用,如果时this调用,那么都是在通过external的方式进行调用,不能在内部去调用一个外部函数。
公有函数:public:在哪都可以调用,public类型的状态变量或者函数,会自动创建一个访问器。
私有函数:private:只能在当前合约中进行访问,不能通过继承进行访问。
案例:
contract Chmod {
// 内部函数
function internalFun() view internal returns(string){
return "internal func";
}
// 在当前合约内进行内部函数的调用
function callInternalFunc() view public returns(string) {
return internalFun();
}
// 外部函数
function externalFunc() view external returns(string) {
return "external func";
}
// 在当前合约中进行外部函数的调用 会报错,只能通过this进行调用
function callExternalFunc() view public returns(string) {
return externalFunc();
}
// 私有函数
function privateFunc() view private returns(string) {
return "private func";
}
// 在当前合约内调用私有函数
function callPrivateFunc() view public returns(string) {
return privateFunc();
}
// 公有函数
function publicFunc() view public returns(string) {
return "public func";
}
// 在内部调用公有函数
function callPublicFunc() view public returns(string) {
return publicFunc();
}
}
// 外部调用 ,相当于在当前合约的上下文之外进行调用
contract externalCall {
Chmod ch = new Chmod(); //合约实例
// 外部调用内部函数
function callInternalFunc() view public returns(string) {
//return ch.internalFun(); 在外部调用内部函数直接报错
}
// 外部调用外部函数
function callExternalFunc() view public returns(string) {
return ch.externalFunc();
}
// 在外部调用私有函数
function callPrivateFunc() view public returns(string) {
// return ch.privateFunc(); 报错,私有函数在外部不可见
}
// 外部调用公有函数
function callPublicFunc() view public returns(string) {
return ch.publicFunc();
}
}
// 通过继承调用
contract child is Chmod {
// 在继承中调用内部函数
function callInternal() view public returns(string) {
return internalFun();
}
// 在继承中调用外部函数
function callExternalFunc() view public returns(string) {
return externalFunc(); // 还是需要通过this进行调用
}
// 在继承中调用私有函数
function callPrivateFunc() view public returns(string) {
return privateFunc();
}
// 在继承中调用公有函数
function callPublicFunc() view public returns(string) {
return publicFunc();
}
}