solidity 从入门到实战(一)
注意:本专栏主要来自于https://www.bilibili.com/video/BV1St411a7Pk?p=11&spm_id_from=pageDriver的学习笔记
编写第一个案例
//声明版本号
pragma solidity ^0.4.16;
//合约 有点类似于java中的class
contract HelloWorld{
//合约属性变量string myName = "HelloWorld";//合约中方法 注意语法顺序 其中此处view 代表方法只读 不会消耗gasfunction getName() public view returns(string){
return myName;}//可以修改属性变量的值 消耗gasfunction changeName(string _newName) public{
myName = _newName;}// pure:不能读取也不能改变状态变量function pureName(string _name) public pure returns(string){
return _name;}}
用constant、view、pure修饰function分别表示:
- constant:只能读取不可改变状态变量(就是contract中定义的变量)
- view:只能读取不可改变状态变量,和constant一样
- pure:不能读取也不能改变状态变量
想要详细了解他们的区别,请点击: https://www.jianshu.com/p/5f1bc0d39d79
solidity 语法介绍
注意:由于以下内容都是一些基本的语言特性,相信有编程基础的同学都可以看懂,因此,关于它的语法代码可以运行一下,看看效果,这里就不做过多的解释。
真假与或非
pragma solidity ^0.4.16;contract BoolTest{
bool a;int c = 100;int d = 200;function getBoolDefault() returns(bool){
return a;}function getBoolean() returns(bool){
return !a;}function judge() returns(bool){
return c==d;}function logicAnd() returns(bool){
return c==d && true;}function logicOr() returns(bool){
return c==d || true;}function logicNot() returns(bool){
return c!=d && true;}}
整型与算术运算
在solidity中,基本的整型有
int(有符号整型,有正有负)
和uint(无符号整型,无负数)
。并且他们以8位为区间,int
支持int8
,int16
,int24
至int256
,uint
同理。int默认为int256,uint默认为uint256
基本算术运算
pragma solidity ^0.4.16;contract Math{
//加function add(uint a,uint b) public returns(uint){
return a+b;}//减function minus(uint a,uint b) public returns(uint){
return a-b;}//乘function multiply(uint a,uint b) public returns(uint){
return a*b;}//除function divide(uint a,uint b) public returns(uint){
return a/b;}//取余function mod(uint a,uint b) public returns(uint){
return a%b;}//幂运算function square(uint a,uint b) public returns(uint){
return a**b;}
}
位运算
solidity支持的位运算有以下几种
位与&
,位或|
,位非~
,位异或^
,左移>>
,右移<<
pragma solidity ^0.4.16;contract Math{
uint8 a = 3;uint8 b = 4;function bitwiseAnd() public returns(uint8){
return a&b;}function bitwiseOr() public returns(uint8){
return a|b;}function tilde() public returns(uint8){
return ~a;}function caret() public returns(uint8){
return a^b;}function leftShift() public returns(uint8){
return a<<1;}function rightShift() public returns(uint8){
return a>>1;}
}
复合运算
++和-- 只需要记住
谁在前,结果输出谁(加号在前,结果加一;数字在前,结果输出数字本身);而变量本身等于运算后的值
。
pragma solidity ^0.4.16;contract Math{
//输出afunction add2(uint a) public returns(uint){
return a++;}//输出a+1function add3(uint a) public returns(uint){
return ++a;}//输出afunction minus2(uint a) public returns(uint){
return a--;}//输出a-1function minus3(uint a) public returns(uint){
return --a;}
}
整型溢出及异常处理
我们先看一下以下代码
pragma solidity ^0.4.16;contract Math{
function flow() view public returns(uint8){
uint8 mm = 255;mm++;return mm;}function flow2() view public returns(uint256){
uint8 mm = 255;mm++;return mm;}function flow3() view public returns(uint){
uint mm = 255;mm++;return mm;}
}
通过运行,我们会发现flow=0,flow2=0, flow3=256
,出现这个原因就是因为那就是进位溢出导致。
我们再来看看下面这段代码
pragma solidity ^0.4.16;contract Math{
function flowMinus() view returns(uint8){
uint8 nn = 0;nn--;return nn;}function flowMinus3() view returns(uint8){
uint8 nn = 0;return nn--;}
}
上述的复合减运算答案分别是255
和0
,你猜对了吗?
要避免的异常
例如:除数不能为0
pragma solidity ^0.4.16;contract Math{
function errorTest() view returns(int){
int a = 2;int b = 3;return a/b;}function errorTest2() view returns(int){
int a = 2;int b = 0;return a/b;}}
数组
固定长度字节数组
关键字有:bytes1,bytes2mbytes3,…,bytes32(以步长1递增)。byte代表bytes1。
pragma solidity ^0.4.16;contract ByteArray{
bytes1 public num1 = 0x7a;bytes2 public num2 = 0x7a68;bytes12 public num3 = 0x7a68656e676a69616e78756e;
}
固定长度字节数组对于数值来说,有点等同于我们的uint。一个字节等于8位。即bytes1 有点等同于uint8,至少在位数上是相等的。
**
注意:上面的例子,我们同时引入了一个public
修饰合约成员变量的范例,在solidity中,直接用public声明成员变量,编译部署后,会为我们生成一个默认的get方法,让我们可以直接调用这个成员属性。
**
动态长度字节数组
pragma solidity ^0.4.16;contract DynamicByteArray{
bytes public name = new bytes(2);function initName(){
name[0] = 0x7a;name[1] = 0x68;}function getLength() view returns(uint){
return name.length;}function changeName(){
name[0] = 0x88;}function changeLength(){
name.length = 5;}
}
依次执行
getLength
,initName
,name
,changName
,name
,changeLength
,getLength
看看结果
此外,我们的动态数组,还提供了一个push
方法,可以在我们自己数组的末尾继续添加我们的字节元素。
function pushTest(){
name.push(0x99);
}
字符串
在上节我们学习了动态字节数组,而我们的字符串,可不可以按照动态字节的数组去获取他的长度和其中的元素呢?
pragma solidity ^0.4.16;contract DynamicString{
string name = "tongxuejava";function getLength() returns(uint){
// return name.length; 不能够直接的获取string的长度return bytes(name).length;//通过bytes强转的转换}function getPartName() returns(bytes1){
return bytes(name)[0];}function changeName() {
// return name[0];不能够直接通过下标的方式获取string里面的内容bytes(name)[0] = 'T';}
}
通过实验,我们发现要想获取字符串中的元素,得通过
bytes()
进行强制转换。
固定长度字节数组转化
pragma solidity ^0.4.16;contract DynamicString{
bytes12 name = 0x7a68656e676a69616e78756e;function changeBytes1() view returns(bytes1){
return bytes1(name);}function changeByte2() view returns(bytes2){
return bytes2(name);}function changeByte3() view returns(bytes16){
return bytes16(name);}
}
通过运行,我们可以发现规律:
转小从头截取,转大末尾补零
。
固定长度字节数组转动态字节数组
pragma solidity ^0.4.16;contract DynamicString{
bytes12 name = 0x7a68656e676a69616e78756e;function fixBytesToDynamicBytes() view returns(bytes){
//return bytes(name); 直接转换为动态字节数组是不行的bytes memory newName = new bytes(name.length);//使用一个for循环来挨个字节进行转换for(uint i= 0;i < name.length;i++){
//注意uint 无符号整型newName[i] = name[i];}return newName;}
}
动态长度字节数组转为string
(bytes===>string)
pragma solidity ^0.4.16;contract Bytes2String{
bytes name = new bytes(2);function init(){
name[0] = 0x7a;name[1] = 0x68;}function bytesToString() view returns(string){
return string(name);}
}
固定长度字节数组转string
我们上面都知道了动态长度数组可以强制转换为string,那么固定长度数组可不可以强制转为string呢?
pragma solidity ^0.4.16;contract Bytes32ToString{
bytes2 name = 0x7a68;function bytes32ChangeString() returns(string){
return string(name); }}
通过编写以上合约,会发现编译出错,那么我们该如何转换呢?
从上面的学习中,我们知道。固定长度字节数组可以转为动态字节数组,而动态字节数组可以转为string。所以,这就是我们转换的思路。
pragma solidity ^0.4.16;contract Bytes32ToString{
function byts32ToString(bytes32 inputName) view returns(string){
bytes memory newName = new bytes(inputName.length);for(uint i = 0;i<newName.length;i++){
newName[i] = inputName[i];}return string(newName);}}
接下来,我们将以上内容做一个总结:
- 动态长度字节数组
- bytes的初始化–new bytes
- 获取bytes的长度和内容
- 修改长度和内容
- string
- 不能够直接获取长度和内容
- 需要转换为bytes获取长度和内容
- 特殊字符的长度的内容和获取
- 中文字符占用3个字节
- 固定长度字节数组之间转换
- 转小从头截取,转大末尾补零
- 固定长度转可变长度数组
- 利用new bytes(),然后循环转换。