以太坊solidity学习记录(一)新版在线remix编译器的使用(2020.4.27)
以太坊solidity学习记录(二)基础操作整理
以太坊solidity学习记录(三)基础数据操作
以太坊solidity学习记录(四)地址与交易
以太坊solidity学习记录(五)函数入门
以太坊solidity学习记录(六)内存与结构体
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,修改成功
英文字符(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格式存储的
结论:位数足够则保留前面的,位数不够再后面加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);
}
}
方法:即再构造另一个可变程度数组然后一个个赋值过去即可
代码如下
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;
}
}
然后点击setvalue之后再点击查看就可发现可变长度数组已经被赋值
方法:直接强制转化即可
代码
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);
}
}
思路:既然存在一下两种转换
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来对所有有效字符进行计数
结论:
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.进行赋值之后可看见数值发生变化
结论:
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.变小在变长之后
结论
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.初始化时,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时,总和改变
结论:
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;
}
}