一、string如何存储中文字符
二、固长数组
三、动态数组
四、二维数组
五、动态二维数组
一、string如何存储中文字符
先看一段代码:
pragma solidity >=0.4.22 <0.6.0;
contract Test {
string name = "张三";
function getLength() public view returns(uint256){
return bytes(name).length;
}
}
- 我们知道,普通字符在占据的内存是一个字节,那么像中文这种特殊字符应该怎么存储呢?我们执行上面的代码:
- 可以看到,一个中文字符是3个字节,总共是6个。
- 事实上,在string中,特殊字符是用UTF-8存储的。
- 关于UTF-8:UTF-8介绍
- 介绍两个关键字:
memory:临时变量,定义在函数内的变量默认为memory,一些版本的编译器要求定义在函数内的临时变量必须加上memory关键字。
storage:永久写入区块链的变量,就是定义在函数之外的状态变量。
- 把字节数组转化为动态字节数组,代码:
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;
}
}
- 有编程基础的人应该不难看出代码逻辑,这里直接给出结果:
- 动态字节数组转字符串可以通过强制转换实现,但是普通的字节数组想要转字符串就比较麻烦了,修改以上代码:
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类型,有编程基础的看这个代码逻辑也不难,在这里不过于解释,运行结果:
- 但是这也引发了一个问题,当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
- 通过方法来修改数组中的值,在合约中加入以下代码:
function Init() public {
arr[0] = 100;
arr[1] = 200;
}
- 先运行Init(),再运行getArrayContent(),运行结果:
- 可以看到,arr数组的第一个元素和第二个元素已经被修改了。
- 在定义的时候也可以初始化值,修改代码:
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()方法:
- 可以看到,数组中的前两个值也被修改了。
- 我们可以用这个数组进行一些简单的算法,比如求数组中所有元素的和,给出代码:
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,运行结果:
- 运行结果与预期的相符。
- 数组是有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;
}
}
- arr就是一个动态数组,因为它没有被定义长度。
- 运行getContent()查看arr的默认值,再运行getLength()查看arr的默认大小
- 可以看到,arr里面没有值,大小也是0。
- 修改代码:
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方法:
- 既然是动态数组,那长度也是可以改变的,我们写一个函数验证一下。
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
-
可以看到,可变二维数组的大小增加和减少都是没有问题的。
- 二维可变数组没有push()方法。
来源:oschina
链接:https://my.oschina.net/u/4358445/blog/4892228