以太坊solidity学习记录(三)基础数据操作

个人目录

以太坊solidity学习记录(一)新版在线remix编译器的使用(2020.4.27)
以太坊solidity学习记录(二)基础操作整理
以太坊solidity学习记录(三)基础数据操作
以太坊solidity学习记录(四)地址与交易
以太坊solidity学习记录(五)函数入门
以太坊solidity学习记录(六)内存与结构体

1.如何修改string类型

pragma solidity ^0.4.0;
contract stringtest1{
    string testword='helloworld'; //68656c6c6f776f726c64为这串字符的16进制
    
    function stringlength() public view returns (uint){
        //return testword.length;  直接返回长度会报错
        return bytes(testword).length;  //强制类型转换之后可以
    }
    
    function stringchange() public  {
        //testword[0]='A'; 直接进行变更会报错
        bytes(testword)[0]='A'; //41为A的16进制值,强制类型转换之后可以修改
    }
    
    function getname() public view returns(bytes){
        return bytes(testword); //查看16进制的string
    }
    
    function stringchangetest() public view returns(byte){
        return bytes(testword)[0]; //查看第一位是否被修改
    }
    
}

测试结果
一开始getname和stringlength的显示结果都正常
在这里插入图片描述

运行stringchange之后,发现第一位从68变成了41,修改成功
在这里插入图片描述

2.string类型是怎么存储数据的

英文字符(A-z)以及特殊字符(&*@#&%())等为一个字节
中文字符为3个字节 PS.solidity中文输入支持很差
举例

contract stringstoragetest{
    string testword1='asldhlkasdh';
    string testword2='^*^*%*()*-/';
    string testword3='中文测试';
    string testword4='中文测试2222';
    
    function stringstoragetest1() public view returns(uint){
        return bytes(testword1).length;
    }
    function stringstoragetest2() public view returns(uint){
        return bytes(testword2).length;
    }
    function stringstoragetest3() public view returns(uint){
        return bytes(testword3).length;
    }
     function stringstoragetest4() public view returns(uint){
        return bytes(testword4).length;
    }
}

测试结果
在这里插入图片描述
可见中文一个占3个字节,中文和英文同时存在时互不干扰
解释:储存中文和一些其他语言时,solidity使用的时UTF-8格式存储的

3.固定长度字节数组bytes的截断

结论:位数足够则保留前面的,位数不够再后面加0
测试程序

contract bytetest1{
    bytes10 testword=0x68656c6c6f776f726c64; //helloworld
    function transbytes1() public view returns(bytes1){
        return bytes1(testword);
    }
    function transbytes2() public view returns(bytes5){
        return bytes5(testword);
    }
    function transbytes3() public view returns(bytes12){
        return bytes12(testword);
    }   
}

运行结果
在这里插入图片描述

4.将固定长度数组变为可变长度数组

方法:即再构造另一个可变程度数组然后一个个赋值过去即可
代码如下

contract arrtranstest{
    bytes10 testword=0x68656c6c6f776f726c64;
    bytes transarr = new bytes(testword.length);
    
    function setvalue() public {
       for(uint i=0;i<testword.length;i++){
           transarr[i]=testword[i];
        }
    }
    function showtransarr() public view returns(bytes){
        return transarr;
    }
}

运行结果
首先点击查看可以看见transarr没有被赋值
在这里插入图片描述

然后点击setvalue之后再点击查看就可发现可变长度数组已经被赋值
在这里插入图片描述

5.将可变长度字节数组bytes转化为可以显示字符的string

方法:直接强制转化即可
代码

contract bytestostring{
    bytes testword = new bytes(10);
    
    function setvalue() public {
       testword.push(0x68);
       testword.push(0x4d);
    }
    function showtransarr() public view returns(string){
        return string(testword);
    }
}

运行结果
在这里插入图片描述

6.将固定长度字节数组转化为string类型

思路:既然存在一下两种转换
1.固定长度字节数组转化为可变长度字节数组
2.可变长度字节长度数组转化为string类型
那么我们综合12便可得到我们的解法

contract bytes32tostring{
    bytes10 testword=0x68656c6c6f776f726c64; //为helloworld
    
    function bytes32tostringF() public view returns(string){
        uint count=0; //这里必须初始为uint,否则报错
    for(uint i=0;i<testword.length;i++){
        bytes1 tester=testword[i];
        if(tester!=0x00){//此步计算出所有不为空值的位数
            count++;
        }
    }
    bytes memory transarr=new bytes(count);//声明一个新的可变数组,长度为之前的count,
                                           //这样就不会导致转化后后面过多的方框了
    for(uint j=0;j<count;j++){//重新对可变数组进行赋值
        transarr[j]=testword[j];      
    }
    return string(transarr);//强制转化即可
    }
}

运行结果
在这里插入图片描述
注意:
1.固定长度字节数组不能直接强制转化为string,否则会报错无法编译通过
2.如果不使用count来计数,那么可变长度数组前面为原来固定长度数组的值,后面则全部为0,强制转化出来的string后面就会带许多的“口”(表示未知字符),所以需要使用count来对所有有效字符进行计数

7.固定长度数组入门

结论:
1.如果不赋值,那么默认所有位均为0
2.支持直接使用.length查看数组长度,但不支持对数组长度做修改
3.不支持通过.push添加数据
代码

contract fixedarrtest{
    uint[3] testarr1;//不进行赋值直接声明数组
    uint[3] testarr2=[1,2,3];//声明数组并进行赋值
    
    function showarr1() public view returns(uint[3]){
        return testarr1; //如果不赋值,那么默认所有位均为0
    }
    
    function showarr2() public view returns(uint[3]){
        return testarr2;
    }
    
    function initarr() public{
        testarr1[0]=12;//进行赋值操作
    }
    
    function lengthtest() public view returns(uint){
        return testarr1.length;//solidity支持直接查看数组长度
    }
    
    function changelengthtest() public view returns(uint){
        //testarr1.length=testarr1.length+3;//solidity不支持直接修改数组长度
    }
    
    function pushtest() public view {
        //testarr2.push(2);//solidity不支持直接push数据到数组
    }
    
}

运行结果
1.初始化之前可看到arr1所有数组均为0
在这里插入图片描述
2.进行赋值之后可看见数值发生变化
在这里插入图片描述

8.可变长度数组入门

结论:
1.如果不初始化就无法单独赋值,但可以push或者改长度使有值之后再进行赋值。即必须修改的这一位不能为空(试了好久才发现,我一开始还以为是bug)
2.支持直接使用.length查看数组长度,也支持对数组长度做修改。
将数组长度缩小则会从前往后保留
将数组长度增长则后面原本没有值的位会被默认置0
3.支持直接通过.push方法在末尾添加数值

contract dynamicarrtest{
    uint[] testarr=[1,2,3,4,5];
    
    function showarr() public view returns (uint[]){
        return testarr;
    }
    
    function changearr() public{
        //for(uint i=0;i<5;i++){
            testarr[0] = 2;//如果不使0位有值,那么该函数无用
        //}
    }
    
    function lengthtest() public view returns(uint){
        return testarr.length;
    }
    
    function changelengthtest1() public{
        testarr.length=1;
    }
    
    function changelengthtest2() public{
        testarr.length=10;//变长之后后面默认置0
    }
    
    function pushtest() public{
        testarr.push(6);//可变数组支持此操作
    }
    
}

运行结果
1.原始情况
在这里插入图片描述
2.调用push,并且改变数值之后
在这里插入图片描述
3.变小在变长之后
在这里插入图片描述

9. 有点反人类的固定长度二维数组

结论
1.初始化时,uint[ i ] [ j ]表示有j个元素,每个元素包含i个值(和其他许多语言不同
2.二维数组可以直接获取长度,既可以获得所有元素个数,也可以获得单独元素有多少值
3.对二维数组进行增删改等操作时时是与初始化时反过来的,即uint[ i ] [ j ]表示第i个元素的第j个值(和其他许多语言一样
4.不支持push方法,也不支持对长度进行修改

contract doublearrtest{
    uint[2][4] testarr1=[[1,2],[3,4],[5,6]];
    function showlength1() public view returns (uint){
        return testarr1.length; //返回整个数组有多少值
    }
    
    function showlength2() public view returns (uint){
        return testarr1[0].length;  //返回单个元素的长度
    }
    
    function changevalue() public{
        testarr1[0][1]=10;  //给第1个元素的第2个值赋值10
        testarr1[2][0]=200;  //给第3个元素的第1个值赋值200
        
    }
    
    function showall() public view returns(uint[2][4]){
           return testarr1;  //可以看见直接返回时是横向排列的
    }
    
    //function pushtest() public{   不管怎样使用push方法均会报错
           //testarr1.push([7,8]);
           //testarr1.push(7,8);
    //}
    
    function inittest() public{
           //testarr1[0][3]=7;  
           testarr1[3][0]=7;  //可以给未赋值的位数赋值
           testarr1[3][1]=8;
           
    }
    function getsum() public view returns (uint){
        uint sum=0;
        for(uint i=0;i<testarr1.length;i++){  
            for(uint j=0;j<testarr1[i].length;j++){
                sum+=testarr1[i][j];   //遍历数组求和
            }
        }
        return sum;
    }
}

运行结果
1.未进行数值修改之前
在这里插入图片描述
2.进行数值修改之后
在这里插入图片描述

10.可变长度二维数组

结论
1.初始化时,uint[ i ] [ j ]表示有j个元素,每个元素包含i个值(和其他许多语言不同
2.可变长度二维数组可以直接获取长度,既可以获得所有元素个数,也可以获得单独元素有多少值
3.对二维数组进行增删改等操作时时是与初始化时反过来的,即uint[ i ] [ j ]表示第i个元素的第j个值(和其他许多语言一样
4.不支持push方法
5.支持对长度进行修改,修改后默认值为0
6.未声明的值不能直接赋值,修改长度之后默认有值才可以

代码

contract dynamicdoublearrtest{
    uint[][] testarr1=[[1,2],[3,4],[5,6]];
    function changevalue() public{
        testarr1[0][1]=10;
        testarr1[2][0]=200;
        
    }
    
    //function showall() public view returns(uint[][]){
    //       return testarr1;
    //}
    
    //function pushtest() public{
           //testarr1.push([7,8]);
           //testarr1.push(7,8);
    
    function inittest() public{
           //testarr1[0][3]=7;
          testarr1[0][2]=7; //未声明的值仍然不支持直接赋值
          testarr1[0][3]=8;
           //testarr1.push(7,8);
    }
    
   function initvalue1() public view returns(uint){
       return testarr1[0][2];
    }
    
   function initvalue2() public view returns(uint){
       return testarr1[0][3];
   }
    
    
    function getsum() public view returns (uint){
        uint sum=0;
        for(uint i=0;i<testarr1.length;i++){
            for(uint j=0;j<testarr1[i].length;j++){
                sum+=testarr1[i][j];
            }
        }
        return sum;
    }
    
    function changelengthtest1() public{
        testarr1.length=5;
    }
    
    function changelengthtest2() public{
        testarr1[0].length=5;
    }
    
    function getlength1() public view returns(uint){
        return testarr1.length;
    }
    
    function getlength2() public view  returns(uint){
        return testarr1[0].length;
    }
    
    function getdefaultvalue() public view  returns(uint){
        return testarr1[0][4];
    }
}

测试结果
1.一开始可以获得长度与总和,并且点击initvalue1,initvalue2没反应
在这里插入图片描述
2.改变长度之后再赋值就有反应了,而且总和改变,说明赋值成功,而且默认值设置的是0
在这里插入图片描述
3.最后进行changevalue时,总和改变
在这里插入图片描述

11.数组字面量

结论:
1.返回数组时,returns()括号里面的类型要与return的数据类型相同。
通过getarr1和getarr2可以知道,return之后的会默认最小数据类型,比如小于255的就默认为uint8类型, return [1,2,3]就迷人uint8,return [256,2,3]就默认uint16等等,然而returns()里面的uint默认为uint256,所以报错,需注意
2.可以通过对return里面任意一个数值来进行强制转换来改变数据类型
3.可以直接接受参数来进行计算

contract finaltest{
    function getarr1() public view returns(uint[3]){
    //    return [1,2,3];  报错,此处为uint8,而需要返回的是uint256
    }
    function getarr2() public view returns(uint[3]){
    //    return [256,2,3];报错,此处为uint16,而需要返回的是uint256
    }
    function getarr3() public view returns(uint8[3]){
        return [1,2,3];    //成功
    }
    function getarr4() public view returns(uint16[3]){
        return [256,2,3];  //成功
    }
    function getarr5() public view returns(uint32[3]){
        return [uint32(1),2,3]; //可以通过对return里面任意一个数值来
                                //进行强制转换来改变数据类型
    }
    function getarr6(uint[] num) public view returns(uint){
        uint sum=0;
        for(uint i=0;i<num.length;i++){
            sum+=num[i]; //可以直接接受参数来进行计算,
           //参数需要按照格式来,此处就应该为[x1,x2,x3,x4,...,xn]
        }
        return sum;
    }
}

测试结果
在这里插入图片描述

本文所有代码见下(无注释)

pragma solidity ^0.4.0;
contract stringtest1{
    string testword='helloworld'; //68656c6c6f776f726c64
    
    function stringlength() public view returns (uint){
        //return testword.length; 
        return bytes(testword).length;
    }
    
    function stringchange() public  {
        //testword[0]='A';
        bytes(testword)[0]='A'; //41
    }
    
    function getname() public view returns(bytes){
        return bytes(testword);
    }
    
    function stringchangetest() public view returns(byte){
        return bytes(testword)[0];
    }
}

contract stringstoragetest{
    string testword1='asldhlkasdh';
    string testword2='^*^*%*()*-/';
    string testword3='中文测试';
    string testword4='中文测试2222';
    
    function stringstoragetest1() public view returns(uint){
        return bytes(testword1).length;
    }
    function stringstoragetest2() public view returns(uint){
        return bytes(testword2).length;
    }
    function stringstoragetest3() public view returns(uint){
        return bytes(testword3).length;
    }
     function stringstoragetest4() public view returns(uint){
        return bytes(testword4).length;
    }
}

contract bytetest1{
    bytes10 testword=0x68656c6c6f776f726c64; 
    function transbytes1() public view returns(bytes1){
        return bytes1(testword);
    }
    function transbytes2() public view returns(bytes5){
        return bytes5(testword);
    }
    function transbytes3() public view returns(bytes12){
        return bytes12(testword);
    }
    
}


contract arrtranstest{
    bytes10 testword=0x68656c6c6f776f726c64;
    bytes transarr = new bytes(testword.length);
    
    function setvalue() public {
    for(uint i=0;i<testword.length;i++){
        transarr[i]=testword[i];
    }
    }
    
    
    function showtransarr() public view returns(bytes){
        return transarr;
    }
}

contract bytestostring{
    bytes testword = new bytes(10);
    
    function setvalue() public {
       testword.push(0x68);
       testword.push(0x4d);
    }
    function showtransarr() public view returns(string){
        return string(testword);
    }
}


contract bytes32tostring{
    bytes10 testword=0x68656c6c6f776f726c64;
    
    function bytes32tostringF() public view returns(string){
        uint count=0;
    for(uint i=0;i<testword.length;i++){
        bytes1 tester=testword[i];
        if(tester!=0x00){
            count++;
        }
    }
    bytes memory transarr=new bytes(count);
    for(uint j=0;j<count;j++){
        transarr[j]=testword[j];
    }
    return string(transarr);
    
    }
    
}

contract fixedarrtest{
    uint[3] testarr1;
    uint[3] testarr2=[1,2,3];
    
    function showarr1() public view returns(uint[3]){
        return testarr1;
    }
    
    function showarr2() public view returns(uint[3]){
        return testarr2;
    }
    
    function initarr() public{
        testarr1[0]=12;
    }
    
    function lengthtest() public view returns(uint){
        return testarr1.length;
    }
    
    function changelengthtest() public view returns(uint){
        //testarr1.length=testarr1.length+3;
    }
    
    function pushtest() public view {
        //testarr2.push(2);
    }
    
}



contract dynamicarrtest{
    uint[] testarr=[1,2,3,4,5];
    
    function showarr() public view returns (uint[]){
        return testarr;
    }
    
    function changearr() public{
        //for(uint i=0;i<5;i++){
            testarr[0] = 2;
        //}
    }
    
    function lengthtest() public view returns(uint){
        return testarr.length;
    }
    
    function changelengthtest1() public{
        testarr.length=1;
    }
    
    function changelengthtest2() public{
        testarr.length=10;
    }
    
    function pushtest() public{
        testarr.push(6);
    }
    
}

contract doublearrtest{
    uint[2][4] testarr1=[[1,2],[3,4],[5,6]];
   
    
    function showlength1() public view returns (uint){
        return testarr1.length;
    }
    
    function showlength2() public view returns (uint){
        return testarr1[0].length;
    }
    
    function changevalue() public{
        testarr1[0][1]=10;
        testarr1[2][0]=200;
        
    }
    
    function showall() public view returns(uint[2][4]){
           return testarr1;
    }
    
    //function pushtest() public{
           //testarr1.push([7,8]);
           //testarr1.push(7,8);
    //}
    
    function inittest() public{
           //testarr1[0][3]=7;
           testarr1[3][0]=7;
           testarr1[3][1]=8;
           //testarr1.push(7,8);
    }
    
    
    
    function getsum() public view returns (uint){
        uint sum=0;
        for(uint i=0;i<testarr1.length;i++){
            for(uint j=0;j<testarr1[i].length;j++){
                sum+=testarr1[i][j];
            }
        }
        return sum;
    }
    

}



contract dynamicdoublearrtest{
    uint[][] testarr1=[[1,2],[3,4],[5,6]];
    function changevalue() public{
        testarr1[0][1]=10;
        testarr1[2][0]=200;
        
    }
    
    //function showall() public view returns(uint[][]){
    //       return testarr1;
    //}
    
    //function pushtest() public{
           //testarr1.push([7,8]);
           //testarr1.push(7,8);
    
    function inittest() public{
           //testarr1[0][3]=7;
          testarr1[0][2]=7; //未声明的值仍然不支持直接赋值
          testarr1[0][3]=8;
           //testarr1.push(7,8);
    }
    
   function initvalue1() public view returns(uint){
       return testarr1[0][2];
    }
    
   function initvalue2() public view returns(uint){
       return testarr1[0][3];
   }
    
    
    function getsum() public view returns (uint){
        uint sum=0;
        for(uint i=0;i<testarr1.length;i++){
            for(uint j=0;j<testarr1[i].length;j++){
                sum+=testarr1[i][j];
            }
        }
        return sum;
    }
    
    function changelengthtest1() public{
        testarr1.length=5;
    }
    
    function changelengthtest2() public{
        testarr1[0].length=5;
    }
    
    function getlength1() public view returns(uint){
        return testarr1.length;
    }
    
    function getlength2() public view  returns(uint){
        return testarr1[0].length;
    }
    
    function getdefaultvalue() public view  returns(uint){
        return testarr1[0][4];
    }
}
contract finaltest{
    function getarr1() public view returns(uint[3]){
    //    return [1,2,3];
    }
    function getarr2() public view returns(uint[3]){
    //    return [256,2,3];
    }
    function getarr3() public view returns(uint8[3]){
        return [1,2,3];
    }
    function getarr4() public view returns(uint16[3]){
        return [256,2,3];
    }
    function getarr5() public view returns(uint32[3]){
        return [uint32(1),2,3];
    }
    function getarr6(uint[] num) public view returns(uint){
        uint sum=0;
        for(uint i=0;i<num.length;i++){
            sum+=num[i];
        }
        return sum;
    }
}


版权声明:本文为weixin_45067603原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。