天天看點

以太坊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的顯示結果都正常

以太坊solidity學習記錄(三)基礎資料操作

運作stringchange之後,發現第一位從68變成了41,修改成功

以太坊solidity學習記錄(三)基礎資料操作

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;
    }
}
           

測試結果

以太坊solidity學習記錄(三)基礎資料操作

可見中文一個占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);
    }   
}
           

運作結果

以太坊solidity學習記錄(三)基礎資料操作

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沒有被指派

以太坊solidity學習記錄(三)基礎資料操作

然後點選setvalue之後再點選檢視就可發現可變長度數組已經被指派

以太坊solidity學習記錄(三)基礎資料操作

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);
    }
}
           

運作結果

以太坊solidity學習記錄(三)基礎資料操作

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);//強制轉化即可
    }
}
           

運作結果

以太坊solidity學習記錄(三)基礎資料操作

注意:

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

以太坊solidity學習記錄(三)基礎資料操作

2.進行指派之後可看見數值發生變化

以太坊solidity學習記錄(三)基礎資料操作

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.原始情況

以太坊solidity學習記錄(三)基礎資料操作

2.調用push,并且改變數值之後

以太坊solidity學習記錄(三)基礎資料操作

3.變小在變長之後

以太坊solidity學習記錄(三)基礎資料操作

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.未進行數值修改之前

以太坊solidity學習記錄(三)基礎資料操作

2.進行數值修改之後

以太坊solidity學習記錄(三)基礎資料操作

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沒反應

以太坊solidity學習記錄(三)基礎資料操作

2.改變長度之後再指派就有反應了,而且總和改變,說明指派成功,而且預設值設定的是0

以太坊solidity學習記錄(三)基礎資料操作

3.最後進行changevalue時,總和改變

以太坊solidity學習記錄(三)基礎資料操作

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;
    }
}
           

測試結果

以太坊solidity學習記錄(三)基礎資料操作

本文所有代碼見下(無注釋)

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;
    }
}

           

繼續閱讀