Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 26.02.2009, 06:46
Darken Darken вне форума
Прохожий
 
Регистрация: 24.02.2009
Сообщения: 48
Репутация: 10
По умолчанию Проверка на допустимость

Подскажите пожалуйста как проверить, что некотрое поле содержит именно числовое значение, т.е. что пользователь ввел именно цисло (целое или с плавающей точкой) и вопролнить дальнейшие математические действия только если условие выполнено. На PHP можно проверить регулярным выражением примерно так:

PHP код:
{^[a-zA--яА-Я\.\\]+$} 

или что-т о около того, возможно ли такое на Delphi?
как реализуются подобные проверки?
Ответить с цитированием
  #2  
Старый 26.02.2009, 07:36
Аватар для Karsh
Karsh Karsh вне форума
Активный
 
Регистрация: 22.09.2007
Адрес: SPb
Сообщения: 228
Версия Delphi: 7, 2009, XE2
Репутация: 70
По умолчанию

вот процедура проверки строки:
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
  s: string;
  i: Integer;
  f: Double;
begin
  s:= Edit1.Text;
  if TryStrToInt(s, i) then
  begin
    ShowMessage('Целое число');
    exit;
  end;
  if TryStrToFloat(s, f) then
  begin
    ShowMessage('Дробное число');
    exit;
  end;
  ShowMessage('Ошибка!');
end;
Ответить с цитированием
  #3  
Старый 26.02.2009, 09:35
Darken Darken вне форума
Прохожий
 
Регистрация: 24.02.2009
Сообщения: 48
Репутация: 10
По умолчанию

спасибо, работает, НО значения типа 1,35 и т.д. введенные с цифровой клавиатуры воспринимаются как String, если поставить точку через букву ''ю", все работает нормально.... как заставить программу понимать знак вводимый клавишей Del на цифровой клавиатуре как запятую, а не как точку? Заранее огромное спасибо

Последний раз редактировалось Darken, 26.02.2009 в 10:16.
Ответить с цитированием
  #4  
Старый 26.02.2009, 12:18
Аватар для Rokuell
Rokuell Rokuell вне форума
Активный
 
Регистрация: 27.12.2006
Адрес: Псков
Сообщения: 274
Версия Delphi: Delphi 7
Репутация: 497
Сообщение

Необходимо проводить проверку непосредственно при нажатии клавиши.
Функция StrToFloat по умолчанию считает разделителем точку(хм, то что она считает по умолчанию вообще-то зависит от региональных настроек), поэтому надо либо при вводе запятую заменять на точку (как это сделано в приведённом ниже коде), либо собственноручно определять, какой символ использовать в качестве разделителя в десятичых дробях(обычно так и делается для пущей безопасности).

Также стоит сделать проверку, когда вводит пользователь не цифру или не знак разделителя - при этом просто не помещать этот символ в поле ( для этого надо прировнять Key:=#0 )

Необходимо разрешить и некоторые спец. символы - Backspace( #8 ) и Delete ( #46 )

Код:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
 if Key = ',' then Key := '.'
 else
  if not ( Key in [ '0'..'9' , '.' , #8 , #46 ] ) then Key := #0;
end;
__________________
Велик и могуч наш Object Pascal !
ICQ: 357-591-887
Ответить с цитированием
  #5  
Старый 26.02.2009, 13:03
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Rokuell, метод хорош, тут ничего не скажешь (кста, delete можно и не указывать, и так нормально удаляет) я сам его долгое время использовал, но, как говорится, есть одно "но". Данный метод не спасает от copy/paste
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #6  
Старый 26.02.2009, 13:15
Darken Darken вне форума
Прохожий
 
Регистрация: 24.02.2009
Сообщения: 48
Репутация: 10
По умолчанию

совместив два ранее предложенных пожхода получили нечто

PHP код:
var
  
sstring;
  
iInteger;
  
fDouble;

procedure TForm4.Edit1KeyPress(SenderTObject; var KeyChar);
begin
    
if Key '.' then Key := ','      //замена точки запятой
    
else
      if 
not Key in '0'..'9' '.' #8 , #46 ] ) then Key := #0;


  
s:= Edit1.Text;                //проверка ввода
  
if TryStrToInt(sithen
  begin
    Label5
.Caption:='Целое';
    exit;
  
end;
  if 
TryStrToFloat(sfthen
  begin
     Label5
.Caption:='Дробное';
    exit;
  
end;
   
Label5.Caption:='Ошибка';
  
end

Но, почему-то если ввести число 4, например - выдает ошибку, если 44 - тогда пишет, что целое...

И еще хотя это и не нужно в данном проекте, но если ввести число более 12 знаков - выдает, что оно дробное, почему?
Ответить с цитированием
  #7  
Старый 26.02.2009, 14:47
Аватар для Karsh
Karsh Karsh вне форума
Активный
 
Регистрация: 22.09.2007
Адрес: SPb
Сообщения: 228
Версия Delphi: 7, 2009, XE2
Репутация: 70
По умолчанию

Цитата:
Сообщение от Darken
Но, почему-то если ввести число 4, например - выдает ошибку, если 44 - тогда пишет, что целое...
В твоей процедуре сначала проверяется строка в Edit, а потом добавляется значение нажатой клавиши, т.е. если нажать 4 в пустом поле, то сначала провериться пустая строка (отсюда и "ошибка"), а потом добавиться "4". Чтобы этого избежать, необходимо "перенести" эту процедуру в события OnKeyUp, например так:
Код:
var
  s: string;
  i: Integer;
  f: Double;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
    if Key = '.' then Key := ','      //замена точки запятой
    else
      if not ( Key in [ '0'..'9' , '.' , #8 , #46 ] ) then Key := #0;
end;

procedure TForm1.Edit1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  s:= Edit1.Text;                //проверка ввода
  if TryStrToInt(s, i) then
  begin
    Label5.Caption:= s + ' Целое';
    exit;
  end;
  if TryStrToFloat(s, f) then
  begin
     Label5.Caption:= s + ' Дробное';
    exit;
  end;
   Label5.Caption:= s + ' Ошибка';
end;

Цитата:
Сообщение от Darken
И еще хотя это и не нужно в данном проекте, но если ввести число более 12 знаков - выдает, что оно дробное, почему?
превышен лимит Integer

Последний раз редактировалось Karsh, 26.02.2009 в 14:51.
Ответить с цитированием
  #8  
Старый 27.02.2009, 01:22
Аватар для Rokuell
Rokuell Rokuell вне форума
Активный
 
Регистрация: 27.12.2006
Адрес: Псков
Сообщения: 274
Версия Delphi: Delphi 7
Репутация: 497
Сообщение Обработка

Цитата:
Сообщение от Aristarh Dark
Rokuell, метод хорош, тут ничего не скажешь (кста, delete можно и не указывать, и так нормально удаляет) я сам его долгое время использовал, но, как говорится, есть одно "но". Данный метод не спасает от copy/paste

Ну что ж, если надо ещё контроль над вставкой, то:

1. В моём варианте комбинация Ctrl+C и так не работает ( т.к. 'C' - это не цифра )

2. Есть ещё комбинация клавиш для вставки Shift+Ins
Для её контроля можно добавить код:
Код:
procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
 if ( ssShift in Shift ) and ( Key = VK_INSERT ) then Key := 0;
end;

3. Но! Вставить в Edit можно ещё одним способом - кликнув правой кнопкой мыши и выбрав пункт меню "Вставить".
И вот если надо контролировать ещё и это, то надо использовать другой вариант.

Общий вариант для всех 3х случаев:

1. В секцию формы private добавляем переменную и новую процедуру:
Код:
private
    StdEditProc : procedure (var Msg:TMessage) of object;
    procedure EditProc(var Msg:TMessage);

2. При создании формы заменяем стандартый обработчик сообщения у Edit на самописный, предварительно сохраняя стандартный:
Код:
procedure TForm1.FormCreate(Sender: TObject);
begin
 StdEditProc := Edit1.WindowProc;
 Edit1.WindowProc := EditProc;
end;

3. И в нашем обработчике пишем:
Код:
procedure TForm1.EditProc(var Msg: TMessage);
begin
 Case Msg.Msg of
  WM_PASTE: ; // ничего не делаем, поэтому вставка не происходит
  WM_KEYDOWN,WM_KEYUP,WM_CHAR: begin
                        // Если это запятая ( 44 - это её ASCII код )
                        if Msg.WParam = 44 then
                         begin
                          // Заменяем на точку
                          Msg.WParam := 46;
                          // И вызываем стандартный обработчик 
                          StdEditProc(Msg); 
                         end
                        else
                         if Msg.WParam in [8,37,39,46,48..57]
                         then StdEditProc(Msg);
                         // 8 - backspace
                         // 37 и 39 - VK_LEFT и VK_RIGHT
                         // 46 - точка
                         // 48..57 - '0'..'9'
                         // Для других символов ничего не происходит
                       end;
  Else StdEditProc(Msg);
 End;
end;
__________________
Велик и могуч наш Object Pascal !
ICQ: 357-591-887
Ответить с цитированием
  #9  
Старый 27.02.2009, 06:02
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Класс, только одно замечание:
46 (точка) заменить на ord(DecimalSeparator) и вообще будет гут.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #10  
Старый 27.02.2009, 07:25
Darken Darken вне форума
Прохожий
 
Регистрация: 24.02.2009
Сообщения: 48
Репутация: 10
По умолчанию

очень интересный и познавательный топ получился, всем спасибо, добавил в избранное
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

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

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 07:33.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter