Учебный центр "ANIT Texno Inform"
Опубликован: 25.06.2014 | Доступ: свободный | Студентов: 2597 / 852 | Длительность: 24:39:00
Специальности: Программист
Лекция 12:

Массивы простые, многомерные и динамические

< Лекция 11 || Лекция 12: 123 || Лекция 13 >
Аннотация: Лекция посвящена изучению массивов. Подробно рассматриваются простые, многомерные и динамические массивы, а также функции для работы с ними. Материал подкрепляется практическими примерами.

Цель лекции

Изучение простых, многомерных и динамических массивов.

Массив

В практике программирования нередко возникает необходимость обработать большое количество однотипных данных. Допустим, распределить недельную прибыль кафе по дням. Что для этого нужно? Использовать переменные типа currency, как раз для таких случаев и применяемые. И сколько переменных нам нужно? Ну, ясен вопрос - по переменной на день, всего семь штук. Давайте посмотрим, как такую задачу можно было бы решить на Lazarus (пример академический, выполнять его не нужно):

var
   day1, day2, day3, day4, day5, day6, day7: currency;
    

Довольно длинное объявление получилось, правда? А если бы нужно было посчитать не недельную прибыль, а месячную? Или годовую? Теперь предположим, что нам нужно посчитать сумму этой прибыли. Это выглядело бы примерно так:

pribil:= day1 + day2 + day3 + day4 + day5 + day6 + day7;
    

А если бы пришлось считать месячную или годовую прибыль? Какой длины оператор тогда бы получился? А ведь часто бывают и более сложные расчеты, которые требуется провести с каждой однотипной переменной.

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

Массив - это формальное объединение нескольких однотипных переменных в единый набор, с одним общим именем.

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

var
   a: array[1..7] of currency;
    

Ключевое слово array указывает, что это будет массив. Числа в квадратных скобках разделяются двумя точками и обозначают диапазон индексов. Так, [1..7] означает, что индексы массива будут от 1 до 7, то есть, 7 штук. После ключевого слова of указывается тип массива, такой же тип будет и у каждого элемента массива. В результате, компилятор создает в оперативной памяти семь ячеек по 8 байт каждая (тип currency занимает 8 байт):

Размещение элементов массива a в памяти

Рис. 13.1. Размещение элементов массива a в памяти

Тип данных, используемый в массивах, так же может быть любым. Во многих других языках программирования диапазон индексов всегда начинается с 0. В языках, основанных на Паскале, диапазон может начинаться с любой цифры: с 0, 1, или 438, если вам так нравится. Хотя программисты обычно начинают диапазон либо с 0, либо с 1, в зависимости от обстоятельств. Пример объявления различных массивов:

var
   name: array[0..30] of string;
   year: array[1..2013] of integer;
   man: array[10..25] of boolean'
    

Хорошо, массивы мы объявили. Что с ними делать дальше? Мы можем обратиться к любому элементу массива, указав после имени в квадратных скобках индекс этого элемента. Так, мы можем присвоить значение элементу или получить его значение. Другими словами, мы можем обращаться с элементами массива, как с отдельными переменными. Примеры:

…
a[1]:= 3520.45;
a[2]:= a[1] + 12.4;
ShowMessage('Прибыль за пятницу составила  ' + FloatToStr(a[5]));
…
    

Ну, ладно, мы научились создавать и использовать массивы. Но какие же преимущества у массивов в отличие от простых однотипных переменных? О первом таком преимуществе мы уже говорили, вот как просто можно объявить массив с элементами, рассчитанными на год:

var
   a: array[1..365] of currency;
    

Попробуйте-ка объявить 365 отдельных переменных! Второе преимущество гораздо важней: обрабатывать элементы массива намного проще, чем отдельные переменные. Например, нам нужно создать программу, которая бы могла сделать перевод температур из привычных нам Цельсиев в непривычные американские Фаренгейты. И пусть диапазон возможных температур будет от -100 градусов до +200. Идея такова: пользователь вводит нужную температуру, а программа выводит результат на экран. Конечно, проще было бы делать нужный расчет в момент, когда пользователь введет свои данные, и нажмет кнопку "рассчитать". Но мы поступим по-другому: мы сначала сделаем все расчеты и поместим результаты в массив, а затем будем просто выводить нужные данные. Массив сделаем глобальным, чтобы заполнять его в одном событии, а выводить данные в другом. Открываем Lazarus с новым проектом, сохраняем его сразу в папку 13-01 там, где у нас хранятся все учебные проекты. Проект сохраним под именем MyTemp, а модуль главной формы, как обычно - Main. Займемся главной формой, измените у нее следующие параметры:

  • Name = fMain
  • Caption = Перевод температурных шкал
  • BorderStyle = bsDialog
  • Position = poMainFormCenter

Далее, перейдите на вкладку Additional Палитры компонентов, найдите и установите на форму компонент TStaticText, который предназначен для вывода на экран пояснительного текста, в том числе и многострочного. Если вы забыли, то найти нужный компонент просто: нужно просто подвести указатель мыши к компоненту, и через короткое время появится всплывающая подсказка с именем компонента.

В принципе, для этих целей можно использовать и простую метку TLabel, но было бы интересней познакомиться и с другими компонентами. В Инспекторе объектов в свойстве Caption нажмите на кнопку "" справа от свойства:

Свойство Caption компонента TStaticText

Рис. 13.2. Свойство Caption компонента TStaticText

В открывшемся редакторе напишите следующий текст:

Укажите температуру в Цельсиях 
от -100 до 200 градусов:
    

Именно так, в две строки. Затем измените размеры компонента на форме, чтобы текст отображался точно в таком виде, как мы ввели. И еще: в свойстве Alignment выберите taRightJustify, чтобы текст выравнивался по правому краю.

Теперь перейдите на вкладку Misc палитры компонентов, найдите там и установите на форму, правее TStaticText, компонент TSpinEdit, который предназначен для ввода пользователем целых чисел. Этот компонент похож на простой TEdit, но справа от него есть стрелки вверх и вниз, которыми пользователь может прибавлять или убавлять указанное в строке число. Использование этого компонента гарантирует нам, что пользователь не сможет ввести в него ничего, кроме целого числа. А чтобы еще гарантировать правильный диапазон этих чисел, в свойстве MaxValue (максимальное возможное значение) установите 200, а в MinValue (минимальное возможное значение) установите -100 (минус сто). Теперь пользователь не сможет ввести в это поле ничего, кроме целых чисел. Если же он попытается превысить максимальное значение, то компонент автоматически установит число 200 - максимально возможное. И наоборот, если указать число меньше, чем -100, компонент установит -100, так что нам не нужно беспокоиться об ошибках. Кроме того, в этом компоненте позже нам понадобятся ещё два свойства: Text (установленное значение в виде строки), и Value (установленное значение в виде целого числа).

По умолчанию, компонент недостаточно широк, поэтому установите в его свойстве Width значение 75. И еще: нам придется обращаться к компоненту по имени, а SpinEdit1 - это слишком длинное имя. Измените его свойство Name на SE1.

Ну и наконец, установите на форму простую кнопку, в свойстве Caption которой напишите Рассчитать температуру. Надпись на кнопке не уместится, поэтому кнопку придется удлинить. Расположите компоненты на форме примерно так:

Внешний вид формы

Рис. 13.3. Внешний вид формы

Теперь займемся предварительными расчетами. Для начала нам нужно сделать глобальный массив вещественных чисел - температура по Фаренгейту уже не будет целым числом. Значение по Фаренгейту вычисляются так: берется температура по Цельсию, умножается на 9/5, затем к результату прибавляется 32. Поэтому в глобальном разделе var, сразу над ключевым словом implementation объявляем массив atemp:

var
  fMain: TfMain;
  atemp: array[-100..200] of real;  //наш глобальный массив

implementation
    

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

Выделите форму, щелкнув по её свободному месту, затем в Инспекторе объектов перейдите на вкладку События. Нам нужно событие OnCreate - оно возникает только однажды, при создании формы. Щелкните дважды по этому событию, чтобы сгенерировать его. Код события следующий:

procedure TfMain.FormCreate(Sender: TObject);
var
  i: smallint;  //счетчик для цикла
begin
  for i:= -100 to 200 do
    atemp[i]:= i * 9/5 + 32;
end;
    

Вот теперь, наконец, мы сможем оценить всю прелесть использования массивов! Давайте разберем этот код. В разделе var мы объявили переменную i типа smallint. Это - счетчик для цикла for, который мы использовали в коде. Так как диапазон нужных нам значений располагается от -100 до +200, тип целых чисел smallint - самый подходящий. А теперь обратите внимание на код:

  for i:= -100 to 200 do
    atemp[i]:= i * 9/5 + 32;
    

Это - самая главная "фишка" массивов - обработка всего массива, каким бы большим он не был, в простом цикле. Вначале счетчик i принимает значение -100. Внутри цикла мы присваиваем значение одному элементу массива. Если мы заменим переменную i на её значение, как это делает компилятор в процессе работы, то получим следующее:

    atemp[-100]:= -100 * 9/5 + 32;
    

Таким образом, мы высчитываем перевод температуры из Цельсия в Фаренгейты для конкретной температуры: -100 градусов по Цельсию, и полученный результат присваиваем элементу массива atemp[-100]. Затем цикл повторяется, i увеличивается на единицу, и уже равна -99. Новое значение присваивается новому элементу массива, и так до конца цикла. Как вы думаете, сколько элементов массива будет заполнено в этом цикле? Кто сказал 300?! А про ноль вы забыли? 301 раз будет работать цикл, и 301 различное значение будет присвоено 301 элементу массива. А теперь представьте, как это выглядело бы для отдельных переменных:

t_100:= -100 * 9/5 + 32;
t_99:= -99 * 9/5 + 32;
…
t200:= 200 * 9/5 + 32;
    

Вместо двух строчек цикла мы получили бы 301 строку кода с одинаковыми вычислениями!

Но вернемся к нашему проекту, ведь нам еще нужно вывести на экран результат перевода температур. Сгенерируем для кнопки Button1 событие OnClick. Её код будет совсем простой:

procedure TfMain.Button1Click(Sender: TObject);
begin
  ShowMessage(SE1.Text + ' Цельсия = ' +
                         FloatToStr(atemp[SE1.Value]) + ' Фаренгейта');
end;
    

Здесь у нас всего один оператор - процедура ShowMessage(). Она формирует выводимое сообщение из 4 частей: SE1.Text - это то значение, которое установил пользователь в компоненте TSpinEdit в виде строки. Затем мы вставляем в сообщение текст ' Цельсия = '. Обратите внимание на пробелы вначале и в конце этого кусочка - без них слова слипались бы, а это некрасиво. Далее, мы добавляем к строке следующий код:

FloatToStr(atemp[SE1.Value])
    

Здесь SE1.Value - это то значение, которое установил пользователь, но уже в виде целого числа! Допустим, пользователь установил значение 35, тогда этот код будет таким:

FloatToStr(atemp[35])
    

В элементе массива atemp[35] у нас уже хранится переведенное в Фаренгейты значение температуры 35 по Цельсию. А функция FloatToStr() только переведет это значение в строку. Таким образом, для значения 35 сформируется сообщение: "35 Цельсия = 95 Фаренгейта". Сохраните проект, скомпилируйте его и убедитесь, что программа корректно работает в указанных пределах температур, а превысить их пользователь не сможет, если и захочет, как не сможет ввести ничего другого, кроме целого числа.

< Лекция 11 || Лекция 12: 123 || Лекция 13 >
Инга Готфрид
Инга Готфрид
Александр Скрябнев
Александр Скрябнев

Через WMI, или используя утилиту wmic? А может есть еще какие более простые пути...