solidity二固定长度数组动态长度数组字符串之间的转换solidity字典hash表的使用solidity——memorystorage使用注意项solidity状态变量局部变量

Posted yida&yueda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了solidity二固定长度数组动态长度数组字符串之间的转换solidity字典hash表的使用solidity——memorystorage使用注意项solidity状态变量局部变量相关的知识,希望对你有一定的参考价值。

四、 引用类型介绍

1. 不定长字节数组(bytes)

bytes -> []byte

  • 动态字节数组
  • 引用类型(表明可以使用storage来修饰,进行引用传递,指针的效果)
  • 支持下标索引
  • 支持lengthpush方法**(push会帮助分配空间的)**
  • 可以修改
  • 以十六进制格式赋值: ‘h’ -> 0x68 -> 104
  • 格外注意:对于bytes,如果不使用下标访问,那么可以不用先申请空间, 直接赋值即可,或者直接push

2. 字符串(string)

  • 动态尺寸的UTF-8编码字符串,是特殊的可变字节数组
  • 引用类型
  • 不支持下标索引
  • 不支持length、push方法
  • 可以修改(需通过bytes转换)

3. 数据位置(Data location)

复杂类型,不同于之前值类型,占的空间更大,超过256字节,因为拷贝它们占用更多的空间,如数组(arrays)数据结构(struct),他们在Solidity中有一个额外的属性,即数据的存储位置:memorystorage

- 内存(memory)

  • 数据不是永久存在的,存放在内存中,越过作用域后无法访问,等待被回收。
  • 被memory修饰的变量是直接拷贝,即与上述的值类型传递方式相同。

- 存储 (storage)

  • 数据永久保存在。
  • 被storage修饰的变量是引用传递,相当于只传地址,新旧两个变量指向同一片内存空间,效率较高,两个变量有关联,修改一个,另外一个同样被修改。
  • 只有引用类型的变量才可以显示的声明为storage

- 状态变量

状态变量总是stroage类型的,无法更改

- 局部变量

默认是storage类型(仅限数据结构或数组,string),但是可以声明为memory类型。

4. 转换(bytes1/bytes/string)

5. 数组

- 内置数组

  • string(不定长)
  • bytes(不定长)
  • bytes1…bytes32(定长)

- 自定义数组

定长数组

go numbers [10] uint

  • 类型T,长度K的数组定义为T[K],例如:uint [5] numbers, byte [10] names;
  • 内容可变
  • 长度不可变,不支持push
  • 支持length方法

不定长数组

  • 定义格式为T [ ],例如:string[ ] names, byte[ ] citys。
  • 内容可以修改
  • 可以改变长度(仅限storage类型) 支持lengthpush方法
  • memory类型的不定长数组不支持修改长度
  • 即使没有手动分配空间,直接改变长度,那么也会自动分配空间

6. 结构体

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Test 
    //定义结构之后无分号,与枚举一致
    struct Student 
        string name;
        uint age;
        uint score;
        string sex;
    

    Student[] public students;

    //两种赋值方式
    Student public stu1 = Student("lily", 18, 90, "girl");
    Student public stu2 = Student(name:"Jim", age:20, score:80, sex:"boy");

    function assign() public 
        students.push(stu1);
        students.push(stu2);

        stu1.name = "Lily";
    

7. 字典/映射/hash表(mapping)

  • 键key的类型允许除映射外的所有类型,如数组,合约,枚举,结构体,值的类型无限制。
  • 无法判断一个mapping中是否包含某个key,因为它认为每一个都存在,不存在的返回0或false。
  • 映射可以被视作为一个哈希表,在映射表中,不存储键的数据,仅仅存储它的keccak256哈希值,用来查找值时使用。
  • 映射类型,仅能用来定义状态变量,或者是在内部函数中作为storage类型的引用。
  • 不支持length
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;


contract Test 
    mapping(string => string)public id_name;
    
    function initMapping()public 
        id_name["a"] = "yida1";
        id_name["b"] = "yida2";
        id_name["c"] = "yida3";
        id_name["c"] = "yida";
    

int型动态数组总结

简单的数据结构之-int型动态数组

这个貌似没有参考可以借鉴,如果哪位有幸看到,请您给我说一下哈!再次感谢各位了!

想关的参看的资料来自某培训机构,我是参照动态数组写的

想关的介绍文章 C语言中文网:http://c.biancheng.net/cpp/html/2790.html

 

 

数组都有一个固定的长度,超出它的长度就无法再添加新的元素,但是动态数组可以动态的增加数组的长度,可以无限的插入数据。

 

 

// 动态数组是一个不存在的数据类型,所以需要定义一个结构体来说明动态数组的类型,数组需要空间存储数据,因为对初始容量什么的未知,所以需要定义一个指针(int*):

数组有自己的容量,当容量不够时,需要动态增加容量,既然有容量,那么就需要一个变量来存储数组的实际长度

 

typedef struct _INT_DYNAMICARRAY

{

    int *array;

    int arrayLen;

    int capacity;

}IntDynamicArray;

 

数组结构体,定义好了之后,还需要定义想关的操作函数,增删改查是基本数据结构的四个函数,还有初始化、打印、释放,数组的大小、容量、数据的排序,

 

动态数组的初始化:

主要功能就是对动态数据的结构体分配内存空间

 

int Init_IntDynamicArray(IntDynamicArray **Array, int Capacity)

{

    // 对传入的参数进行判断,如果为空,则终止下面的执行,没空间没法执行

    if (Array == NULL)

    {

        exit(-1);

    }

 

    // 为动态数组的结构体开辟空间

    *Array = (IntDynamicArray *)malloc(sizeof(IntDynamicArray));

    if (*Array == NULL)

    {

        exit(-2);

    }

 

    // 为(*Array)->array 开辟一段长度为 Capacity 的空间用来存储数组的数据

    (*Array)->array = (int *)malloc(sizeof(int)*Capacity);

 

    // 对开辟的空间一定要判断,这儿没有用return 的原因是开辟空间失败,后面的操作有报错的可能

    if ((*Array)->array == NULL)

        exit(-2);

   

    // 对开辟的空间赋初始值

    for (int i = 0; i < Capacity; ++i)

        (*Array)->array[i] = 0;

    // 对结构体中的关键字进行初始化

    (*Array)->arrayLen = 0;

    (*Array)->capacity = Capacity;

 

    return 0;

}

 

// 元素的插入

int Insert_IntDynamicArray(IntDynamicArray *Array, int Data,int Pos)

{

    // 对传入的参数进行检查

    if (Array == NULL)

    {

        return -1;

    }

 

    // 对传入的参数进行合理化处理

    if (Pos < 0 )

    {

        Pos = 0;

    }

    if (Pos > Array->arrayLen)

    {

        Pos = Array->arrayLen;

    }

 

    // 如果空间不够,那么开辟一段空间来存储新的数据

    if (Array->arrayLen == Array->capacity)

    {

        // 开辟两倍的空间

        int *array = (int *)malloc(sizeof(int) * 2 * Array->capacity);

        if (array == NULL)

        {

            return -2;

        }

       

        // 将原数据的元素拷贝过来,这儿也可以用循环

        memcpy(array, Array->array, sizeof(int)*Array->arrayLen);

       

        // 释放原来的空间

        free(Array->array);

 

        Array->array = array;

        Array->capacity *= 2;

 

        // 对新开辟的空间进行初始化

        for (int i = Array->arrayLen; i < Array->capacity; ++i)

        {

            array[i] = 0;

        }

    }

    // 为插入元素腾出空间

    for (int i = Array->arrayLen-1; i >= Pos; --i)

    {

        Array->array[i+1] = Array->array[i];

    }

 

    // 插入新元素

    Array->array[Pos] = Data;

 

    ++ Array->arrayLen;

 

    return 0;

}

 

// 元素的删除

int EraseByPos_IntDynamicArray(IntDynamicArray *Array, int Pos)

{

    if (Array == NULL)

    {

        return -1;

    }

    if (Pos < 0 || Pos >= Array->arrayLen)

    {

        return -2;

    }

 

    // 直接通过覆盖的方式删除

    for (int i = Pos; i < Array->arrayLen - 1; ++i)

    {

        Array->array[i] = Array->array[i + 1];

    }

 

    -- Array->arrayLen;

    return 0;

}

 

// 修改

int Modif_IntDynamicArray(IntDynamicArray *Array, int Pos, int Data)

{

    if (Array == NULL)

    {

        return -1;

    }

    if (Pos<0 || Pos>Array->arrayLen - 1)

    {

        return -2;

    }

 

    Array->array[Pos] = Data;

 

    return 0;

}

 

// 通过位置查找

int SeekByPos_IntDynamicArray(IntDynamicArray *Array, int Pos)

{

    if (Array == NULL)

    {

        return 0x00;

    }

    if(Pos<0||Pos>Array->arrayLen-1)

    {

        return 0x01;

    }

    return Array->array[Pos];

}

 

// 查找第一次出现某值的位置

int SeekByVal_IntDynamicArray(IntDynamicArray *Array, int Val)

{

    if (Array == NULL)

    {

        return 0x00;

    }

    for (int i = 0; i < Array->arrayLen; ++i)

    {

        if (Array->array[i] == Val)

            return i;

    }

    return -1;

}

 

// 打印动态数组

void Print_IntDynamicArray(IntDynamicArray *Array)

{

    if (Array == NULL)

    {

        return;

    }

    for (int i = 0; i < Array->arrayLen; ++i)

    {

        printf("%d ", Array->array[i]);

    }

    printf("\n");

}

 

 

// 数组长度

int Size_IntDynamicArray(IntDynamicArray *Array)

{

    if (Array == NULL)

    {

        return -1;

    }

    return Array->arrayLen;

}

 

 

// 数组容量

int Capacity_IntDynamicArray(IntDynamicArray *Array)

{

    if (Array == NULL)

    {

        return -1;

    }

    return Array->capacity;

}

 

// 销毁

int Destroy_IntDynamicArray(IntDynamicArray *Array)

{

    if (Array == NULL)

    {

        return -1;

    }

    if (Array->array != NULL)

    {

        free(Array->array);

    }

 

    free(Array);

 

    return 0;

}

 

呵呵!结束了!

 

以上是关于solidity二固定长度数组动态长度数组字符串之间的转换solidity字典hash表的使用solidity——memorystorage使用注意项solidity状态变量局部变量的主要内容,如果未能解决你的问题,请参考以下文章

Solidity极简入门#6. 引用类型

int型动态数组总结

Solidity语言详解

Solidity语言详解

Golang数据类型之数组

Go语言基础之数组