Главная » C++, C++ Builder » Проверка корректности данных в поле ввода C++ Builder

1

Одна из важных граней многих программ (особенно предназначенных для неопытных пользователей) — проверка того, что введенные данные корректны. Как только данные прошли через приложение, они находятся в постоянном хранилище, например в базе данных, независимо от того, корректны ли они и соответствуют ли нужному формату. Я не могу сказать, сколько раз у меня происходил сбой программы из-за того, что якобы правильные данные, которые она считывала из базы данных, хранились в неправильном формате. Поля, в которых не должно было быть ничего, кроме цифр, содержали буквы, а поля, гарантированно содержащие целые значения, содержали десятичную точку. Этот список можно продолжать долго.

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

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

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

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

Замечание

Исходный код для программы «Проверка ввода» находится в каталоге Chapter4\EditValidation на сопроводительном  компакт-диске.

На рис. 4.7 приведена форма, которую мы будем использовать в этом примере. Чтобы ее получить, нужны два поля ввода (TEdit), три переключателя (TRadioButton) и два поля статического текста в тех позициях, как на рисунке. При помощи этого мы будем проверять ввод несколькими способами.

Рис. 4.7. Форма для примера проверки данных

Когда вы построите визуальную форму, добавьте обработчик выбора переключателя Только цифры. Если этот переключатель установлен, то  компонент  TEdit  (поле  ввода)  над переключателем будем принимать только цифры (от 0 до 9, без десятичной точки) для ввода в поле. Добавьту следующий код в обработчик:

void __fastcall TForm1::RadioButton1Click(TObject *Sender)

{

Label1->Caption = "Вводите только цифры:"; Edit1->OnKeyPress = Edit1Keypress;

}

В приведенном примере мы устанавливаем текст в статическом поле в «Вводите только цифры: ». Это помогает пользователю разобраться, что к чему. После этого мы устанавливаем, что событие KeyPress (нажатие клавиши) поля ввода будет обрабатывать  проверяющая  процедура Edit1KeyPress. Далее следует код для процедуры Edit1KeyPress, которая будет вызываться при нажатии пользователем клавиши в поле ввода Edit1, если установлен первый переключатель:

void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)

{

if ( !isdigit(Key) ) Key = 0;

}

Эта процедура просто проверяет каждый символ, вводимый пользователем. Функция isdigit, находящаяся в заголовочном файле ctype.h, который вам нужно подключить в начале исходного файла для формы, проверяет, лежит ли символ в диапазоне от 0 до 9. Если это так, то функция возвращает TRUE (истина). Иначе функция возвращает FALSE (ложь). Синтаксис !isdigit в C++ означает, что следующий код будет выполняться тогда и только тогда, когда функция  вернет FALSE. Установка параметра Key в 0 говорит компоненту TEdit, что этот символ нужно игнорировать.

Скомпилируйте и запустите программу. Щелкните на первом переключателе, для  которого  мы только что добавляли обработчик и затем щелкните в поле ввода. Попробуйте ввести букву, например «а». Угадайте, что будет? Если вы решили, что символ не попадет в поле ввода, то вы ошиблись. Поле ввода радостно отобразит символ «а», тем самым  руша  стратегию  проверки ввода.

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

Закройте приложение и перейдите в дизайнер форм в CBuilder. Выберите форму, щелкнув где- либо в клиентской области формы, не содержащей компонентов. Или вы можете перейти в Object Inspector и выбрать объект Form1 из выпадающего списка в верхней части окна инспектора. В любом случае перейдите к свойству формы KeyPreview и установите его в TRUE (истина). Скомпилируйте и запустите приложение, и вы заметите, что стало невозможным вводить нецифровые символы в поле ввода.

Свойство KeyPreview формы показывает, передаются ли нажатия клавиш  сначала  в  форму,  а потом уже к выбранному компоненту. Если свойство KeyPreview равно FALSE (ложно), то нажатия клавиш пойдут прямиком к компоненту, имеющему фокус ввода. Если же свойство KeyPreview равно TRUE (как мы только что сделали), то нажатия клавиш будут  приходить сначала к обработчику нажатий уровня формы, такому как наш метод, а только потом будут направлены к компоненту с фокусом ввода. Это позволяет нам просматривать нажатия клавиш и модифицировать под свои нужды. Это возможно из-за того, что обработчики нажатий получают параметр — символ по ссылке (char &Key), что позволяет методу модифицировать значение символа.

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

void __fastcall TForm1::RadioButton2Click(TObject *Sender)

{

Label1->Caption =

"Вводите цифры или десятичную точку: "; Edit1->OnKeyPress = Edit1Keypress2;

}

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

void __fastcall TForm1::EditKeyPress2(TObject *Sender,

char &Key)

{

if ( !isdigit(Key) && Key != ‘.’) Key = 0;

}

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

BOOL bFlag = strchr( Edit1.Text.c_str(), ‘.’);

Тогда если логическое значение bFlag равно TRUE (истина), то вы могли бы также запретить ввод. Последний  обработчик  для  поля  ввода  разрешает  любые  символы.  Вы  думаете,  мы  напишем

обработчик, который каким-либо образом позволяет любые символы? Для этого есть более простой путь. Создайте обработчик для третьего переключателя и добавьте следующий код в обработчик события:

void __fastcall TForm1::RadioButton3Click(TObject *Sender)

{

Label1->Caption = "Вводите что угодно: "; Edit1->OnKeyPress = NULL;

}

Опять же, мы ставим подсказку о том, что за ввод разрешен. Однако, вместо того, чтобы назначить обработчику конкретный метод, мы ставим его в NULL. Это убирает обработку события для этого компонента и передает старшинство стандартному обработчику компонента TEdit (который воспринимает все символы). По ходу дела вам нужно было добавлять прототипы обработчиков событий, которые мы создавали, в заголовочный файл. Если у вас есть вопросы, то вот переделанный заголовочный файл:

class TForm1 : public TForm

{

__published: // IDE-managed components TLabel *Label1;

TEdit *Edit1; TLabel *Label2;

TEdit *Edit2;

TRadioButton RadioButton1; TRadioButton RadioButton2; TRadioButton RadioButton3;

void      fastcall Edit1KeyPress(TObject *Sender, char &Key);

void     fastcall Edit2Exit(TObject *Sender);

void fastcall RadioButton1Click(TObject *Sender); void   fastcall RadioButton2Click(TObject *Sender); void fastcall RadioButton3Click(TObject *Sender); private:  // User declarations

void

fastcall Edit1KeyPress2(TObject *Sender, char &Key);

public: // User declarations

    fastcall TForm1(TComponent *Owner);

}

Поскольку я добавил функцию Edit1KeyPress через CBuilder как обработчик события KeyPress, то она уже находится в части, управляемой CBuilder.

Источник: Теллес М. – Borland C++ Builder. Библиотека программиста – 1998

По теме:

  • Комментарии

1 комментарий

  1. В коде есть БАГ!

    Если мы попробуем стереть значение из поля Edit, ничего не получится.
    код обработчика должен выглядеть так:

    if((!isdigit(Key) && (!iscntrl(Key))) Key=0;

    iscntrl() разрешит нам нажатие backspace