Некоторые операции со строками.

Операция Описание
Copy(S, pos, len) Возвращает подстроку длиной len символов из строки S, начиная с символа номер pos.
Length(S) Возвращает фактическую (динамическую) длину строки S.
Pos(substr, S) Возвращает позицию первого вхождения подстроки substr в строку S.
SetLength(S, newlen) Задаёт новую длину newlen строке S.
StringOfChar(Ch, Count) Возвращает строку, заполненную символом Ch в количестве Count.
Trim(S) Возвращает строку без начальных и конечных пробелов.
UpperCase(S) Возвращает строку с прописными буквами.

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

ПРИМЕР 9

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

ShowMessage отображает статические сообщения. Это диалоговое окно отображает в центре экрана строку текста и кнопку “OK” (рис. 24). Вызывается посредством использования процедуры ShowMessage(S), где S – строка типа String.

ShowMessagePos (рис. 25) предназначено для тех же целей, что и ShowMessage. При вызове, кроме строки текста, процедуре необходимо передать экранные координаты X и Y расположения этого окна.

Некоторые операции со строками. - student2.ru Рис. 24 Окно ShowMessagePos. Некоторые операции со строками. - student2.ru Рис. 25 Окно ShowMessage.

В отличие от предыдущих диалоговых окон, MessageBox (рис. 26) позволяет задавать две строки: заголовок окна и поясняющий текст. Программно вызов оформлен в виде функции. Эта функция возвращает значение, на какой кнопке щёлкнул пользователь. Количество отображаемых кнопок может быть одна или более и задаётся с помощью аргумента, представля-ющего собой набор предопределённых кон-стант. Передаваемые в функцию строки заголовка и текста должны иметь тип PChar. Если эти строки типа String, то необходимо использовать преобразование типов, записывая P = PChar(S), где P типа PChar, а S – String.

MessageDlg (рис. 27) отличается от Message-Box тем, что заголовок этого окна предопределён.

Некоторые операции со строками. - student2.ru Рис. 26 Окно MessageBox. Некоторые операции со строками. - student2.ru Рис. 27 Окно MessageDlg.

Функция Message-Dlg имеет 4 аргумента: первый передает текст в виде строки типа String, второй – вариант заголовка, третий – какие кнопки будут отображаться, четвёр-тый – позволяет орга-низовать связь с файлом подсказки Help.

Некоторые операции со строками. - student2.ru Как и в случае предыдущего окна функция возвращает, на какой кнопке щёлкнул пользователь. Окно MessageDlg располагается в центре экрана. MessageDlgPos (рис. 28) является вариантом MessageDlg с той лишь разницей, что этому виду диалогового окна необходимо передавать координаты X и Y его расположения на экране. Форма примера 9 представлена на рис. 29.

Некоторые операции со строками. - student2.ru

Рис. 29 Форма примера 9.

Для реализации локального меню выбора варианта диалогового окна использовался компонент TRadioGroup – группа взаимосвязанных переключателей TRadioButton.

С помощью свойства Items создается список взаимоисключающих альтернатив, в данном случае из пяти строк, для каждой из которых создаётся переключатель. Выбирая мышью (или стрелками) тот или иной переключатель, в списке фиксируется строка и её номер, который позволяет в программе обеспечить выполнение того или иного кода. Выбранный номер записывается в свойстве ItemIndex. Нумерация переключателей задается от нуля. Переключатели можно располагать не только в один столбец, но и в несколько столбцов. Количество столбцов задается в свойстве Columns. С помощью свойства Caption можно задавать заголовок всей группе взаимозависимых переключателей.

Строки меню заносятся в список. Вызывая в инспекторе объектов свойство Items, можно набрать пять строк, а значение ItemIndex установить, например, равным 3. Для данного компонента необходимо создать обрабочик OnClick.

Текст программы приводится ниже. В данном примере имя формы (Name) выбрано MainForm, соответственно порождающий эту форму класс имеет имя TMainForm.

unitPrim9;

Interface

uses SysUtils, Windows, Messages, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Buttons;

type TMainForm= class(TForm)

RadioGroup1: TRadioGroup;

Bevel1: TBevel;

Label1: TLabel;

BitBtn1: TBitBtn;

procedure RadioGroup1Click(Sender: TObject);

end;

var MainForm: TMainForm;

Implementation

{$R *.DFM}

procedure TMainForm.RadioGroup1Click(Sender: TObject);

const sde='Демонстрация ';

sbi='Было выбрано ';

var TheText,TheCaption: String;

S: String[6];

W: Word;

X, Y: Integer;

begin

case RadioGroup1.ItemIndex of

0: ShowMessage(sde+'ShowMessage');

1: begin

X := 50; Y := 60;

ShowMessagePos(sde+'ShowMessagePos',X,Y);

end;

2: begin

TheText := 'Текст-пояснение к MessageBox';

TheCaption := sde+'MessageBox ';

if Application.MessageBox(PChar(TheText),

PChar(TheCaption),MB_DEFBUTTON1 +

MB_ICONEXCLAMATION + MB_OKCANCEL) = IDOK

then ShowMessage(sbi+'OK')

else ShowMessage(sbi+'Cancel');

end;

3: begin

W := MessageDlg(sde+'MessageDlg', mtInformation,

[mbYes, mbNo, mbIgnore],0);

case W of

mrYes: S := 'Yes';

mrNo: S := 'No';

mrIgnore: S := 'Ignore';

end;

ShowMessage(sbi + S);

end;

4: begin

X := 50; Y := 75;

W := MessageDlgPos(sde+'MessageDlgPos',

mtWarning,mbAbortRetryIgnore, 0, X, Y);

case W of

mrAbort: S := 'Abort';

mrRetry: S := 'Retry';

mrIgnore: S := 'Ignore';

end;

ShowMessage(sbi + S);

end;

end; {case}

end;

end.

В программе при объявлении переменной S задана максимальная длина присваимого ей значения, равная 6 символам. Аргумент функции MessageDlg,заданный в квадратных скобках, означает, что с помощью конструктора множества передаётся некоторое заданное множество.

ЗАПИСИ (ОБЪЕДИНЕНИЯ)

С помощью зарезервированного слова record в единой структуре можно объединить данные разных типов. Общий синтаксис объявления такого объединения следующий:

Type <имя типа> = Record

<Список полей>: <тип>;

<Список полей>: <тип>;

. . . . . . . . . . ;

End;

Поля записи (или объединения) могут быть любого типа, количество их не ограничено. Например,

Type

Complex = record{Тип комплексных чисел}

Re, Im: real;

end;

Data = record {Тип – дата рождения}

Year:word;

Month: 1..12;

Day: 1..31;

end;

Person = record {Тип – сведения о сотруднике}

Name: string[40];

Age: word;

Adres: string[80];

end;

Количество памяти, выделяемой под запись, может быть различным в зависимости от директивы {$A} (выравнивание). Если установлено {$A+}, то поля выравниваются по четным адресам - уменьшается время доступа к переменной в памяти. По умолчанию установлено {$A-}. Перед ключевым словом record можно добавить слово Packed. В этом случае под запись выделяется минимальное количество байт, причем директива {$A} игнорируется.

После объявления типа можно задать переменные или типизированные константы этого типа, например,

Var Z: Data;

X: Complex;

Const

Birthday:Data=(Year:1974;Month:7;Day:12);

Petrov:Person=(Name:’Иван’;Age:22;

Adres:’Новомосковск,Мира,20,3’);

Доступ к полям записи в программе осуществляется следующим способом:

Z.Year:=1969; {Z – селектор записи; Year – поле}.

Z.Month:=7; Z.Day:=13; X.Re: 0.8;

X.Im: 2.1; Z.Month:= Z.Day div 5+2;

Тип данных запись может иметь так называемую вариантную часть. Вариантная частьпозволяет трактовать по-разному занимаемую полями одну и ту же память.

Type

Figure=(Square,Triangle,Circle);

G = Record

X,Y: integer;

Case fig: Figure of

Square: (Side: integer);

Triangle: (Side1,Side2,Angle: integer);

Circle: (Radius: integer);

end;

В данном случае задан перечисляемый тип для обозначения трёх геометрических фигур: квадрата, треугольника и окружности. Далее вводится объединение: X, Y – координаты привязки этих фигур на некоторой плоскости, Side(сторона) определяет квадрат, Side1, Side2, Angle (угол) определяют треугольник, Radius – окружность. Начиная с ключевого слова Case,записывается вариантная часть. Память выделяется одна. Трактовать её можно в данном случае так: в памяти находится или одна величина Side, или три величины Side1, Side2, Angle, или одна величина Radius. Когда и как трактовать память – выбирает программист.

Вариантная часть может быть только одна и располагаться в конце записи. Синтаксически Fig есть параметр выбора (указывать его необязательно). Чаще всего вариантную часть записывают так:

Case Figure of

Square: (Side: integer);

Triangle: (Side1,Side2,Angle: integer);

Circle: (Radius: integer);

Как замечено выше, память под вариантную часть выделяется одна и та же. В данном случае для Triangle требуется записать три величины типа integer, больше, чем для других фигур. Поэтому под вариантную часть будет выделено 12 байт памяти (по 4 байта на каждую величину).

Далее выберем две переменные и запишем данные в эти переменные:

Var MySquare: G; MyCircle: G;

. . . . . . . . . . . . . .

MySquare.Side:= 5; MyCircle.Radius: = 10;

Как можно заметить, отличий в записи информации в вариантные поля от обычных полей на этом уровне не существует. Если попытаться в примере выше прочитать значение MySquare.Side, то оно будет равно 10, так как последняя запись в общую память была именно такая (MyCircle.Radius: = 10;).

ОПЕРАТОР WITH

Оператор With часто называется оператором присоединения. Для того чтобы не записывать каждый раз имя селектора, при обращении к полям записи используется этот оператор, например, With Data do begin

Year:= 1971; Month:=5;

Day:=28;

End;

ПРИМЕР 10

Пусть требуется рассчитать зарплату (З), премию (П) и итоговую сумму (И) 2-м сотрудникам в соответствии с табл. 12.

Таблица 12

Данные к примеру 10.

Таб N ФИО Окл, Т.с Час Дни Дни граф З П И
Иванов И.И.      
Петров П.П.      

В данном случае заданы два варианта расчёта зарплаты: по окладу (Окл = 6000) и по часовой тарифной ставке (Т.с = 40). В первом случае зарплата (З) расчитывается следующим образом: Некоторые операции со строками. - student2.ru

Во втором случае необходимо использовать такие соотношения: Некоторые операции со строками. - student2.ru ; Некоторые операции со строками. - student2.ru

Указанные ограничения в формулах означают, что, если сотрудник отработал больше, чем по графику, то это сверхурочные, которые оплачиваются отдельно (в примере сверхурочные не учитываются). Используемая во втором случае цифра 8 означает, что задан восьмичасовой рабочий день.

Предусмотрена премия не более 150 % от зарплаты, которая выплачивается, если предприятие имеет прибыль. Форма с вариантом решения приводится на рис. 30.

Некоторые операции со строками. - student2.ru

Рис. 30 Форма с вариантом расчета примера 10.

Задача решается в 2 этапа: вначале - ввод информации (можно изменить исходные данные), затем - расчет.

Как и в предыдущих случаях, в данном примере использовались новые компоненты. Для указания, есть ли премия в данном месяце, необходим переключатель. При решении примера 10 использовался переключатель с независимой фиксацией TCheckBox. Этот стандартный элемент Windows позволяет выбрать или отменить определенную опцию. С помощью группы таких переключателей можно выбирать или отключать несколько опций одновременно. Состояние переключателя (вкл/выкл) содержится в свойстве Checked. Для обработки переключений используется событие OnClick. Кнопку можно перевести в третье состояние (“включённое серое”) c помощью свойства AllowGrayed. Это свойство используется, если переключатель содержит еще ряд вложенных переключателей. Третье состояние переключателя указывает, что вложенные опции не все включены или не все выключены. Узнать, включено ли свойство AllowGrayed, можно с помощью свойства State.

Для полноты представления проблемы рассмотрим ещё один вид переключателей – переключатель с зависимой фиксацией - TradioButton. Этот вид переключателей в примере 9 уже использовался, но в составе группы. Если выбрано несколько таких переключателей, то они автоматически объединяются в группу и позволяют из множества опций выбрать одну, в отличие от CheckBox. TradioButton также имеет свойство Checked и событие OnClick, свойство AllowGrayed отсутствует.

Событие OnClick обрабатывается по-разному у переключателей TCheckBox и TRadioButton. У TCheckBox событие обрабатывается независимо от того, включена или выключена опция Checked, у TRadioButton - только если Checked равно true в момент переключения.

Для представления табличных данных использовалась графическая таблица TDrawGrid, которая, в отличие от TStringGrid, может отображать не только текстовую информацию, но и графическую. TDrawGrid имеет значительно больше возможностей, чем TStringGrid. Например, размеры строк и столбцов можно изменять индивидуально. Можно изменять и цвет ячеек (индивидуально). Внешний вид графической сетки настраивается с помощью следующих свойств: ColCount, RowCount– количества столбцов и строк; DefaultColWidth, DefaultRowHeight – высота и ширина по умолчанию; Height, Width – ширина и высота таблицы; FixedColls, FixedRows – фиксированное количество столбцов и строк. Индивидуальные размеры строк и столбцов содержатся в свойствах ColWidth и RowHeight – эти свойства являются массивами. Отметим несколько опций свойства Options: GoRowSizing – разрешить или запретить изменение размеров строк, GoColSizing - разрешить или запретить изменение размеров столбцов, GoEditing – разрешить или не разрешить редактирование, GoAlwaysShowEditor - если эта опция отключена, то редактор загружается клавишей F2 или щелчком мыши, если эта опция включена, то редактор загружается автоматически. В отличие от TStringGrid, TDrawGrid не имеет свойства Cells (ячейки), поэтому ввод данных и запись данных после редактирования нужно организовывать самостоятельно. Для отображения данных необходимо воспользоваться событием OnDrawCell – перерисовка ячеек. При перерисовке ячеек область рисования (в пикселах) задается в виде свойства Rect (прямоугольник). Свойство Rect преобразует номера колонки и строки в прямоугольник, заданный в пикселах. Перерисовка ячейки зависит от свойства State (состояние), которое может иметь следующие значения: gdSelected – ячейка выбрана; gdFocused – на ячейке находится фокус gdFixed – зафиксированная ячейка (заголовок). Для рисования в DrawGrid имеется свойство TCanvas. Для задания прямоугольника существует метод CellRect, который в соответствии с аргументами: номером столбца и номером строки - задаёт координаты области рисования в пикселах. Событие OnSelectCell позволяет индивидуально запретить или разрешить передачу фокуса какой-либо ячейке внутри таблицы. Для организации ввода данных используется событие OnGetEditText. Для фиксирования изменений после ввода (после редактирования) используется событие OnSetEditText.

На форме рис. 30 выбраны такие значения для некоторых свойств DrawGrid: ColCount = 9, RowCount = 3, Options: goColSizing = true, goEditing = true, goAlwaysShowEditor = True, DefaultDrawing = False. Последнее свойство может отключать событие OnDrawCell, включая прорисовку по умолчанию.

В данном примере необходимо реализовать несколько обработчиков событий:

· OnClick –запуск рисования ячеек;

· OnDrawCell – перерисовка ячеек;

· OnGetEditText – вызов редактора ввода данных в ячейки;

· OnSetEditText – запись информации после ввода;

· OnKeyPress – ограничение (фильтр) ввода;

· OnSelectCell – ограничение доступа к некоторым ячейкам.

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

· С помощью Button1 предусмотрим обработчик, задающий начало расчета (OnClick).

· Для Edit1 необходим OnKeyPress.

· Для Edit1 необходим OnExit, чтобы контролировать ввод числа (не более 150) по условию задачи.

· Для CheckBox1 организуем обработчик при потере фокуса этим элементом (OnExit) и передаче фокуса или Edit1 или DrawGrid1 (обход Edit1).

Для записи результатов ввода и итоговых результатов предусмотрим двумерный массив Field,который должен объявляться глобально. Размеры массива [0..2], [0..8] – 3 строки и 9 столбцов. Для выполнения всех расчетов воспользуемся типом данных запись. Ниже приводится программа.

unit prim10;

Interface

uses Windows, Messages, SysUtils, Classes, Graphics,

Controls, Forms, Dialogs, Grids, Buttons, StdCtrls,

ExtCtrls;

Type

TMainForm = class(TForm)

Panel1: TPanel;

Button1: TButton;

BitBtn1: TBitBtn;

DrawGrid1: TDrawGrid;

CheckBox1: TCheckBox;

Edit1: TEdit;

Label1: TLabel;

Procedure DrawGrid1DrawCell

(Sender: TObject; ACol, ARow: Integer;

Rect: TRect; State: TGridDrawState);

procedure DrawGrid1GetEditText(Sender: TObject;

ACol, ARow: Integer; var Value: String);

procedure DrawGrid1Click(Sender: TObject);

procedure FormCreate(Sender: TObject);

procedure DrawGrid1SetEditText(Sender: TObject;

ACol, ARow: Integer;const Value: String);

procedure DrawGrid1SelectCell(Sender: TObject;

ACol, ARow: Integer;var CanSelect: Boolean);

Procedure DrawGrid1KeyPress

(Sender: TObject; var Key: Char);

procedure CheckBox1Exit(Sender: TObject);

procedure Edit1KeyPress(Sender: TObject;

var Key: Char);

procedure Button1Click(Sender: TObject);

end;

var MainForm: TMainForm;

const Field: array [0..2, 0..8] of string =(('ТабN',

'Ф.И.О.','Окл,Т','Час','Дней','Дн.г.','Зарпл',

'Премия','Итого'), ('1','Иванов И.И.','6000',

'176','22','24','0','0','0'),('2','Петров П.П.',

'40','184','23','24','0','0','0'));

Implementation

{$R *.DFM}

procedure TMainForm.DrawGrid1DrawCell(Sender: TObject;

ACol, ARow: Integer;Rect: TRect;

State: TGridDrawState);

var i,j:byte;

begin

with DrawGrid1 do

for j:=0 to RowCount-1 do begin

if j=0 then Canvas.Brush.Color:=clBtnFace

else Canvas.Brush.Color:=clWindow;

for i:=0 to ColCount-1 do begin

Rect:=CellRect(i,j);

with Canvas,Rect do TextRect(Rect,Left+(Right-

Left-TextWidth(Field[j,i])) div 2,Top+(Bottom-

Top-TextHeight(Field[j,i])) div 2,Field[j,i]);

end;

end;

end;

procedure TMainForm.DrawGrid1GetEditText(Sender:

TObject; ACol, ARow: Integer;var Value: String);

begin

Value:=Field[ARow,ACol];

end;

procedure TMainForm.DrawGrid1Click(Sender: TObject);

begin

with DrawGrid1 do begin

DrawGrid1DrawCell(Sender,0,0,CellRect(0,0),

[gdFixed]);

DrawGrid1DrawCell(Sender,0,1,CellRect(0,1),

[gdSelected,gdFocused]);

DrawGrid1DrawCell(Sender,0,2,CellRect(0,2),

[gdSelected,gdFocused]);

end;

end;

procedure TMainForm.FormCreate(Sender: TObject);

var i:byte;

begin

with DrawGrid1 do

for i:=0 to ColCount-1 do

case i of

0,2: ColWidths[i]:=40;

1: ColWidths[i]:=90;

3..5:ColWidths[i]:=36;

else ColWidths[i]:=57;

end;

end;

procedure TMainForm.DrawGrid1SetEditText(Sender:

TObject; ACol, ARow: Integer;const Value: String);

begin

if (ARow = 1) and (ACol <> 3)

or (ARow = 2) and (ACol <> 4) then

Field[ARow,ACol]:=Value;

if (ARow = 1) and (ACol = 4) then

if Length(Value) > 0 then Field[ARow,3]:=

IntToStr(StrToInt(Value)*8);

if (ARow = 2) and (ACol = 3) then

if Length(Value) > 0 then Field[ARow,4]:=

IntToStr(round(StrToInt(Value)/8));

end;

procedure TMainForm.DrawGrid1SelectCell(Sender:

TObject; ACol, ARow: Integer;var CanSelect: Boolean);

begin

CanSelect:=true;

with DrawGrid1 do

if (ARow = 1) or (ARow = 2) then

if ACol in [0,5..8] then CanSelect:=false;

end;

Наши рекомендации