彩世界开奖app官网-彩世界平台官方网址(彩票平台)
做最好的网站
来自 计算机编程 2019-12-07 01:30 的文章
当前位置: 彩世界开奖app官网 > 计算机编程 > 正文

【Solidity智能合约系列】04--数组【彩世界开奖a

彩世界开奖app官网 1

Reader和Writer和上面的InputStream和OutStream很类似,只不过他们读写的单位是字符,并且提供几个方法读写String的方法。
3.  所有流类都直接或间接继承自上面4个抽象类,并提供不同的功能,下面是常用流类的继承关系:
InputStream
    |-ByteArrayInputStream: 字节输入流。
    |-FileInputStream: 文件输入流
    |-ObjectInputStream: 对象输入流
    |-PipedInputStream: 管道输入流
    |-FilterInputStream: 过滤输入流
        |-BufferedInputStream: 缓存输入流,读出时先缓存。
        |-DataInputStream: 数据输入流,读出Java基本数据类型。
OutStream
    |-ByteArrayOutputStream: 字节输出流
    |-FileOutputStream: 文件输出流
    |-ObjectOutputStream: 对象输出流
    |-PipedOutputStream: 管道输出流
    |-FilterOutputStream: 过滤输出流
        |-BufferedOutputStream: 缓存输入流,读出时先缓存。
        |-DataOutputStream: 数据输入流,读出Java基本数据类型。
Reader
    |-CharArrayReader: 字符读流。
    |-StringReader: 字符串读流。
    |-PipedReader: 管道读流。
    |-BufferedReader: 缓存读流。
    |-InputStreamReader: 从字节流读出字符。
Writer
    |-CharArrayWriter: 字符写流。
    |-StringWriter: 字符串写流。
    |-PipedWriter: 管道写流。
    |-BufferedWriter: 缓存写流。
    |-OutputStreamWriter: 将字符写入字节流。

类型为数组的状态变量,可以标记为public,从而让Solidity创建一个访问器getter,可以通过索引的方式来访问数组的某个元素。

2.数组大小为什么要自动调整为2的n次方?

  从流中读出多个字节,并存到数组b中;期望读出的字节数由len决定,off指定b的偏移,数据将从这个偏移开始保存;方法返回实际读出的字节,如果已到达结尾将返回-1。
public void mark(int readlimit) 标记一个位置,当下一次调用reset时,Pos将被定位到这个位置。
public void reset() 重置Pos到上一次mark指定的位置,默认为0.
public boolean markSupported() 是否支持标记
public long skip(long n) 从Pos跳过n个字节,相当于Pos = n。
public void close() 关闭流以释放相关的系统资源,比如文件流,但并不是所有的流类都需要Close。
public int available() 还有多少字节可以读取,相当于: Size - Pos

数组可以声明时指定大小,也可以是动态变长。对于storage存储的数组来说,元素类型可以是任意的(可以是数组,map,结构体)。对于memory存储的数组,如果作为public函数的参数,它不能是map类型的数组,只能是支持ABI的类型。

适用于:

1.  java通过流的概念来实现数据的输入输出,或叫读写更容易理解一些;下面4个类是所有流的基类,分别处理字节和字符的读写:
InputStream: 输入(读)字节流抽象类。
OutputStream: 输出(写)字节流抽象类。
Reader: 输入(读)字符流抽象类。
Writer: 输出(写)字符流抽象类。
2.  上面4个抽象类提供了最基本的读写方法,输入输出流有一个当前位置(Pos)的概念,指定下一次的读写将从流的什么位置开始,调用Read或Write方法时,Pos会同时向后移,移多少依读写多少字节或多少字符而定:

一个数组,固定大小为k,元素类型为T,可以声明为T[k],如果数组大小是动态的,可以声明为T[]。如声明一个类型为uint的数组长度为5的变长数组(5个元素都是变长数组),可以声明为uint[][5]。(注意,相比其他语言,solidity多维数组的长度声明是反的。)要访问第三个动态数组的第二个元素,使用x[2][1](数组的索引是从0开始的,访问数组元素的顺序与声明时相反)。

        static void Main(string[] args)
        {
            Buffer<int> buffer = new Buffer<int>(10);
            var taskWrite = Task.Factory.StartNew(() =>
            {

                for (int i = 0; i < 20; i  )
                {
                    buffer.Write(i);
                    Console.WriteLine($"Write:i={i}");
                    Task.Delay(300).Wait();
                }
            });
            var taskRead = Task.Factory.StartNew(() =>
            {
                for (int i = 0; i < 7; i  )
                {
                    Console.WriteLine("Read:"   string.Join(",", buffer.Read()));
                    Task.Delay(1000).Wait();
                }
            });
            Task.WaitAll(taskWrite, taskRead);
        }
    }

OutStream:
方法 说明
public abstract void write(int b) 向流写一个字节
public void write(byte[] b) 向流写多个字节
public void write(byte[] b, int off, int len) 向流写多个字节,从数组的off偏移开始写,最多写len个字节。
public void close() 关闭流以释放相关的系统资源,比如文件流,但并不是所有的流类都需要Close。
public void flush() 刷新流,提供这个方法意图是:如果流的实现是将之前写入的数据缓存着,调用该方法可以强迫将数据真正写入流中。

已经计划在未来移除这样的限制。当前因为ABI传递数组还有些问题。

利用byte的这个特点,写的时候 ,读的时候--,不用考虑边界,是不是比较方便。

InpuStream:
方法 说明
public abstract int read() 从流中读下一个字节,方法返回这个字节,但如果到达流结尾,将返回回-1。
public int read(byte[] b) 从流中读出多个字节,并存到数组b中;期望读出的字节数由数组的长度决定,方法返回的是实际读出的字节,如果已到达结尾将返回-1。
public int read(byte[] b, int off, int len)

contract C { function f() returns  { ... } }

pragma solidity ^0.4.16;contract ArrayContract { uint[2**20] m_aLotOfIntegers; // 这里不是两个动态数组的数组,而是一个动态数组里,每个元素是长度为二的数组。 bool[2][] m_pairsOfFlags; // newPairs 存在 memory里,因为是函数参数 function setAllFlagPairs(bool[2][] newPairs) public { m_pairsOfFlags = newPairs; } function setFlagPair(uint index, bool flagA, bool flagB) public { // 访问不存在的index会抛出异常 m_pairsOfFlags[index][0] = flagA; m_pairsOfFlags[index][1] = flagB; } function changeFlagArraySize(uint newSize) public { // 如果新size更小, 移除的元素会被销毁 m_pairsOfFlags.length = newSize; } function clear() public { // 销毁 delete m_pairsOfFlags; delete m_aLotOfIntegers; // 同销毁一样的效果 m_pairsOfFlags.length = 0; } bytes m_byteData; function byteArrays(bytes data) public { // byte arrays  are different as they are stored without padding, // but can be treated identical to "uint8[]" m_byteData = data; m_byteData.length  = 7; m_byteData[3] = byte; delete m_byteData[2]; } function addFlag(bool[2] flag) public returns  { return m_pairsOfFlags.push; } function createMemoryArray(uint size) public pure returns  { // Dynamic memory arrays are created using `new`: uint[2][] memory arrayOfPairs = new uint[2][]; // Create a dynamic byte array: bytes memory b = new bytes; for (uint i = 0; i < b.length; i  ) b[i] = byte; return b; }}

有时候需要把最新的N条记录暂时存起来供需要的时候调用,C#有没有指针,怎么办呢咱利用数组和byte字节整一个类:

可使用new关键字创建一个memory的数组。与stroage数组不同的是,你不能通过.length来修改数组大小。

1.byte _Index=0;

bytesstring是特殊的数组。bytesbyte[]是类似的,但在外部函数作为参数调用中,bytes会进行压缩打包。stringbytes类似,但是不允许长度索引的方式访问。

当然可以>255,只要把_Index的类型改为uint16,uint32或者uint64,那大小分别是0xFFFF,0xFFFFFFFF和0xFFFFFFFFFFFFFFFF,但是这么大有用吗?还叫缓存吗?

警告:在external函数中,不能使用多维数组

结果:

数组常量是一个固定大小的memory数组,元素类型则是使用刚好能存储的元素的能用类型,比如[1, 2, 3],只需要uint8即可存储,因为这几个元素的类型都是uint8。它的类型是uint8[3] memory。

1.小缓存,<=255

目前唯一的解决办法是使用一个非常大的静态数组。

 解释一下:

pragma solidity ^0.4.16;contract C { function f public pure { uint[] memory a = new uint[]; bytes memory b = new bytes; // Here we have a.length == 7 and b.length == len a[6] = 8; //错误,编译不通过 // a.length = 10; }}

2.单线程读单线程写操作

pragma solidity ^0.4.16;contract C { function f() public pure { //编译不通过 //g([1, 2, 3]); g, 2, 3]); } function g(uint[3] _data) public pure { // ... }}

 

注意:如果你想访问字符串的某一个字节,你可以通过bytes.length / bytes[7] = 'x';的方式来访问。记住,你访问的是UTF-8表示的低级别的字节,而不是独立的字符。这句话有点绕,我尝试用自己的理解解释一下。可以将字符串s通过bytes转为一个bytes,可以通过bytes.length获取长度,bytes[n]获取对应的UTF-8编码。通过下标访问获取到的不是对应字符,而是UTF-8编码,比如中文编码是多字节,变长的,所以下标访问到的只是其中的一个编码。

 

数组常量,是一个还没有赋值到变量的数组表达式。

那是因为只有2的n次方的时候,(0xFF % _Capcity)==_Capcity-1,才能实现数组的遍历。

参考:

测试一下,调用的代码如下:

因此,优先使用bytes而不是byte[],因为bytes更节省内存。

    public class Buffer<T>
    {
        private T[] _TS;
        private byte _Index = 0;
        private int _Capcity;
        public Buffer(int capcity)
        {
            //将数组的大小设置成2的n次方
            while ((capcity & capcity - 1) != 0)
                capcity  ;
            _TS = new T[capcity];
            _Capcity = capcity;
        }
        public void Write(T t)
        {
            _TS[_Index % _Capcity] = t;
            _Index  ;
        }

        public IEnumerable<T> Read()
        {
            byte index = _Index;
            for (int i = 0; i < _TS.Count(); i  )
            {
                index--;
                yield return _TS[index % _Capcity];
            }
        }
    }

由于g()方法的参数需要的是uint(uint表示的是uint256),所以需要对第一个元素进行类型转换,使用uint来进行这个转换。注意:定长的memory数组是不能和变长的memory数组之间相互赋值的。

 

// 不能编译通过pragma solidity ^0.4.0;contract C { function f() public { // The next line creates a type error because uint[3] memory // cannot be converted to uint[] memory. uint[] memory x = [uint, 3, 4]; }}

_Index--; //=0xff

length:数组有一个.length属性,表示当前的数组长度。storage的变长数组(memory不可以),可以通过给.length赋值调整数组长度。memory的变长数组不支持。不能通过访问超出当前数组的长度的方式,来自动实现改变数组长度。memory数组虽然可以通过参数,灵活指定大小,但一旦创建,大小不可调整。push:变长的storage数组和bytes都有一个成员方法push(),用于在数组的末尾添加一个新元素,返回值为新的长度。pop:变长的storage数组和bytes都有一个成员方法push(),用于移除数组末尾的元素。

_Index ;//=0

基于EVM的限制,不能通过external函数返回动态的内容。在下面这个的例子中,如果通过web3.js调用能返回数据,但从Solidity中调用不能返回数据。

本文由彩世界开奖app官网发布于计算机编程,转载请注明出处:【Solidity智能合约系列】04--数组【彩世界开奖a

关键词: java 语言 程序开发 软件开发