solidity二固定长度数组动态长度数组字符串之间的转换solidity字典hash表的使用solidity——memorystorage使用注意项solidity状态变量局部变量
Posted yida&yueda
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了solidity二固定长度数组动态长度数组字符串之间的转换solidity字典hash表的使用solidity——memorystorage使用注意项solidity状态变量局部变量相关的知识,希望对你有一定的参考价值。
四、 引用类型介绍
1. 不定长字节数组(bytes)
bytes -> []byte
- 动态字节数组
- 引用类型(表明可以使用
storage
来修饰,进行引用传递,指针的效果) - 支持
下标索引
- 支持
length
、push
方法**(push会帮助分配空间的)** - 可以修改
- 以十六进制格式赋值: ‘h’ -> 0x68 -> 104
- 格外注意:对于bytes,如果不使用下标访问,那么可以不用先申请空间, 直接赋值即可,或者直接push
2. 字符串(string)
- 动态尺寸的UTF-8编码字符串,是特殊的可变字节数组
- 引用类型
- 不支持下标索引
- 不支持length、push方法
- 可以修改(需通过bytes转换)
3. 数据位置(Data location)
复杂类型,不同于之前值类型
,占的空间更大,超过256字节,因为拷贝它们占用更多的空间,如数组(arrays)
和数据结构(struct)
,他们在Solidity中有一个额外的属性,即数据的存储位置:memory
和storage
。
- 内存(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类型) 支持
length
、push
方法 - 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状态变量局部变量的主要内容,如果未能解决你的问题,请参考以下文章