Основы алгоритмизации и программирования - Учебное пособие (Струков В.М.)

6. ввод-вывод массивов

Массивы являются наиболее часто используемыми структурами в задачах обработки данных. Поэтому умение работать с ними очень важно с точки зрения практического программирования.

В этой главе будут рассмотрены наиболее общие приемы обработки одномерных и двумерных массивов – ввод, вывод и решение некоторых типовых задач.

6.1. Ввод одномерных массивов.

Ранее рассмотренные простейшие средства ввода данных неудобны для ввода элементов одномерных массивов. Поэтому в Delphi для этой цели используется специальный компонент Memo из палитры Standard: .

Компонент Memo позволяет вводить и редактировать несколько строк текста. Его также можно использовать для ввода значений числовых одномерных массивов.

Основным свойством Memo является свойство Lines, которое представляет собой одномерный массив строк типа String. Значение этого свойства может быть сформировано как до выполнения приложения (на этапе визуального конструирования) так и в процессе его выполнения. Нумерация элементов массива Lines начинается с 0.

Для формирования значений Lines в Инспекторе объектов необходимо выполнить следующие операции:

1). Щелчком мышки по значку  в поле значения свойства Lines активизировать редактор строк компонента Memo. При этом на экране появится следующая картинка.

2). Ввести необходимое количество строк текста и нажать кнопку Ok.

При этом количество введенных строк будет отображаться над рабочим окном редактора (например, - 5 lines).

Значения элементов Memo можно вводить и в процессе выполнения приложения. Это можно делать двумя способами:

Просто во время работы приложения в поле ввода ввести нужные значения элементов.

Путем добавления строк к концу списка с помощью метода Add.

Загрузкой в поле ввода текстового файла.

Во всех случаях количество введенных элементов фиксируется в невизуальном свойстве Count массива Lines.

Пример. Ввести массив фамилий.

Для решения этой задачи выполним следующие действия.

Разместим на форме компоненту Memo, кнопку Button, присвоив ей имя Ввод и компонент Label для контрольного вывода введенных данных.

Для кнопки Ввод сформируем следующий обработчик события Onclick:

Запустим сформированное приложение на выполнение и получим следующий результат:

Для очистки содержимого поля Memo можно воспользоваться методом Clear:  Memo1.Clear;

Формирование поля Memo путем занесения в него строк из оперативной памяти с помощью метода Add можно выполнить следующим образом:

 Var i:integer;

         s:array[1..5] of string[20];

begin

. . .

For i:=0 to 4 do

Memo1.Lines.Add(S[i+1]);

Приведенный пример означает, что кроме основного своего назначения (ввод данных), компонент Memo может также использоваться и для вывода одномерных массивов.

Значение компонента Memo можно также формировать, загружая в него содержимое текстового файла. Для этого используется метод LoadFromFile, например:

Memo1.Lines. LoadFromFile(‘d:MyDirTextFile.txt;’);

Можно также записывать содержимое компонента Memo в текстовый файл. Для этого используется метод SaveToFole, например:

Memo1.Lines. SaveToFile(‘d:MyDirFileRes.txt;’);

Ввод числовых массивов.

Для ввода числовых массивов нужно преобразовывать введенные в поле Memo1 числа из символьной формы представления в числовую.

Пример. Найти максимальный элемент целочисленного массива.

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

 Запустим приложение на выполнение и получим следующий результат:

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

Ss None – полос прокрутки нет;

SsHorizontal – есть горизонтальная полоса прокрутки;

SsVertical – есть вертикальная полоса прокрутки;

SsBoth – есть обе полосы прокрутки.

Пример:

В этом случае свойству ScrollBars присвоено значение SsBoth.

ЗАМЕЧАНИЕ. Аналогичными возможностями обладает также компонент RichEdit из палитры Win32. Но в дополнение к ним позволяет применять к тексту дополнительные операции форматирования, и совместим с форматом RTF, который поддерживается многими текстовыми редакторами.

6.2. Вывод одномерных массивов.

6.2.1. Использование компонента ListBox.

В общем случае для вывода элементов одномерных массивов (как строковых, так и числовых) можно использовать различные средства, в том числе и рассмотренные ранее (ShowMessage, Label и др.). Вместе с тем, стандартным средством, предназначенным именно для отображения на экране значений элементов одномерных массивов, считается компонент ListBox  - простой список (от английского слова List), который находится в палитре Standard. Он представляет собой прямоугольную область (аналогично компоненту Memo) c расположенными в нем строками:

В это поле на этапе выполнения пользователь не может с клавиатуры вносить свои значения – оно предназначено только для отображения данных. Кроме этого, можно располагать элементы списка не в одну, а в несколько колонок, сортировать элементы списка в алфавитном порядке, на этапе выполнения приложения выделять в списке один или несколько элементов, управлять внешним видом списка.

Свойства компонента ListBox.

Основным свойством компонента ListBox является комплексное свойство Items, которое представляет собой одномерный массив элементов типа String. Значение этого свойства может быть сформировано в Инспекторе объектов (до выполнения приложения) и в процессе выполнения приложения. Нумерация элементов массива Items начинается с 0. Количество элементов в списке фиксируется в невизуальном свойстве Count типа Integer.

В программе доступ к этому свойству возможен, например, следующим образом:

ShowMessage(’Количество элементов в списке равно - ’+ IntToStr(ListBox1.Items.Count));

Для формирования строк массива Items в Инспекторе объектов используется такой же редактор строк, как и в компоненте Memo. Порядок его активизации и применения аналогичен - щелкаем мышки по значку  в поле значения свойства Items и в появившемся окне редактора строк вводим необходимые значения. Основное назначение этого средства – задать в случае необходимости некоторые стартовые значения списка.

Формирование списка Items в процессе выполнения приложения осуществляется путем простого присваивания элементам списка их значений.

Для иллюстрации решим простейшую задачу: ввести массив строк и вывести его в список ListBox. Ввод данных выполним с помощью компонента Memo. Операции ввода и вывода будем выполнять с помощью командных кнопок Button. Текст программы с двумя обработчиками события OnClick, реализующими ввод и вывод данных, имеет следующий вид:

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, StdCtrls;

type

         TForm1 = class(TForm)

         Memo1: TMemo;

         ListBox1: TListBox;

         Button1: TButton;

         Button2: TButton;

         procedure Button2Click(Sender: TObject);

         procedure Button1Click(Sender: TObject);

private

         { Private declarations }

public

         { Public declarations }

end;

var

         Form1: TForm1;

         s:array[1..10] of string[20];

implementation

 

{$R *.dfm}

 

procedure TForm1.Button2Click(Sender: TObject);

Var k:integer;

begin

         ListBox1.Clear;

         For k:=0 to Memo1.Lines.Count-1 do

         ListBox1.Items[k]:=s[k+1];

end;

 

procedure TForm1.Button1Click(Sender: TObject);

Var k:integer;

begin

         For k:=0 to Memo1.Lines.Count-1 do

         s[k+1]:=Memo1.Lines[k];

end;

end.

Строка  ListBox1.Clear; чистит содержимое поля вывода перед тем, как выводить в него данные.

Запустим сконструированное приложение на выполнение, введем в поле ввода исходные данные и щелкнем кнопку Ввод. При этом отработает обработчик события OnClick кнопки Ввод, который запишет в массив S введенные строки. Форма после этих действий будет иметь следующий вид:

 

После этого щелкнем кнопку “Вывод» и получим следующий результат:

 

 

Если список большой и все элементы не помещаются в поле вывода, то справа автоматически вставляется вертикальная полоса прокрутки.

Компонент ListBox, кроме уже рассмотренных, имеет следующие важные свойства.

ItemIndex - свойство типа Integer, доступно только во время работы приложения и содержит номер выделенного элемента списка (если выделяется один элемент). Если ни один из элементов списка не выделен, то ItemIndex = -1.

Sorted - свойство типа Boolean. Позволяет автоматически сор-тировать элементы списка в алфавитном порядке (Sorted =True). Доступно как до, так и во время выполнения приложения.

Column - свойство типа Integer. Позволяет располагать элементы списка в несколько колонок. Применяется для длинных списков. К примеру, если установить это свойство равным 2, то получим следующий результат:

 

 MultiSelect свойство типа Boolean. Позволяет выделять несколько элементов списка.

В случае выделения одного или нескольких элементов списка пользователем для определения выделенных элементов используется свойство Selected, которое представляет собой массив типа Boolean (True - выделен, False - не выделен). Это свойство доступно только во время выполнения приложения. Установление факта выбора i-того элемента списка может быть выполнено с помощью следующего оператора:

If ListBox1.Selected[i] Then . . . ;

ExtendedSelect - свойство типа Boolean. Задаёт способ выбора нескольких элементов списка. Работает только совместно со свойством MultiSelect. Если MultiSelect=True и ExtendedSelect=True, то можно выбирать несколько смежных элементов протягиванием мышки или с использованием клавиш Shift и Ctrl. Можно также отменять выделение элементов повторным щелчком по ранее выделенному элементу.

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

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

Для ввода данных воспользуемся компонентом Memo, а для вывода результатов – простым списком ListBox. Свойства MultiSelect и ExtendedSelect установим в значение False. Обработчик события, реализующий задачу, имеет следующий вид :

 

Результат решения имеет вид:

6.2.2. Использование компонента ComboBox.

Комбинированный список ComboBox объединяет в себе возможности компонентов Memo и ListBox, то есть позволяет не только отображать данные, но и редактировать их. Кроме того, он позволяет отображать данные в более компактной форме, чем простой список ListBox. Все эти возможности реализованы в компоненте ComboBox  из палитры Standard.

ComboBox позволяет отображать массив строк в виде разворачивающегося списка:

В отличие от простого списка ListBox в комбинированном списке нельзя отображать элементы списка в несколько колонок (всегда в одну колонку), он не имеет горизонтальной полосы прокрутки и в нем можно выделить только один элемент.

Может использоваться в 3-х режимах:

как простой список ListBox;

как разворачивающийся список;

неизменяемый.

Режим использования (внешний вид и поведение) комбинированного списка определятся свойством Style, которое может принимать следующие значения:

-CsSimple – поле списка представляется в виде прямоугольника с неизменными размерами. Для увеличения количества видимых элементов списка нужно увеличивать высоту списка (свойство Height); пользователю предоставляется возможность редактировать данные в поле редактирования;

-CsDropDown – режим, устанавливающийся по умолчанию, - разворачивающийся список. Номер элемента списка, который показывается в поле свернутого списка, определяется свойством ItemIndex. Если значение этого свойства меньше 0, то в поле отображается текст, хранящийся в свойстве Text. Пользователю предоставляется возможность редактировать данные в поле редактирования.

-CsDropDownList – режим разворачивающегося списка, как и в предыдущем случае, однако пользователь не может редактировать данные.

-CsOwnerDrawFixed – список с элементами фиксированной высоты, которую задает свойство ItemHeight.

-CsOwnerDrawVariable - список с элементами, которые могут иметь различную высоту.

Элементы списка хранятся в свойстве Items. Количество элементов фиксируется в свойстве Count, доступ к которому возможен только при выполнении приложения, например, так:

Label1.Caption:=’Количество элементов в списке равно - ’+ IntToStr(ComboBox1.Items.Count);

Свойство DropDownCount типа Integer определяет количество строк, которые одновременно отображаются в окне раскрытого списка.

Свойство DroppedDown типа Boolean определяет вид списка – раскрыт (True) или свернут (False). Это свойство работает только в том случае, если свойство Style имеет значение не CsSimple.

6.2.3. Основные приемы работы со списками

Над элементами списков (как простых, так и комбинированных) можно выполнять следующие простейшие операции:

вставка нового элемента в список;

добавление нового элемента в конец списка;

удаление элемента списка;

очистка списка (удаление всех элементов списка).

Для вставки нового элемента в произвольную позицию имеющегося списка используется метод Insert. Формат обращения к нему имеет следующий вид:

<Имя списка>.Items.Insert (Index:integer; Const St:string);

Действие метода: в список <Имя списка> вставляется строка St, начиная с позиции Index. Пример:

ListBox1. Items. Insert (2;’Новый элемент’);

Выполнение такого оператора в программе приведет к вставке между первым и вторым элементами списка ListBox1 новой строки ’Новый элемент’.

Для добавления нового элемента в конец имеющегося списка используется метод Add. Формат обращения к нему имеет следующий вид:

<Имя списка>.Items.Add(Const St:string);

Действие метода: в конец списка <Имя списка> вставляется строка St. Пример:

ListBox1.Items. Add(’Конец списка!’);

Выполнение такого оператора в программе приведет к вставке в конце списка ListBox1 строки ’ Конец списка!’.

Удаление произвольного элемента списка выполняется с помощью метода Delete. Формат обращения к нему имеет следующий вид:

<Имя списка>.Items.Delete(Index:integer);

Из списка <Имя списка> удаляется строка с номером Index. Пример:

ComboBox1.Items.Delete(2);

Из списка ComboBox1 будет удалена вторая строка.

Для очистки всего содержимого списка используется метод Clear. Пример обращения к нему:

ComboBox1.Clear;

Все строки списка ComboBox1 после выполнения этого оператора будут удалены.

6.3. Ввод-вывод двумерных массивов.

Работа с двумерными массивами (матрицами) является важнейшим элементом программирования на любом алгоритмическом языке. И ввод-вывод есть основа обработки матриц.

Для ввода-вывода элементов матриц в Delphi используются два компонента – StringGrid и DrawGrid, размещенные в палитре Additional.

6.3.1. Ввод-вывод матриц с помощью компонента StringGrid.

 

Компонент StringGrid применяется как для ввода данных, так и для вывода. Режим его использования регулируется предусмотренными для этого свойствами.

StringGrid представляет собой прямоугольную решетку ячеек, состоящую из строк и столбцов, следующего вида:

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

Таблица может работать в одном из двух режимов: 1) режим отображения (вывода) и 2) режим ввода и редактирования. В режиме отображения вводить данные в ячейки таблицы или редактировать их нельзя.

Свойства таблицы StringGrid.

Основным свойством компонента StringGrid является свойство Cells, которое представляет собой двумерный массив типа String. Это свойство доступно только на этапе выполнения приложения. Строки и столбцы массива Cells пронумерованы, начиная с 0. При обращении к ячейке массива сначала указывается номер столбца, а затем – номер строки, например:

StringGrid1.Cells[2,5]:=’1’;

Этим оператором в ячейку, которая находится на пересечении третьего столбца и шестой строки, записывается символ ’1’.

ColCount – свойство типа LongInt, определяет количество колонок в таблице. По умолчанию равно 5.

RowCount – свойство типа LongInt, определяет количество строк в таблице. По умолчанию равно 5.

Для формирования «шапки» таблицы (фиксирования верхних строк или левых столбцов) используются свойства FixedCols и FixedRows типа Integer. Свойство FixedCols определяет число фиксированных левых столбцов, FixedRows - число фиксированных верхних строк. При горизонтальном и вертикальном скроллинге таблицы зафиксированные строки и столбцы остаются на месте, что очень удобно при обработке больших таблиц. По умолчанию значения этих свойств равны 1. Ячейки шапки автоматически выделяются серым цветом. При желании цвет выделения можно изменить с помощью свойства FixedColor.

Color - свойство типа TColor (принимает значения из набора именованных констант) задает цвет ячеек таблицы (кроме ячеек шапки). По умолчанию равно clWindow.

Cols – свойство, доступное только при выполнении приложения, представляющее собой одномерный массив, элементом которого является столбец таблицы с заданным номером. Например, запись StringGrid1. Cols[3] указывает на четвертый столбец таблицы StringGrid1. Посредством этого свойства можно также обратиться к конкретной ячейке таблицы, например:

StringGrid1.Cols[2][1]:='абс';

Этим оператором во вторую ячейку третьего столбца таблицы запишется строка 'абс'.

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

ColWidths – невизуальное свойство, представляющее собой одномерный массив типа Integer. Задает ширину указанного столбца в пикселях. Так, например, оператор StringGrid1.ColWidths[2]:=50; устанавливает ширину третьего столбца таблицы в 50 пикселов.

RowHeights - невизуальное свойство, представляющее собой одномерный массив типа Integer. Задает высоту указанной строки в пикселях. Порядок его применения аналогичен предыдущему свойству.

Режим работы таблицы (отображение или редактирование) регулируется совместно двумя свойствами – Enabled и goEdditing.

Enabled – свойство типа Boolean, определяет доступность таблицы: если оно установлено в False, то таблица пользователю недоступна и работает только в режиме отображения (вывода); если же значение этого свойства установлено в True, то степень доступности ячеек таблицы определяется значением свойства goEdditing типа Boolean. Это свойство входит как элемент в состав комплексного свойства Options. Если goEdditing=True, то ячейки таблицы можно редактировать (режим ввода и редактирования данных), Если goEdditing=False, то ячейки таблицы не доступны для редактирования, их можно только выделять мышкой.

ЗАМЕЧАНИЕ 1. Пользователю недоступны для редактирования ячейки шапки таблицы. Программно доступны все ячейки таблицы.

ЗАМЕЧАНИЕ 2. При выделении пользователем ячейки таблицы, ее координаты (номер строки и номер столбца, на пересечении которых она находится) фиксируются в невизуальных свойствах Row и Col типа LongInt. Эти свойства доступны и для записи, что можно использовать с целью программного выделения ячеек таблицы.

Комплексное свойство Options используется для настоек режимов работы таблицы и включает множество подсвойств типа Boolean. Рассмотрим некоторые из них.

goVertLine и goHorzLine – позволяют отображать (True) или не отображать (False) разделительные линии между ячейками таблицы.

goRangeSelect - позволяет пользователю выделять диапазон ячеек. Игнорируется если свойство goEdditing=True.

goDrawFocusSelected – если это свойство установлено в True, то содержащая фокус ячейка выделяется рамкой и цветом.

goTabs – разрешает перемещение между ячейками таблицы с помощью клавиш Tab и Shift-Tab.

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

Для решения этой задачи разместим на форме следующие компоненты: StringGrid1 – для ввода элементов матрицы; командные кнопки «Ввод» – для преобразования введенных числовых значений из строковой формы представления в числовую и записи в целочисленную матрицу, и «Максимум» – для поиска и отображения максимального элемента матрицы.

Текст программы, которая реализует решение поставленной задачи приведен ниже:

unit Unit1;

interface

uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, Grids;

Type  TForm1 = class(TForm)

Button2: TButton;

 Label1: TLabel;

StringGrid1: TStringGrid;

Button1: TButton;

procedure Button2Click(Sender: TObject);

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var  Form1: TForm1;

 a:array[1..3,1..4] of integer;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);

Var i,j,max,imax,jmax:integer;

begin

         max:=-Maxint;

         For i:=1 to 3 do

         For j:=1 to 4 do

         if a[i,j]>max then

         begin

         max:=a[i,j];

         imax:=i;

         jmax:=j;

         end;

         StringGrid1.Col:=jmax-1;

         StringGrid1.Row:=imax-1;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

Var i,j:integer;

begin

         For i:=1 to 3 do

         For j:=1 to 4 do

         a[i,j]:=StrToInt(StringGrid1.Cells[j-1,i-1]);

end;

 

end.

Результат работы программы после ввода данных и нажатия кнопки «Максимум» выглядит следующим образом:

Как видно из рисунка в этой таблице отсутствует шапка, то есть свойства FixedRows=0 и FixedCols=0.