Введение в массивы
 
Автор rdc

Массивы, вероятно, одни из наиболее полезных конструкций программирования, которые доступны для вас в FreeBasic. Многие проблемы, которые вы будете пытаться решить с помощью программирования - это решения включать данные в табличном формате и массивы идеально подходят для управления этого типа данных. Понимание массивов является одним из важнейших навыков , чтобы стать компетентным программистом.

Массивы являются непрерывным сегментом данных в памяти одного или составного типа. Вы можете думать о массиве как о таблице из строк и столбцов данных. Массив может иметь одну или несколько строк, и каждая строка может содержать один или более столбцов. Количество строк и столбцов определяют размеры массива. FreeBasic использует строковую схему для массивов, что означает, что первое измерение ссылается на строку в виде массива, который имеет более одного измерения. FreeBasic поддерживает до восьми измерений в массиве.

Одномерные массивы


Массив с одной строкой называется одномерным массивом. Если массив является одномерным, то строка не определена в декларации, только количество столбцов в строке. Поскольку массив требует минимум один ряд, то ряд понимается в этом случае как существующий. Следующие фрагменты кода создают целочисленный одномерный массив, используя различные схемы определения массива, доступные в FreeBASIC.

Dim myArray(10) As Integer

Dim myArray(1 To 10) As Integer


Первый метод будет определять массив с одной строкой и 11 столбцами, с индексами (номерами) от 0 до 10. Второй метод определяет нижнюю и верхнюю границы, с использованием ключевого слова To. Здесь индексы будут варьироваться от 1 до 10.

Индексы одномерного массива


Для доступа к каждому элементу массива используется значение индекса. В случае одномерного массива, индекс будет относиться к номеру столбца в строке по умолчанию. Формат использования переменной массива с индексом заставляет окружать скобками.

myArray(5) = 7


Это создаст в столбце 5 массива значение 7.

myInt = myArray(5)


Это установит переменную myInt значением из столбца 5 массива  myArray.

Двумерные массивы


Двумерный массив представляет собой массив, имеющий более одной строки, а также определенных столбцов. Двумерный массив, как таблица, с определенным количеством строк, где каждая строка содержит определенное количество столбцов. В следующем фрагменте кода определяется массив с помощью метода по умолчанию.

Dim myArray(2, 10) As Integer


Первое измерение определяет количество строк в массиве, в то время как второе измерение определяет количество столбцов в каждой строке. В этом примере массив имеет 3 строки, под номером 0-2, и каждая строка состоит из 11 столбцов, пронумерованных от 0 до 10.

Вы также можете определять нижние и верхние границы массива.

Dim myArray(1 To 2, 1 To 10) As Integer


Это определение задаст 2 строки, пронумерованных от 1 до 2 и 10 столбцов , пронумерованных 1 до 10.

Индексы двумерного массива


Чтобы получить доступ к элементам массива из двумерного массива, вы должны использовать два индекса. Первый индекс выбирает строку, а второй индекс выбирает столбец в пределах этой строки.

myArray(1, 5) = 7


Этот код устанавливает 5 столбец 1 строки значением 7.

myInt = myArray(1, 5)


Этот код установит переменную myInt значением из 5 столбца 1 строки массива.

Многомерные массивы


Для массивов из трех или более измерений используется тот же формат, что перечислен выше, принимая во внимание прогрессирование размерности массива. Для трехмерного массива, первое измерение будет строка, второе столбец, третье будет z-порядок, или глубина, каждого столбца.

Например, чтобы определить куб в пространстве, вы должны использовать Y, X, Z формат, где Y определяет вертикальную ось, X определяет горизонтальная ось и Z определяет ось глубины. Чтобы создать массив в этом формате, можно определить массив так:

Dim myCube(y, x, z) As Integer. 


MyCube(10, 10, 10) создаст куб с 11 вертикальных блоков, от 0 до 10, 11 горизонтальных блоков, от 0 до 10 и 11 единиц глубины, от 0 до 10. Чтобы получить доступ к центру куба, вы должны использовать iCenter = myCube(5, 5, 5).

Вероятно вам никогда не потребуется использовать массивы более трех измерений, если конечно вы не делаете некоторые передовые математические расчеты. Однако, если вам нужно использовать многомерные массивы, те же принципы применяются.

Динамические массивы


Массивы, описанные выше, являются статическими массивами; размер массива не может изменяться в ходе выполнения программы. Но вы также можете создавать динамические массивы, которые могут изменить размер во время выполнения. Динамические массивы могут использоваться для создания таких структур данных, как стеки или очереди.

Статические массивы, описанные выше, хранятся в куче, но динамические массивы выделяются из пула компьютерной памяти. Компилятор динамически выделяет память для массива на основе запрошенных измерений массива.

Вы указываете динамический массив с помощью ключевого слова ReDim.

ReDim myArray(1 To 5, 1 To 5) As Integer


Если вам неизвестны необходимые границы массива на старте выполнение программы, вы можете определить массив с пустыми индексами.

Dim myArray() As Integer


В этом случае компилятор устанавливает значение по умолчанию 0 для размера массива. Затем вы можете использовать ReDim в какой-то момент в программе, чтобы установить границы массива.

ReDim и ReDim Preserve


Динамические массивы могут изменять размеры во время выполнения. ReDim очистит содержимое массива в значения по умолчанию, в то время как ReDim Preserve будет держать неповрежденным существующее содержимое, если размер массива не меньше предыдущего размера.

Функции массива


Есть целый ряд функций, которые вы можете использовать с массивами.

Массивы составных типов


Определения типов позволяют группировать данные, связанные в единое целое, и часто вам нужно больше, чем один экземпляр типа , чтобы в полной мере выразить данные. Массивы типов позволяют создать несколько экземпляров определения типа, которые могут быть легко управляться с помощью функций массивов. Примером такого использования может быть система инвентаря для вашего RPG, серия описаний документов в редакторе, и набор записей сотрудников из базы данных с произвольным доступом.

Вы создаете массивы типов так же, как и при работе с любым из встроенных типов данных. Следующий фрагмент кода иллюстрирует синтаксис.

Type myPoint
    row As Integer
    col As Integer
End Type

Type myLine
    p1 As myPoint
    p2 As myPoint
    char As String * 1
End Type

Dim myLineSet (1 To 3) As myLine


Код определяет набор из 3 линий, с конечными точками p1 и p2, где каждая конечная точка находится в row и col. Чтобы получить доступ к элементам массива, используется комбинацию оператора индекса и оператора точки

myLineSet(1).p1.row = 1
myLineSet(1).p1.col = 1
myLineSet(1).p2.row = 10
myLineSet(1).p2.col = 10
myLineSet(1).char = Chr(219)


Массивы в типах


Вы не только можете создать массив из составного типа, но так же вы можете иметь массив как поле в составном типе. Приведенный выше пример можно записать более эффективно путем замены p1 и p2 массивом.

Type myPoint
    row As Integer
    col As Integer
End Type

Type myLine
    pts(1 To 2) As myPoint
    char As String * 1
End Type

Dim myLineSet (1 To 3) As myLine


Здесь pts представляет собой массив myPoint. Для доступа к этой структуре будет использоваться комбинация индексов и оператора точки.

myLineSet(1).pts(1).row = 1
myLineSet(1).pts(1).col = 1
myLineSet(1).pts(2).row = 10
myLineSet(1).pts(2).col = 10
myLineSet(1).char = Chr(219)


myLineSet является массивом, поэтому можно использовать значение индекса. pts является элементом типа, так что вам нужно квалифицировать его с помощью оператора точка. Однако, pts также является массивом, поэтому можно использовать индекс, чтобы выбрать каждый элемент массива pts. Row и col являются элементами типа myPoint и доступны с помощью оператора точка.

Использование массива для конечных точек позволяет легко расширить определение линии для поддержки не только строк, но треугольников и квадратов. В следующем фрагменте кода показан одно из возможных определений.

Type myObj
    objid As Integer
    Union
            myLine(1 To 2) As myPoint
        myTriangle(1 To 3) As myPoint
        mySquare(1 To 4) As myPoint
    End Union
    char As String * 1
End Type


objid поле будет означать, какой тип объекта содержится в определении Union. То есть,  1 может указывать на линии,  2 может указывать на треугольник и 3 может указывать на квадрат. Поскольку определение определяет один объект, Union используется для упаковки массивов конечных точек, чтобы оптимизировать использование памяти.

Чтобы напечатать объект на экране, нужно изучать objid и затем использовать Lbound и Ubound на соответствующей конечной точке определения массива, а затем печатать количество линий, которые соответствуют типу объекта.

Одно дальнейшее расширение вы можете сделать в этой программе, путем добавления указателя функции в определении типа, а затем написать подпрограмму печати, которая соответствуют типу печатаемого объекта. С помощью этой методики вы можете увеличить полезность кода, путем упрощения процесса добавления новых объектов к определению типа.

Например, если вам нужно описать куб, вы просто добавите новый массив в Union, добавите функцию печати куба и определение типа сможет напечатать куб, просто добавив несколько строк кода , сохраняя при этом первоначальную функциональность без изменений.

Инициализация массива


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

Dim aArray(1 To 5) As Integer => {1, 2, 3, 4, 5}


Этот фрагмент кода создает целочисленный массив с 5 элементами, затем устанавливает элементы в список, содержащейся в фигурных скобках. Оператор стрелка => сообщает компилятору, что список после Dim  следует использовать для инициализации массива.

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

Dim bArray(1 To 2, 1 To 5) As Integer => {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10}}


В этом примере первый блок, {1, 2, 3, 4, 5}, соответствует строке 1, а второй блок, {6, 7, 8, 9, 10}, соответствует строке 2. Помните, что массивы FreeBASIC определяются в row-major порядке, так что строка указывается перед столбцом. При инициализации массива таким образом, вы должны быть уверены, что количество элементов впишется в массиве.

Инициализация массива типов


Вы можете не только инициализировать массив простых типов данных, но так же вы можете инициализировать массив с составными типами. Следующий фрагмент кода иллюстрирует массив типов, содержащую массив в качестве элемента типа.

Type aType
    a As Integer
    b As Byte
    c(1 To 2) As String * 10
End Type

Dim As aType myType(1 To 2) => { (1234, 12, {"Hello", "World"}), (5678, 24, {"From", "Freebasic"})} 


Фигурные скобки означают инициализацию массива, а круглые скобки указывают на инициализацию типа. Поскольку тип имеет встроенный массив, можно использовать фигурные скобки, чтобы загрузить данные во встроенный массив, так же, как в обычный массив. Если встроенный массив является многомерным, то вам нужно будет обернуть каждую строку в {и} так же, как у обычных массивов.

Использование опции компилятора -exx


Ключ компилятора -exx позволяет определять ошибки, связанные с нарушением границ массива в пределах вашей программы. Если вы выйдете за пределы массива в пределах вашей программы, компилятор будет генерировать ошибку: "out of bounds" при работе программы.

Это большая помощь в отладке вашей программы, и поиске проблем связанных с массивами. -exx также проинформирует вас о Null указателях, поэтому это весьма полезная опция.

С помощью -exx добавляется дополнительный код в программу, так что после того, как вы будете уверены, что ваша программа работает правильно, вы можете скомпилировать программу без параметра -exx.