Опубликован: 07.04.2008 | Доступ: свободный | Студентов: 11836 / 2840 | Оценка: 4.44 / 4.10 | Длительность: 20:15:00
Специальности: Программист, Преподаватель
Лекция 15:

Преобразования типов

< Лекция 14 || Лекция 15: 12 || Лекция 16 >

Другие преобразования

Иногда, чтобы преобразовать один тип данных в другой, достаточно указать этот тип:

var
   p : PChar;
   s : String;
begin
   p := 'Строка';
   s := String(p);
   p := PChar(s);

В других случаях, схожие типы данных можно просто присваивать друг другу. Компилятор в этом случае сам произведет нужное преобразование. Например, целый тип данных можно присвоить вещественному числу, компилятор сам подставит ноль. А вот наоборот не получится, ведь вещественное число рассматривается, как два целых числа:

var
   f : Real;
   i : Integer;
begin
   i := 12;
   f := i; //Результат: 12,0
   i := f; //Ошибка! Так нельзя

Подстановка значений

Очень часто в языках программирования для элегантности кода подставляют одно значение вместо другого. Сравните два примера:

var
   s : String;
   i : Integer;
begin
   s := Edit1.Text;
   i := StrToInt(s);
end;

Все, что мы сделали в данном примере, так это присвоили переменной i число из Edit1, которое хранилось там в виде строки. Но для этого нам пришлось вначале занести эту строку в строковую переменную s, и уже ее обрабатывать функцией StrToInt(). Такой пример вполне будет работать, однако он слишком громоздок. Гораздо элегантнее выглядит следующий код:

var
   i : Integer;
begin
   i := StrToInt(Edit1.Text);
end;

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

i := StrToInt(Memo1.Lines[5]) + StrToInt(Edit1.Text);
s := IntToStr(StrToInt(Memo1.Lines[5]) + StrToInt(Edit1.Text));

В первой строке в целую переменную i мы вывели сумму целых чисел, которые хранились в виде строки в Edit1 и в пятой строке Memo1.

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

i := StrToInt(Memo1.Lines[5]);
k := StrToInt(Edit1.Text);
m := i + k;
s := IntToStr(m);

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

Глобальная переменная DecimalSeparator

Это неявная глобальная переменная. Неявная, потому что вы ее нигде не описывали, и в коде модуля ее нет. Однако Delphi самостоятельно создает эту и некоторые другие глобальные переменные для каждого нового проекта, так что вы спокойно можете ей пользоваться.

Что это за переменная? Она хранит один символ – разделитель между целой и десятичной частью вещественного числа. И разделителем может быть либо точка, либо запятая. В русских версиях Windows чаще всего используется запятая, хотя можно перенастроить операционную систему так, что будет точка. А вот в английских ОС – точка. Если вы делаете программу только для личного использования, то смело можете устраивать проверку на ввод вещественных чисел, и в качестве разделителя указывать запятую. Но если вы делаете программу для клиента, то не можете быть уверены, какой разделитель там стоит. Ведь он может использовать вашу программу и на английской версии Windows! Тогда программа будет выдавать ошибку сразу, как дело дойдет до ввода вещественного числа.

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

Создайте новый проект, и установите на него компонент Edit для ввода вещественного числа. Ниже поместите Memo, сюда мы будем выводить это число, отформатированное разными способами с помощью FormatFloat(). Еще ниже – кнопку для того, чтобы начать заполнять Memo. Первым делом мы с вами установим "защиту от дураков" - проверку компонента Edit, чтобы пользователь не смог ввести туда ничего, кроме целого или вещественного числа. При этом мы будем в качестве разделителя использовать переменную DecimalSeparator, и кроме того, проверим, чтобы она не встречалась более одного раза. Затем эту же проверку без изменений вы сможете применять в любых последующих ваших проектах, где потребуется необходимая проверка. Для Edit1 создаем обработчик события OnKeyPress, которое вызывается всякий раз, когда пользователь нажимает любую клавишу при вводе текста в компонент Edit. Впишем следующий код:

case Key of
    '0'..'9': ; //числа разрешаем
    //если разделителя еще нет - выводим правильный разделитель,
    //иначе ничего не выводим
    ',' , '.' :  if Pos(DecimalSeparator, Edit1.Text)= 0 then
                    Key := DecimalSeparator
               else Key := Chr(0);
    #8 : ; //backspace
    //разрешаем отрицательное число, если минус идет первым символом
    '-': if (Pos('-', Edit1.Text) = 1) or
            (Length(Edit1.Text) >0) then Key := Chr(0);
    #13 : Button1.SetFocus;
  else Key := Chr(0);
  end; //case

Этот код требует некоторых пояснений. Событие OnKeyPress компонента Edit самостоятельно создает параметр Key, это переменная типа Char, то есть, символ. В этой переменной содержится символ, введенный пользователем. Поскольку символ – перечисляемое значение (то есть, он может быть от 0 до 255), можно использовать конструкцию case. В качестве селектора указываем переменную Key, а в качестве значения указываем то значение, которое там может находиться. Строка

'0'..'9': ; //числа разрешаем

показывает, что если были введены символы от 0 до 9, то ничего не происходит (после знака ":" нет действующих операторов). Здесь мы можем извлечь новое правило: можно показывать диапазон числовых или символьных значений через знак "..", например, 'a'..'z'; 1..9. Далее идут строки:

',' , '.' :  if Pos(DecimalSeparator, Edit1.Text)= 0 then
                    Key := DecimalSeparator
               else Key := Chr(0);

Этот код дает нам новое правило: через запятую можно указать возможные значения. То есть, блок кода будет выполняться, если пользователь ввел либо запятую, либо точку. В самом блоке кода мы проверяем: нет ли уже в строке нужного разделителя? Если нет ( Pos() вернула ноль), то мы записываем в переменную Key нужный разделитель, иначе присваиваем ей нулевой символ (то есть пользователь ничего не ввел). При этом неважно, точку или запятую ввел пользователь – разделитель все равно будет правильным.

Далее, если пользователь ввел символ #8 (нажал <BackSpace>), то ничего не делаем – то есть, разрешаем этот символ. Надо же оставить ему возможность редактировать свой текст, исправлять ошибки. И снова правило: можно указать номер символа, используя функцию Chr(), либо просто после символа "#":

Key := Chr(8);
Key := #8;

В обоих случаях, в переменную Key попадет символ, который в таблице символов идет под номером 8.

Далее мы смотрим, не минус ли ввел пользователь? Если да, то смотрим, какова длина строки. Ведь если длина строки больше нуля, значит, в ней уже есть символы, и минус разрешать нельзя. В случае же, если строка еще не содержит ничего, то минус допустим, и блок кода if не выполнится.

Если пользователь нажал <Enter>, Key будет содержать символ #13. Обычно пользователь нажимает <Enter>, когда он закончил ввод текста. Строка

#13 : Button1.SetFocus;

передает фокус (то есть, выделение компонента) на кнопку, если нажата клавиша <Enter>.

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

В процедуре нажатия кнопки пишем такой код:

var
  f : Real;
begin
   f := StrToFloat(Edit1.Text);
  Memo1.Lines.Add(FormatFloat('', f));
  Memo1.Lines.Add(FormatFloat('0,000.00', f));
  Memo1.Lines.Add(FormatFloat('#,###.##', f));
  Memo1.Lines.Add(FormatFloat('#.##', f));
  Memo1.Lines.Add(FormatFloat('0.00', f));
  Memo1.Lines.Add('---------------'); //разделитель
end;

Тут все понятно – сначала преобразуем полученное число в виде строки, в вещественное число. Затем это число выведем в Memo, придав ему различные форматы. Сохраните пример, скомпилируйте его и посмотрите, как работает программа. В дальнейшей практике вам не раз придется ставить подобную "защиту от дураков", данный пример события OnKeyPress можно будет просто копировать в любую программу.

< Лекция 14 || Лекция 15: 12 || Лекция 16 >
Виктор Пелих
Виктор Пелих

Здравствуйте.
Прохожу курс "Введение в программирование на Delphi"
Добрался до Лекции 29: Введение в базы данных.

Установлена RAD Studio 11.3, у которой отсутствует вкладка BDE и, соответственно, компонент Table,  который обеспечивает доступ к таблице средствами механизма BDE.
Поиск в интернете подсказал 
BDE Installer for RAD Studio, Delphi, C++Builder 10.3 Rio
Подскажите, имеется ли ещё возможность использовать механизм BDE в Delphi11 и если такая возможность есть, как подключить BDE к Delphi11?
С уважением...

 

Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

как я получу диплом о профессиональной переподготовке?