Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
rusldv
7 лет назад

Язык Solidity: Массивы и соответствия (Урок 4)

Язык Solidity: Массивы и соответствия (Урок 4)



Предыдущие уроки:


Язык Solidity: Неllo World (Урок 1)
Язык Solidity: Типы данных (Урок 2)
Язык Solidity: Переменные состояния контракта (Урок 3)


Массивы позволяют упорядоченно хранить значения одинакового типа. Это удобно, когда требуется работать с данными связанными общим признаком (например, товар, цена и т.п.). Естественно в финансовых скриптах, массивы очень важные средства для разработки. В Solidity их можно разделить на 2 типа: обычные индексные массивы и соответствия (похожи на ассоциативные массивы). Я придумал несколько простых примеров, которые показывают как работать с массивами. Сами по себе эти контракты просто хранят данные в массивах. Нам же они интересны в целях обучения.

Массив строк

Первый пример контракта, позволяет хранить строки в кодировке UTF-8 в массиве. Наподобие как это бы можно было сохранять в текстовом файле обычной операционной системы.
pragma solidity ^0.4.0;

contract Lines {
    // Массив строк
    string[] lines;
    
    // Возвращает кол-во строк
    function getLinesCount() constant returns (uint) {
        return lines.length;
    }
    
    // Добавляет строку
    // Строка должна быть в двойных кавычках ("str")
    function addLine(string s) {
        lines.push(s);
    }
    
    // Возвращает последнюю строку (pop)
    function getLastLine() constant returns (string) {
        return lines[lines.length-1];
    }
    
    // Возвращает строку по ее индексу в массиве с 0
    function getLineByIndex(uint index) constant returns (string) {
        if(index >= 0) {
            return lines[index];
        } else {
            return "empty";
        }
    }
}

string[] lines; - это и есть наш индексный массив строк.
У массивов есть члены - метод push() добавляет значение типа массива в его конец, а свойство length поваляет узнать количество элементов которые мы добавили в массив.
В нашей функции getLastLine() мы воспроизводим поведение функции pop() - обратной push().
Она возвращает последний добавленный в массив элемент (т.е с самым большим индексом): return lines[lines.length-1];.
Так как отсчет элементов в массивах начинается с 0, а при каждом добавлении значение свойства length увеличивается на 1, мы вычитаем единицу, чтобы получить правильный индекс элемента.
В функции getLineByIndex(uint index) мы также ни чего не придумываем и минимальное значение параметра index также равно 0.

Массив чисел


Числовые массивы ведут себя также как и строковые:

pragma solidity ^0.4.0;

contract Arrays {
    /* contract stat property */
    
    uint32[] nums;
    
    /* contract functions */
    
    function getNumsCount() returns (uint) {
        return nums.length;
    }
    
    // Добавляем элемент в массив
    function addNum(uint32 n) {
        nums.push(n);
    }
    
    function printNums() constant returns (uint32[]) {
        return nums;
    }
    
    function getNum(uint i) constant returns (uint32) {
        return nums[i];
    }
    
    function getLastNum() constant returns (uint32) {
        return nums[nums.length-1];
    }
}

Все что мы делаем для создания массива - ставим квадратные скобки после типа в объявлении переменной (массива).
Также в этом примере у нас появилась функция printNums(), которая выводит весь массив наших 32-битных без знаковых чисел (uint32).

Соответствие (mapping)


Соответствия похожи на массивы, но не индексные. Соответственно у них нет членов push() и length.
За то в место индекса (ключа) можно использовать значение любого из доступных типов Solidity.
Например, можно соотнести никнейм пользователя с некоторым значением (у нас это уелое беззнаковое (uint8) число.
А сам ник представлен последовательностью байтов длинной 30 байт (bytes30) (Я выбрал наугад длину). Максимальная длина bytes - 32 байта (bytes32), если бы нам понадобилась более длинная строка для ключа, нужно бы было взять за тип ключа string.

pragma solidity ^0.4.0;

contract Mapp {
    /*
        Так определяется соответствие -
        подобие ассоциативного массива
        
        первый аргумент соответствия (ключ) у нас
        имеет тип bytes30 - последовательность в 30 байт
        этого хватит для хранения ника
        этот ник соответствует заданному для него числу
    */
    mapping(bytes30 => uint8) userVal;
    
    // Определим функции для работы с нашим соответствием
    function addItem(bytes30 nick, uint8 val) {
        // Добавляются элементы в соответствие подобно массивам
        userVal[nick] = val;
    }
    
    // Получить значение по никнейму
    function getItem(bytes30 nick) constant returns (uint8) {
        return userVal[nick];
    }
}

Кстати, если вы будите эксперементировать с добавлением ключа и значения, не забудьте никнейм взять в двойные кавычки: "mynick". Иначе интерпретатор не поймет, что вы хотите передать строку и выдаст ошибку несоответствия типов.
Чем же так хороши соответствия. Дело в том, что во время транзакции контракту приходят данные состояния блока (принцип наподобие как подобные данные получает большинство ботов в Golos-е, но сами данные другие, так как блокчейн Ethereum) и в том числе там есть адрес отправителя транзакции.
Если задать ключ соответствия типа address, то мы сможем ассоциировать отправителя транзакции (адрес аккаунта - пользователя контракта) с некоторыми данными, например, с некоторым балансом.
Именно по этому принципу создаются подвалюты (контракты подвалют, банки) в блокчейне Ethereum.

Я думаю в следующем уроке следует рассмотреть структуры, так как они относятся к данным, а затем рассмотрим системные функции и переменные Ethereum, сообщающие нам всю необходимую информацию, для создания полноценного контракта.


В следующем уроке рассмотрим структуры и объединения

1611
12.518 GOLOS
На Golos с November 2016
Комментарии (17)
Сортировать по:
Сначала старые