Solidity基础四
あなたもきっと、誰かの奇跡 (你也一定会是某个人的奇迹)
目录
一、Solidity的结构体
1.结构体的实例化
2.结构体的基本使用
访问和修改结构体成员
3.结构体的修饰符
二、Solidity的映射
1.映射的基本使用
查询和修改某个value值
三、Solidity的枚举
四、数组、结构体、映射的直接相互嵌套
1.没有数组嵌套数组
2.数组嵌套结构体
3.没有数组嵌套映射
4.结构体嵌套数组
5.结构体嵌套结构体
6.结构体嵌套映射
7.映射嵌套数组
8.映射嵌套结构体
9.映射嵌套映射
10、重要说明(间接嵌套)
五、关于枚举的嵌套
一、Solidity的结构体
结构体是一个引用数据类型,用于表示复合型数据
在结构体里面的数据我们称之为成员
结构体可以任何数据类型作为体内的成员,但是不能内部包含自身结构体,也就是不能在自己的结构体中写自己的结构体
结构体可以多次实例化,且各个实例化互不影响
关键字:struct
定义结构体格式:
struct 结构体名 {
成员1;
成员2;
成员3;
```````````
}
结构体的可见性:
关于可见性,目前只支持internal,所以结构体只能在合约内部和子合约内使用。包含结构体的函数必须显性声明为internal
因此结构体里面的成员也是internal,不能再定义权限修饰符了
1.结构体的实例化
结构体创建后其实是一个模板类似于java中的类,对其实例化以后,相当于拿了这个模板去使用,同一个结构体不同实例化互不影响,自己存储在自己对应的实例化内存中,类似于java的对象
实例化格式:
结构体名 修饰符 实例化结构体名
温馨提示:结构体实例化之后,会给实例化结构体内部数据赋予一个初始值
结构体实例化后整体赋值:
实例化名 = 结构体名(值1,值2,·····)
注意:上下这两种方式是整体赋值必须全部赋值,否则报错
实例化结构体并初始化格式:
结构体名 修饰符 实例化名 = 结构体名(值1,值2,·····) 这个要按成员顺序赋值
结构体名 修饰符 实例化名 = 结构体名({ 成员:值,成员:值,···}) 这个可以不按照顺序赋值
2.结构体的基本使用
访问和修改结构体成员
访问结构体成员格式:
实例化结构体名.成员
修改结构体成员格式:
实例化结构体名.成员 = 新值
3.结构体的修饰符
结构体实例化的修饰符是用于修饰它所存储的位置用memory/storage或者方位权限public````等
如果在函数外实例化,默认强制存储storage不需要写修饰符
如果在函数内实例化,就必须写所存储的位置
当结构体中存在mapping时,不允许再用memory创建和初始化,要用storage(因为maaping只能存储在storage中)
结构体中的mapping类型,可初始化,也可不初始化,其他类型不可
要对结构体中的mapping操作,只能通过storage的存储来操作
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
contract test {struct Student {string name;int age;}Student public stu;function set() public returns(string memory,int){stu = Student(unicode'大哥',2);stu.age=100;return (stu.name,stu.age);//大哥,100}}
二、Solidity的映射
映射 mapping 是智能合约中很常用的一种数据类型,它是引用类型。
Solidity 映射 mapping 用于以键值对的形式存储数据
键 = key 值 = value
一个key对应者一个value
它与使用结构体不同,和数组类似,创建后不需要实例化,直接使用
- 在mapping中key可以是整型、字符串等基本数据类型,但不是引用数据类型和枚举
- 而value的类型没有数据类型限制,可以是任意数据类型,甚至使用一个mapping作为value也是允许的,
温馨提示:mapping不能作为参数使用,也不能返回整个mapping,只能返回key对应的value
关键字: mapping
映射的定义格式:
mapping(key数据类型 => value数据类型) 权限修饰符 映射名
注意
- 映射的数据位置只能是 storage,通常用于状态变量。所以它不可以定义存储修饰符
- 映射可以标记权限修饰符,当权限修饰符为 public, Solidity 会创建一个 getter 函数。 key数据 将成为 getter 的必须参数,并且 getter 会返回 key数据对应的value
映射是没有长度的,也没有 key 的集合或 value 的集合的概念。映射只能是存储的数据位置,因此只允许作为状态变量或作为函数内的存储引用 或 作为库函数的参数。 它们不能用于合约公有函数的参数或返回值。
1.映射的基本使用
查询和修改某个value值
在映射中我们只能查询到value的值,查询不到key的值,也就是说可以通过key查询value但不能通过value查询key
查询value格式:
映射名[key值]
修改value格式:
映射名[key值] = 新value值
初始化映射(删除)
delete 映射名[key值]
注意事项:在映射的查询中,如果赋予一个不存在(没有存储)的key值,那么它所对应和返回的value值就是value数据类型的默认值
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
contract test {mapping(int=>int) public a;function set() public returns(int){a[1]=2;return a[1];}function tests(int _b) public view returns(int){return a[_b];}}
三、Solidity的枚举
solidity 的枚举类型 是一种用户自定义类型,用于表示多种状态。
枚举类型内部就是一个自定义的整型,默认的类型为
uint8
,当枚举数足够多时,它会自动变成uint16
。(也就是枚举里面存放的元素个数)枚举类型可以与整数进行显式转换,但不能进行隐式转换。显示转换会在运行时检查数值范围,如果不匹配,将会引起异常。
关键字:enum
定义格式:
enum 枚举名 { 枚举元素1,枚举元素2,枚举元素3,····· }
注意,枚举的结尾}不需要加;
定义枚举类型变量:
枚举名 权限修饰符 枚举变量名
枚举类型的变量用于存放枚举里面的某个元素值,默认的值为第一个枚举元素值
给枚举变量赋值:
第一种:枚举内元素赋值
枚举变量名 = 枚举名.枚举元素
第二种:自定义uint类型数据赋值
枚举变量名 = uint类型数据
注意:所给枚举变量赋值的uint类型数据必须是枚举元素内含有的值(枚举元素1-枚举元素n的uint值范围)不是该范围则运行报错
重置枚举变量:将其重置为枚举元素1的值
关键字:delete
格式:
delete 枚举变量名
枚举体语法格式注释:
1)enum必须要有成员对象, { }中不能为空;
2)enum 中不能出现中文;
3){ }中不能加分号使用枚举类型的主要好处:
明确值的范围,防止错误的值输入。
提高代码的可读性,使得代码更加清晰易懂。
便于维护,需要增加/删除枚举类型的值的时候,只需要修改枚举类型的定义,不需要修改使用枚举类型的代码。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract EnumExample {enum Status {Pending,Shipped,Accepted,Rejected,Canceled//枚举类型是unit8数据结构,内部元素均为uint8由0开始按顺序赋值//若元素超出了uint8赋值则增加为uint16// 枚举元素 对应的uint// Pending --- 0// Shipped --- 1// Accepted --- 2// Rejected --- 3// Canceled --- 4}//定义了枚举类型的变量Status public status; function get() public view returns (Status) {return status; //默认分配Pending 0}function set1() public {status = Status.Canceled; //设置枚举元素Canceled 4}function set(Status _a) public {status = _a; //外部uint值类型 范围 0-4 ,不是该范围则运行报错}function reset() public {delete status;}
}
四、数组、结构体、映射的直接相互嵌套
1.没有数组嵌套数组
数组不能嵌套数组,只能数组和数组之间相互赋值
2.数组嵌套结构体
在数组里面存放结构体,我们称之为数组结构体
定义格式:
结构体名[长度] 修饰符 数组名
提示:长度可写可不写,写了代表定长数组,不写代表变长数组,变长数组要注意一开始没有长度,需要push()添加值(变长)
查询一个下标对应整个结构体格式:
数组名[下标]
查询一个下标对应结构体的成员值格式:
数组名[下标].结构体成员名
赋值就在查询后面加个 =
作为函数参数的注意事项
当返回的是一个数组结构体值,那么返回的参数也必须是数组结构体
当数组结构体作为形参,那么传入的实参也必须是数组结构体
3.没有数组嵌套映射
数组不能嵌套映射,只能数组和映射相互赋值
4.结构体嵌套数组
在结构体里面让数组作为结构体成员,我们称之为结构体数组
结构体数组可以是变长的也可以是定长的
结构体数组定义格式:
struct 结构体名 {
数据类型[长度] 权限修饰符 数组名;
}
无法给结构体数组初始化赋值
访问结构体数组:
实例化结构体名.数组名
访问结构体数组的数组元素
实例化结构体名.数组名[下标]
给某个实例化结构体中的映射赋值
实例化结构体名.数组名[下标] = 元素值
如果是变长数组则是push()赋值
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Example {struct aaa {string name;int age;int[2] arr;int[] arr2;}aaa public a;function set() public {a.name=unicode'a';a.age=19;a.arr[0]=123;a.arr2.push(10);}function get() public view returns(int,int){return(a.arr[0],a.arr2[0]);}function getArr() public view returns(int[2] memory){return a.arr;}}
5.结构体嵌套结构体
结构体嵌套结构体,我们称之为结构体结构体,嵌套的里面的结构体是实例化的结构体
结构体结构体定义格式:
struct 结构体名1 {
成员;
·····
}
struct 结构体名 {
实例化结构体1
}
访问结构体结构体:
实例化结构体名.实例化结构体1
访问结构体数组的数组元素
实例化结构体名.实例化结构体1.实例化结构体1的成员
赋值就后面加 =
6.结构体嵌套映射
在结构体里面嵌套映射作为结构体的成员,我们成之为结构体映射
注意事项:
- 当结构体中存在mapping时,不允许再用memory对结构体实例化,要用storage(因为maaping只能存储在storage中)
- 要对结构体中的mapping操作,只能通过storage的存储来操作
- 在结构体里面的映射不能加权限修饰符,它强制和struct一样的权限
结构体映射定义格式:
struct 结构体名 {
mapping(key类型 => value类型) 映射名;
}
对结构体实例化并初始化mapping
以大括号引出,不按顺序赋值结构体名 别名= 结构体名( { key名:值,value名:值 } )
实例化结构体后对mapping初始化
以大括号引出,按顺序赋值结构体名: 实例化= 结构体名( { key值,value值 } )
访问结构体种的映射value值
实例化结构体名.映射名[kye值]
给某个实例化结构体中的映射赋值
实例化结构体名.映射名[key值] = value值
作为函数参数的注意事项
当返回的是一个数组结构映射,那么返回的参数也必须是结构体映射
当结构体映射作为形参,那么传入的实参也必须是结构体
7.映射嵌套数组
映射内的value作为数组,整个数组被映射嵌套,我们称之为映射数组
定义格式:
mapping(key类型 => 数组类型[长度]) 权限修饰符 映射名
访问映射里面存储数组
映射名[key值]
访问映射里面存储的数组具体值
映射名[key值][下标]
赋值就在查询后面加个 =
注意事项:映射本身固定为storage类型,因此使用的数组也必须是storage类型
如果里面是动态数组,则需要使用push()来赋值,格式:
映射名[key值].push(值)
8.映射嵌套结构体
映射内的value作为结构体,整个结构体被映射嵌套,我们称之为映射结构体
定义格式:
mapping(key类型 => 结构体名) 权限修饰符 映射名
访问映射里面存储的某个实例化结构体
映射名[key值]
访问映射里面存储的某个实例化结构体成员
映射名[key值].结构体成员
赋值就在查询后面加个 =
注意事项:映射本身固定为storage类型,因此使用的结构体也必须是storage类型
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Example {struct aaa {string name;int age;}mapping(int=>aaa) public bbb;aaa public a;function get(string memory _name,int _age,int _id) public returns(aaa memory,int) {a.name=_name;a.age=_age;bbb[_id]=a;return (bbb[_id],bbb[_id].age);}}
9.映射嵌套映射
映射内的value作为映射,整个内部映射被外部映射嵌套,我们称之为映射映射
定义格式:
mapping(key类型 => mapping(key类型=>value类型)) 权限修饰符 映射名l
例如
mapping(int=>mapping(int=>string)) public a;
访问映射里面存储的映射
映射名[外部key值]
访问映射里面存储的映射的value值
映射名[外部key值][内部key值]
赋值就在查询后面加个 =
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SolidityTest {mapping(int=>mapping(int=>string)) public a;function tran() public returns(string memory) { a[1][2]='a';a[1];return a[1][2];}
}
10、重要说明(间接嵌套)
虽然有些不能直接嵌套,但是可以通过结构体作为媒介进行间接嵌套
而结构体可以通过数组和映射作为媒介间接嵌套
当然有些能直接前嵌套也能间接嵌套
例如
数组-->结构体-->数组
映射-->结构体-->映射
映射--结构体-->数组
数组--结构体-->映射
结构体 -->数组 -->结构体
结构体 -->映射 --> 结构体
五、关于枚举的嵌套
枚举通常都是作为枚举变量使用
枚举只能以枚举变量的形式嵌套在结构体内
使用枚举变量的注意事项:
1.枚举变量的赋值只能给枚举类型变量赋值,或枚举元素
2.枚举变量不能存放到数组、结构体、映射、普通变量中去,因为数据类型不一样
3.枚举变量可以定义到结构体里面,然后对结构体内的枚举变量赋予枚举变量(间接性)
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
contract Enum{enum Status {None,Padding,Shipped,Completed,Rejected,Canceled}Status public status;//枚举变量struct Order {address buyer;Status status;//结构体嵌套枚举}Order[] public orders;//数组结构体function get() view external returns (Status) {return status;//返回枚举变量}function set(Status _status) external {status = _status;//枚举变量的赋值}function ship() external {status = Status.Shipped;//枚举变量的赋值}function reset() external{delete status;//重置枚举变量}
}
Solidity基础四相关推荐
- Solidity 基础知识
Solidity 基础知识 官网:Solidity 版本设置 // SPDX-License-Identifier:MIT 表示身份协议 // ^0.8.7 表示当前代码支持 0.8.7 及以后 so ...
- 智能车竞赛技术报告 | 基础四轮组 - 哈尔滨工程大学 - 济海追风5队
简 介: 本文详细介绍了哈尔滨工程大学"济海追风5队"在第十六届全国大学生智能汽车竞赛基础四轮组中的系统方案.本次比赛采用大赛组委会指定的B3型车模,以英飞凌半导体公司生产的32位 ...
- mysql 连接 分组_MySQL 基础 (四) 分组查询及连接查询
MySQL 基础 (四) 分组查询及连接查询 MySQL 基础(四) 进阶 5 分组查询 语法: SELECT 分组函数, 列(要求出现在 group by 的后面) FROM 表 [where 筛选 ...
- 【RabbitMQ】基础四:路由模式(Routing)
[RabbitMQ]基础四:路由模式(Routing) 1. 路由模式说明 2. 代码示例 2.1 生产者 2.2 消费者1 2.3 消费者2 2.4 测试 3. 总结 1. 路由模式说明 路由模式特 ...
- [GO语言基础] 四.算术运算、逻辑运算、赋值运算、位运算及编程练习
作为网络安全初学者,会遇到采用Go语言开发的恶意样本.因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识:另一方面是分享与读者,希望大家一起进步.前文介绍了Golang的 ...
- 计算机科学与技术学习路线编程基础四大件应用实践编程(含C++学习路线)
计算机科学与技术学习路线&编程基础四大件&应用实践编程(含C++学习路线) 基本介绍 本人211科班出身,目前大学临近毕业,想给迷茫的同行者或者后来人一些建议和推荐,少走弯路.想想自己 ...
- 第十五届全国大学生智能汽车竞赛 基础四轮组总结
第十五届全国大学生智能汽车竞赛 基础四轮组总结 一.方案 循迹:纯电磁 硬件 比赛过程 二.总结 一.方案 1.车模:C1 2.主控:RT1064 3.传感器:电磁循迹.红外对管+干簧管识别斑马线 循 ...
- 《计算机应用基础》第四次作业,[业务]计算机应用基础四次小作业
[业务]计算机应用基础四次小作业 (8页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 本科专业第一次小作业辅导:课本第39页,第52页的填空 ...
- 17届智能车竞赛技术报告 | 乐师逐飞二队 - 基础四轮组
学 校:乐山师范学院 队伍名称:乐师逐飞二队 参赛队员:唐冰奇 罗文祝 唐玉琴 带队教师:杨济豪 李富钢 简 介: 本文以第十七届全国大学生智能车竞赛为背景,以大赛组委会指 ...
最新文章
- efcore多表查询出错_如何提高sql查询的效率?
- Reason not to use LINQ and reason to use
- 用python让excel飞起来 pdf_老外用100个巨型吹风机, 想要靠它们飞起来, 你猜结果怎样...
- 从零开始学Xamarin.Forms(四) Android 准备步骤(添加第三方Xamarin.Forms.Labs库)
- 每天五分钟,玩转Docker。-Day2
- 【Pytorch神经网络理论篇】 02 Pytorch快速上手(二)GPU与CPU张量切换+具有随机值的张量+张量的数学运算
- Django与jQuery通信;Django前后端传值
- How to include library manually into maven local repository?
- Java Singleton类中的线程安全性的示例代码
- 线性查找法java代码_Java线性查找和二分查找
- 人工智能/数据科学比赛汇总 2019.3
- 李国庆夺章后“发配”俞渝,当当网上线“从摔杯到抢章”专题,书目亮了
- 湖南第一师范计算机科学与技,湖南第一师范学院2019年各省各专业录取分数线...
- nlp基础—9.条件随机场模型(CRF算法)
- docker server 容器连接sql_借力 Docker ,三分钟搞定 MySQL 主从复制!
- 推荐一个下载简历模板的网站工具
- 地址后面的sessionid怎么消除_富贵包的消除和改善头前倾,通过运动和减肥可以吗?...
- 阿里云Centos8 yum报错Failed to synchronize cache for repo ‘BaseOS‘解决方案,通过换文件的方式来解决。
- 数字IC验证方法的分类
- 社群运营怎么做更有效?
热门文章
- java 计算两个时间之间的间隔
- 【Dart 教程系列第 49 篇】Dart 是值传递还是引用传递
- EXCEL将默认单元格格式修改成常规
- Encoder-Decoder -编码器解码器架构(RNN循环神经网络)
- android build.gradle在哪里,android中的build.gradle是干什么用的
- 计算机毕业设计php+vue基于微信小程序的贵小团校园社团小程序
- 简单理解CMS与G1垃圾收集器
- UNIX操作系统族谱 —— 发展脉络一览
- SqlServer数据库删除数据
- Python-turtle绘画旅程第一站:哆啦a梦