Solidity基础四

news2024/11/27 6:30:16

あなたもきっと、誰かの奇跡 (你也一定会是某个人的奇迹)

目录

一、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;//重置枚举变量
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/577756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jmeter下载安装---Windows系统

Jmeter下载安装---Windows系统 jmeter是什么Jmeter下载安装安装jmeter前置必须jdk8Jmeter下载 jmeter插件环境变量配置 jmeter是什么 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具,用于对软件做压力测试;在接口及性能测试中广泛使用&…

如何使用JQuery实现Js二级联动和三级联动

前言:使用JQuery封装好的js方法来实现二级三级联动要比直接使用js来实现二级三级联动要简洁很多。所以说JQuery是个非常强大的、简单易用的、兼容性好的JavaScript库,已经成为前端开发人员不可缺少的一部分,是Web开发中最流行的JavaScript库之…

《Spring Guides系列学习》guide61 - guide65

要想全面快速学习Spring的内容,最好的方法肯定是先去Spring官网去查阅文档,在Spring官网中找到了适合新手了解的官网Guides,一共68篇,打算全部过一遍,能尽量全面的了解Spring框架的每个特性和功能。 接着上篇看过的gui…

mybatisplus递归传递多个参数 | mybatisplus传递多个参数获取层级数据 | mybatisplus传递多个参数获取树形数据

搜索关键字: mybatisplus关联查询传递参数|"select""树形结构"|"select""树形结构""传参"| "select""many""传参"| "select""column""传参" 1、…

chatgpt赋能python:用Python自动操作其他软件优化你的SEO

用Python自动操作其他软件优化你的SEO 作为一名有着10年Python编程经验的工程师,我了解到Python具有强大的自动化功能,可以帮助我们自动化执行任务,节省时间和精力。其中,自动操作其他软件应用案例极为常见,如此&…

C#自定义控件:提示未将对象引用设置到对象实例

一、概述 1、当自定义的控件在添加的时候提示:提示未将对象引用设置到对象实例;如下所示: 2、添加上的自定义控件提示:未将对象引用设置到对象实例;如下所示: 二、问题分析 分析1: 在项目中使…

关于“烫烫烫烫烫烫烫”的程序员笑话

环境 Microsoft Visual Studio Community 2022Windows 11 家庭中文版 笑话 小明在超市买了3瓶汽水,他先打开第0瓶汽水,咕咚咕咚喝光了,接着打开第1瓶汽水,又咕咚咕咚喝光了,然后又打开第2瓶汽水,咕咚咕咚…

运维实用脚本整理

运维实用脚本整理 Linux运维日常巡检脚本系统指标巡检脚本日常命令性能相关的命令进程相关的命令javadump.sh 常用工具一键部署安装常用lib库安装系统检查脚本SPN 日常巡查脚本ffmpeg脚本打开进程,并判断进程数量关闭进程 java jar包启动-剔除Pom中依赖Java jar包通…

SAP QM 检验批上的‘容器数’

近期遇到一个问题。项目上质量部门发现某个原料批次收货打印出来的样品标签数不对。经查发现收货后触发的检验批上的‘容器数’(No.Containers)为999,实际上此次收货的箱数有1500多。 对于栏位‘容器数’,SAP的官方帮助文档&#…

指针 --- C语言

目录 1.指针是什么 2.指针和指针类型 3.野指针 4.指针运算 5.指针和数组 6.二级指针 7.指针数组 1.指针是什么 为了更好地管理内存,把内存分为了1个个小小的内存单元,大小是一个字节,每个字节给一个编号,内存的编号就是地…

《Spring Guides系列学习》guide56 - guide60

要想全面快速学习Spring的内容,最好的方法肯定是先去Spring官网去查阅文档,在Spring官网中找到了适合新手了解的官网Guides,一共68篇,打算全部过一遍,能尽量全面的了解Spring框架的每个特性和功能。 接着上篇看过的gu…

Entity Framework Core 简明教程(3)- 关系处理

在数据库层面,表之间关系,通过主键、外键来实现,基于约束 (constraint) 和数据完整性来制约。 在 EF Core 技术层面,并不是简单地与数据库这些关系和约束对应,EF Core 有它自己的机制。本篇介绍 EF core 在处理表关系方…

HTML+CSS实训——Day03——仿网易云音乐的发现页界面

仓库链接:https://github.com/MengFanjun020906/HTML_SX 一些今天需要用到的知识点 弹性盒子 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedg…

二次元的登录界面

今天还是继续坚持写博客&#xff0c;然后今天给大家带来比较具有二次元风格的登录界面&#xff0c;也只是用html和css来写的&#xff0c;大家可以来看看&#xff01; 个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大一在校生&#xff0c;web前端开发专业 &…

[acwing周赛复盘] 第 105 场周赛20230527

[acwing周赛复盘] 第 105 场周赛20230527 总结5029. 极值数量1. 题目描述2. 思路分析3. 代码实现 5030. 核心元素1. 题目描述2. 思路分析3. 代码实现 5031. 矩阵扩张1. 题目描述2. 思路分析3. 代码实现 六、参考链接 总结 又是笨比的一周&#xff0c;只做出1题。T1 模拟T2 计…

leetcode刷题之链表相关问题(js)

21.合并两个有序链表 var mergeTwoLists function(list1, list2) {if(list1null) return list2if(list2null) return list1let newHead new ListNode(0,null) //创建一个虚拟节点let cur newHeadlet cur1 list1,cur2 list2while(cur1&&cur2){if(cur1.val<cur2.…

PowerToys Windows 工具集

Microsoft PowerToys | Microsoft Learn Microsoft PowerToys&#xff1a;用于自定义 Windows 的实用工具 项目2023/04/1918 个参与者 反馈 Microsoft PowerToys 是一组实用工具&#xff0c;可帮助高级用户调整和简化其 Windows 体验&#xff0c;从而提高工作效率。 安装 …

Unity之效应器

主要作用&#xff1a;在一个区域内让游戏对象受到力和扭矩力的作用 1、创建一个精灵&#xff08;绿色区域&#xff09; 2、为其添加碰撞器&#xff08;要将Used By Effector和is Trigger打钩&#xff09; 3、添加效应器组件 4、区域效应器参数 Use Collider Mask&#xff1a;…

第3章 Class and Object

构造函数 Guaranteed initialization with the constructor使用构造函数保证初始化 • If a class has a constructor, the compiler automatically calls that constructor at the point an object is created, before client programmers can get their hands on the o…

Solidity基础五

暂时的一事无成也代表将来万事皆有可能&#xff01; 目录 一、对Solidity文件的理解 二、Solidity的导sol文件&#xff08;库、合约&#xff09; 三、Solidity的继承 1.继承的分类 2.继承的可见性 3.父合约构造函数的传参 4.调用父合约成员 5.重写 四、Solidity的抽象…