Введение в программирование на Delphi

Тип TStrings

Показывать лекцию целиком

Строка и строки TStrings

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

Итак, что такое строка? Фактически, это массив символов. Давайте посмотрим пример:

var
   s : String;
   a : array [1..7] of Char;
begin
   s := 'Привет!';
   ShowMessage(s);  //Результат: вывод строки "Привет!"

   a[1] := 'П';
   a[2] := 'р';
   a[3] := 'и';
   a[4] := 'в';
   a[5] := 'е';
   a[6] := 'т';
   a[7] := '!';
   ShowMessage(a);   //Результат: вывод строки "Привет!"

   ShowMessage(a[1]); //Результат: вывод буквы "П"

К сожалению, мы не можем просто так взять и присвоить массиву строку – это будет ошибкой, поэтому a := s не скомпилируется. Однако после того, как в массив мы посимвольно ввели текст, это получается уже полноценной строкой, поэтому компилятор разрешит директиву ShowMessage(a) ;, и программа отработает без ошибок. Разумеется, неразумно использовать массив символов там, где проще использовать переменную типа String. Этот пример показывает, что строка – это тот же массив символьного типа!

Однако мы с вами уже сталкивались и с типом TStrings – строки. Такой тип мы использовали в свойстве Lines компонента Memo и вы уже убедились, насколько мощный это тип и как легко с ним работать. Он позволяет добавлять или удалять строку из списка строк, с его помощью легко записать строки в файл или наоборот, загрузить их из файла. Тип TStrings присутствует во многих компонентах, и везде вы с ним можете производить такие вот действия! Раз уж мы заговорили о массивах, то проведем сравнение и для TStrings – это тот же массив, только не типа Char (символ), а типа String (строка):

a : array [1..10] of String;

Однако, хотя TStrings по своему образу похож на такой массив, он имеет массу дополнительных возможностей, поэтому используйте его везде, где встает речь о работе с набором строк!

ListBox – список выбора

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

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

Посмотрим на практике, как работать с данным компонентом. Создайте новое приложение, установите на него один компонент ListBox, и под ним – один Edit для вывода той строки, которую выбрал пользователь:

(рис 12.1) Внешний вид формы

Затем дважды щелкните по свойству Items компонента ListBox. Перед вами откроется уже знакомый редактор строк. Наберите названия операционных систем:

MS-DOS
Windows 3.10
Windows 95
Windows 98
Windows ME
Windows 2000
Windows XP
Windows Vista
Unix
Linux
OS/2

Каждое название операционной системы должно быть на отдельной строке. Нажмите "ОК", чтобы сохранить результат. Теперь создайте для компонента ListBox обработчик события onClick. Мы уже знаем, что это событие срабатывает всякий раз, когда пользователь выберет одну из строк в указанном списке.

В обработчике событий напишите только одну строку:

Edit1.Text := ListBox1.Items.Strings[ListBox1.ItemIndex];

Эта строка присваивает свойству Text компонента Edit тот текст, который хранится в выбранной строке списка ListBox. Свойство Items имеет свое свойство Strings, которое представляет собой массив из строк списка. Указав индекс массива, мы можем получить доступ к нужной строке. В примере в качестве индекса указано свойство ListBox1.ItemIndex, которое имеет тип Integer и возвращает индекс выбранной строки в массиве строк. Кстати, когда вы поставите точку и откроется список, там вы этого свойства не обнаружите, так что придется писать его вручную.

Сохраните пример в новую папку, откомпилируйте и посмотрите, как он работает.

Кроме того, мы имеем возможность программно добавлять в ListBox новую строку или удалять выбранную. Киньте на форму еще две кнопки и напишите на них – "Добавить строку", "Удалить строку". Добавлять будем строку, написанную в компоненте Edit, а удалять – выделенную.

Для кнопки "Добавить" впишите:

ListBox1.Items.Add(Edit1.Text);

а для кнопки "Удалить":

ListBox1.Items.Delete(ListBox1.ItemIndex);

Сохраните проект, откомпилируйте и посмотрите, как он работает.

Часто бывает необходимым предоставить пользователю возможность множественного выбора. Пользователь, удерживая клавишу <Ctrl>, щелкает по строкам и выбирает нужные. Для этого у ListBox имеется свойство MultiSelect (множественный выбор). По умолчанию оно равно False, то есть запрещает пользователю выбрать несколько строк. Создадим еще одно приложение, в котором продемонстрируем возможность множественного выбора.

Установите на форму один ListBox и один Memo, ниже – кнопку с надписью "Копировать". При нажатии на кнопку будем искать у ListBox выделенные строки и копировать их в Memo. На рисунке 12.2 в левой части установлен компонент ListBox, а в правой – Memo.

(рис 12.2) Внешний вид приложения

Войдите в редактор строк ListBox и напишите там

Строка № 1
Строка № 2

и так далее, пока не заполните ListBox так, чтобы его не нужно было прокручивать. Установите свойство MultiSelect у ListBox в True. Не забудьте очистить Memo. Теперь для кнопки напишем следующий код:

procedure TForm1.Button1Click(Sender: TObject);
var
  i : Integer;
begin
  Memo1.Clear;
  for i := 0 to ListBox1.Items.Count - 1 do
     if ListBox1.Selected[i] then
        Memo1.Lines.Add(ListBox1.Items.Strings[i]);
end;

Вначале мы очистили Memo, чтобы пользователь мог несколько раз опробовать выбор и копирование строк, и строки в Memo не скапливались.

Затем мы создаем цикл, чтобы обрабатывать ListBox построчно. Первая строка всегда имеет нулевой индекс, а свойство Count во всех объектах TStrings возвращает количество строк в объекте. Нам приходится вычесть единицу, так как индексы начинаются не с 1, а с 0. Далее в цикл мы поместили условный оператор if – если условие верно (то есть строка выделена), то производим добавление строки в Memo. За это отвечает свойство Selected (Выделено) с указанием индекса строки. Если оно равно True, то строка выделена.

ComboBox – выпадающий список

Такие списки вы часто встречаете при работе с Windows и различными программами. Действуют и работают они также как ListBox, с той только разницей, что выглядят по-другому, и не позволяют выбрать несколько элементов сразу. Создайте новое приложение, добавьте туда только один ComboBox и один Edit:

(рис 12.3) Внешний вид приложения

Вызовите редактор строк ComboBox (свойство Items ) Впишите несколько городов:

Москва
Санкт-Петербург
Киев
Минск
Ташкент
Душанбе

Свойство ItemIndex, которое, как мы знаем, указывает индекс выделенной строки, по умолчанию установлено в -1. Это означает, что ни одна строка не выбрана. Если установить его в 0, то в поле ввода текста появится первая строка списка. Оставим -1, чтобы строк не было видно.

Создадим обработчик события OnChange для компонента ComboBox, и там напишем только одну строку:

Edit1.Text := ComboBox1.Items.Strings[ComboBox1.ItemIndex];

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

Управление циклами

Вы знаете уже практически все циклы – for..do, while..do, repeat..until. Однако этими циклами можно еще и управлять. Для этого служат директивы break и continue.

Break – прерывание цикла. Если внутри цикла встретится такой оператор, происходит немедленный выход из цикла. Как правило, этот оператор используют совместно с управляющей структурой if, например:

if a <> b then break;

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

Continue – прерывание текущего шага цикла. В отличие от break, continue не прекращает цикл вовсе, а лишь прерывает дальнейшую обработку этого шага цикла, после чего цикл сразу начинается со следующего шага. Способ применения такой же, как у break. Рассмотрим работу continue на практическом примере.

Нам нужно разделить число 10 на число от -3 до 3 включительно, и результат вывести в ListBox. Поскольку выводить будем также целые числа, нам поможет функция Round(), которая принимает вещественное число, округляет его до ближайшего целого и это целое возвращает. Также мы знаем, что на ноль делить нельзя, это ошибка. Для того, чтобы не допустить это деление, мы прервем этот шаг цикла с помощью директивы continue.

Создайте новое приложение. Установите на форму ListBox, а под ним – кнопку:

(рис 12.4) Внешний вид приложения

При нажатии на кнопку, напишите следующий код:

procedure TForm1.Button1Click(Sender: TObject);
var
   i, r : Integer;
begin
   for i := -3 to 3 do begin
      if i = 0 then begin
         ListBox1.Items.Add('На ноль делить нельзя!');
         Continue;
      end; //if

     r := Round(10/i);
     ListBox1.Items.Add('10/'+IntToStr(i)+'='+IntToStr(r));
  end; //for

end;

В тот момент, когда счетчик i станет равным 0, выполнится тело условия if, и после оператора Continue цикл сразу перейдет на новый виток, пропустив деление.

Самостоятельное задание

В примере мы жестко задали условия: делить именно число 10 на диапазон чисел от -3 до 3. Измените пример так, чтобы пользователь мог сам указать какое число нужно делить, и на какой диапазон. Это несложное задание, однако, придется подключить к работе мозги.

Вернуться к учебному плану