個人目錄
以太坊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的顯示結果都正常
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuETM2IDOyYTM1IDNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
運作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;
}
}