Solidity学习(二)

那年仲夏 提交于 2021-01-12 12:12:50

一、string如何存储中文字符
二、固长数组
三、动态数组
四、二维数组
五、动态二维数组



一、string如何存储中文字符

先看一段代码:

pragma solidity >=0.4.22 <0.6.0;

contract Test {
    string name = "张三";
    
    function getLength() public view returns(uint256){
        return bytes(name).length;
    }
}
  1. 我们知道,普通字符在占据的内存是一个字节,那么像中文这种特殊字符应该怎么存储呢?我们执行上面的代码:
    在这里插入图片描述
  • 可以看到,一个中文字符是3个字节,总共是6个。
  • 事实上,在string中,特殊字符是用UTF-8存储的。
  • 关于UTF-8:UTF-8介绍
  1. 介绍两个关键字:

memory:临时变量,定义在函数内的变量默认为memory,一些版本的编译器要求定义在函数内的临时变量必须加上memory关键字。

storage:永久写入区块链的变量,就是定义在函数之外的状态变量。

  1. 把字节数组转化为动态字节数组,代码:
pragma solidity ^0.7.0;

contract Test {
    bytes6 name = 0x112233445566;
    
    function toNe() view public returns(bytes memory) {
        bytes memory newName = new bytes(name.length);
        for(uint i = 0;i < name.length;i++){
            newName[i] = name[i];
        }
        return newName;
    }
}
  • 有编程基础的人应该不难看出代码逻辑,这里直接给出结果:
    在这里插入图片描述
  1. 动态字节数组转字符串可以通过强制转换实现,但是普通的字节数组想要转字符串就比较麻烦了,修改以上代码:
pragma solidity ^0.7.0;

contract Test {
    bytes6 name = 0x112233445566;
    bytes2 name2 = 0x7a68;
    
    function toNe() view public returns(bytes memory) {
        bytes memory newName = new bytes(name.length);
        for(uint i = 0;i < name.length;i++){
            newName[i] = name[i];
        }
        return newName;
    }
    
    function BytestoString() view public returns(string memory){
        bytes memory newName = new bytes(name2.length);
        for(uint i = 0;i < name2.length;i++){
            newName[i] = name2[i];
        }
        return string(newName);
    }
}
  • 第二个函数的目的是吧name2字节数组类型转化为string类型,有编程基础的看这个代码逻辑也不难,在这里不过于解释,运行结果:
    在这里插入图片描述
  1. 但是这也引发了一个问题,当bytes的空间大于我输入的数据的时候,比如bytes6 = 0x112233,那么后面三位就会自动赋值为0,若这样的数据也被转换成string那就很浪费空间。解决方式就是先把bytes类型转换为动态bytes,再强转为string。

二、固长数组

  • 关于数组这个概念大家肯定都不陌生,先看代码:
pragma solidity ^0.4.0;

contract TestArray {
   
   uint[5] arr;
   
   function getArrayContent() view public returns(uint[5]){
       return arr;
   }
}
  • 运行getArrayContent()函数,得到结果:
    在这里插入图片描述
  • 说明uint数组在默认情况下,初始值为0
  1. 通过方法来修改数组中的值,在合约中加入以下代码:
 function Init() public {
       arr[0] = 100;
       arr[1] = 200;
   }
  • 先运行Init(),再运行getArrayContent(),运行结果:
    在这里插入图片描述
  • 可以看到,arr数组的第一个元素和第二个元素已经被修改了。
  1. 在定义的时候也可以初始化值,修改代码:
pragma solidity ^0.4.0;

contract TestArray {
   
   uint[5] arr = [1,2,3,4,5];
   
   function Init() public {
       arr[0] = 100;
       arr[1] = 200;
   }
   
   function getArrayContent() view public returns(uint[5]){
       return arr;
   }
}
  • 先运行getArrayContent()方法查看数组中的值:
    在这里插入图片描述
  • 初始化成功。
  • 在运行Init()方法后再运行getArrayContent()方法:
    在这里插入图片描述
  • 可以看到,数组中的前两个值也被修改了。
  1. 我们可以用这个数组进行一些简单的算法,比如求数组中所有元素的和,给出代码:
 function getGrades() view public returns(uint) {
       uint totall = 0;
       for(uint i = 0;i < arr.length;i++){
           totall = totall + arr[i];
       }
    return totall;
   }
  • 我们先运行Init()方法初始化后,再运行getGrades进行求和操作,预期结果应该是100+200+3+4+5 = 312,运行结果:
    在这里插入图片描述
  • 运行结果与预期的相符。
  1. 数组是有length属性的,但是不能对length属性进行修改。固定数组也没有push方法,不能向固定数组中增加元素。

三、动态数组

先看代码:

pragma solidity ^0.4.0;

contract TestArray {
    
    uint[] arr;// 定义一个可变长度的数组
    
    function getContent() view public returns(uint[]){
        return arr;
    }
    
    function getLength() view public returns(uint){
        return arr.length;
    }
}
  1. arr就是一个动态数组,因为它没有被定义长度。
  • 运行getContent()查看arr的默认值,再运行getLength()查看arr的默认大小
    在这里插入图片描述
  • 可以看到,arr里面没有值,大小也是0。
  1. 修改代码:
pragma solidity ^0.4.0;

contract TestArray {
    
    uint[] arr = [1,2,3,4,5];// 定义一个可变长度的数组
    
    function getContent() view public returns(uint[]){
        return arr;
    }
    
    function getLength() view public returns(uint){
        return arr.length;
    }
    
    function setArr() public{
        arr[0] = 100;
        arr[1] = 200;
    }
    
    function push() public{
        arr.push(6);
        arr.push(7);
        arr.push(8);
    }
}
  • 首先直接运行getContent()和getLength(),获取初始化后arr里的值和arr的大小:
    在这里插入图片描述
  • 运行setArr方法修改其中的值,再运行下面两个get方法:
    在这里插入图片描述
  • 运行push()方法向数组后面增加三个数,再运行下面两个get方法:
    在这里插入图片描述
  1. 既然是动态数组,那长度也是可以改变的,我们写一个函数验证一下。
  function changeLength(uint length) public{
        arr.length = length;
    }
  • 这个函数的逻辑很简单,在这里就不细说了。
  • 运行changeLength方法春如参数为10,之后在运行两个get方法,运行结果:
    在这里插入图片描述

可以看到,之后添加的空间上都补上了0

  • 相同的方法,吧参数改为1,运行结果:
    在这里插入图片描述

超过给定大小之后的值全部都被抹去了。

四、二维数组

在java中的二维数组,例如int[3][2] arr;表示arr有3个元素,每个元素都是一个长度为2的数组。
但是在solidity里,完全相反,例如uint[3][2] arr;表示arr有2个元素,每个元素都是一个长为3的数组。

给出二维数组有关代码:

pragma solidity ^0.4.0;

contract TestArray {
    
    uint[2][3] arr = [[1,2],[3,4],[5,6]];
    
    function getLength() view public returns(uint){// 获取数组的长度
        return arr.length;
    }
    
    function getLength2() view public returns(uint){// 获取二维数组的长度
        return arr[0].length;
    }
    
    function getContent() view public returns(uint[2][3]){// 获取二维数组中所有数的值
        return arr;
    }
    
    function add() view public returns(uint){// 将二维数组中所有数相加
        uint count = 0;
        for(uint i = 0;i < getLength2();i++){
            for(uint j = 0;j < getLength();j++){
                count += arr[j][i];
            }
        }
        return count;
    }
}
  • 每个函数的功能都在代码中标出,逻辑都很简单,可以自己回去写一下,运行结果:
    在这里插入图片描述
  • 结果正确。
  • 也可以通过方法修改二维数组的元素值,在这里就不给出代码了。

五、动态二维数组

先给出代码:

pragma solidity ^0.4.0;

contract TestArray {
    
    uint[][] arr = [[1,2],[3,4],[5,6]];
    
    function setLength(uint length) public{
        arr.length = length;
    }
    
    function getLength() view public returns(uint){
        return arr.length;
    }
}
  • 运行getLength()获取长度:
    在这里插入图片描述

  • 运行setLength()更改长度之和,再运行getLength()获取更改后的长度,这里我们给出两个结果,第一个输入2,第二个输入6
    在这里插入图片描述
    在这里插入图片描述

  • 可以看到,可变二维数组的大小增加和减少都是没有问题的。

  1. 二维可变数组没有push()方法。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!