Буквенный или цифровой введен символ
Модератор: Модераторы
-
Sergey_Afanasyev
- новенький
- Сообщения: 49
- Зарегистрирован: 22.02.2012 19:30:27
Буквенный или цифровой введен символ
Пользователь может ввести в окно ввода или фамилию или код сотрудника, который состоит из цифр. По первому введенному символу нужно определить как будет
производится поиск. Если это цифра – то по шифру. В программе написано
ss1 := TRIM(Edit1.Text);
ss2 := Utf8Copy(ss1,1,1);
if (ss2='0') or (ss2='1') or (ss2='2') or (ss2='3') or (ss2='4') or
(ss2='5') or (ss2='6') or (ss2='7') or (ss2='8') or (ss2='9') then
begin
// Поиск по шифру
End;
Как записать это более грамотно не перечисляя все цифры ?
производится поиск. Если это цифра – то по шифру. В программе написано
ss1 := TRIM(Edit1.Text);
ss2 := Utf8Copy(ss1,1,1);
if (ss2='0') or (ss2='1') or (ss2='2') or (ss2='3') or (ss2='4') or
(ss2='5') or (ss2='6') or (ss2='7') or (ss2='8') or (ss2='9') then
begin
// Поиск по шифру
End;
Как записать это более грамотно не перечисляя все цифры ?
Код: Выделить всё
if ss1[1] in ['0'..'9'] then ...Код: Выделить всё
if (ss1[1]>='0') and (ss1[1]<='9') then ...-
Sergey_Afanasyev
- новенький
- Сообщения: 49
- Зарегистрирован: 22.02.2012 19:30:27
Большое спасибо. Оба варианта хорошо работают.
По моему мнению, первый пример затратит меньше времени выполнения (могу ошибаться / подскажите...), т..е более-актуален. Вопрос ответами исчерпан ))
Deimos,
позволите поинтересоваться, на чем основано ваше мнение?
Вы провели сравнительные замеры производительности и/или посчитали такты в ассемблерном листинге?
У вас было еще какое-то обоснование, которое по непонятным причинам не было приведено?
Добавлено спустя 23 минуты 57 секунд:
Кстати, код, генерируемый 2.6.4 для b:=s[1] in ['0'..'9'], ничего общего с проверкой на принадлежность множеству не имеет, временное множество не конструируется, код действительно эффективнее 2-го случая:сравните с:С ключом -O1 ситуация улучшается:С -O2 или -O3 всё ещё лучше:
позволите поинтересоваться, на чем основано ваше мнение?
Вы провели сравнительные замеры производительности и/или посчитали такты в ассемблерном листинге?
У вас было еще какое-то обоснование, которое по непонятным причинам не было приведено?
Добавлено спустя 23 минуты 57 секунд:
Кстати, код, генерируемый 2.6.4 для b:=s[1] in ['0'..'9'], ничего общего с проверкой на принадлежность множеству не имеет, временное множество не конструируется, код действительно эффективнее 2-го случая:
Код: Выделить всё
; [5] b:=s[1] in ['0'..'9'];
movzx eax,byte ptr [U_P$PROGRAM_S+1]
sub eax,48
cmp eax,10
jb @@j5
@@j5:
setc byte ptr [U_P$PROGRAM_B]
Код: Выделить всё
; [6] b:=(s[1]>='0') and (s[1]<='9');
mov al,byte ptr [U_P$PROGRAM_S+1]
cmp al,48
jae @@j8
jmp @@j7
@@j8:
mov al,byte ptr [U_P$PROGRAM_S+1]
cmp al,57
jbe @@j6
jmp @@j7
@@j6:
mov byte ptr [U_P$PROGRAM_B],1
jmp @@j9
@@j7:
mov byte ptr [U_P$PROGRAM_B],0
@@j9:
Код: Выделить всё
; [6] b:=(s[1]>='0') and (s[1]<='9');
mov al,byte ptr [U_P$PROGRAM_S+1]
cmp al,48
jnae @@j7
mov al,byte ptr [U_P$PROGRAM_S+1]
cmp al,57
jnbe @@j7
mov byte ptr [U_P$PROGRAM_B],1
jmp @@j9
@@j7:
mov byte ptr [U_P$PROGRAM_B],0
@@j9:
Код: Выделить всё
; Var b located in register al
; [6] b:=(s[1]>='0') and (s[1]<='9');
cmp al,48
jnae @@j7
cmp al,57
jnbe @@j7
mov al,1
jmp @@j11
@@j7:
mov al,0
@@j11:
бог мой! Уже регэкспы бедняге предлагаются
Коллеги, почему по этому случаю позабыто самое традиционное?
if (pos(ss2,'0123456789')<>0) ...
или еще идеологически правильнее:
if (utf8pos(ss2,'0123456789')<>0) ...
Коллеги, почему по этому случаю позабыто самое традиционное?
if (pos(ss2,'0123456789')<>0) ...
или еще идеологически правильнее:
if (utf8pos(ss2,'0123456789')<>0) ...
SSerge писал(а):Коллеги, почему по этому случаю позабыто самое традиционное?
Потому что за такой код, как и за регулярки, при решении подобной задачи, надо хватать такого "программиста" и депортировать его обратно в Индию.
bormant писал(а):Deimos,
позволите поинтересоваться, на чем основано ваше мнение?
Вы провели сравнительные замеры производительности и/или посчитали такты в ассемблерном листинге?
У вас было еще какое-то обоснование, которое по непонятным причинам не было приведено?
Замечу свое-же
могу ошибаться
Нет, замеров я не делал.
Исходил из логики, что в первом случае используется одна операция проверки вхождения в последовательность, во втором - 10 операций сравнений. Тактов, опять-же, не считал... Как конкретно реализованы оба эти варианта в компиляторе, я не знаю, исходя из чего я и упомянул, что это мое мнение...
bormant писал(а):Кстати, код, генерируемый 2.6.4 для b:=s[1] in ['0'..'9'], ничего общего с проверкой на принадлежность множеству не имеет, временное множество не конструируется
прочел позднее ответа. Информация полезна - спасибо.
pda писал(а):Потому что за такой код, как и за регулярки, при решении подобной задачи, надо хватать такого "программиста" и депортировать его обратно в Индию.
формально он ничем не хуже решения из самого первого поста темы
Истинно индусский код - он не такой, а что-то типа:
Код: Выделить всё
i:byte^;
i:=(pbyte)@ss1;
if (i>=48 and i<(48+10)) then ...
2 SSerge
Вы дважды уже допускаете ошибку (в двух последних комментариях), и поэтому, лично я, поддерживаю:
P.S. Ничего личного...
Вы дважды уже допускаете ошибку (в двух последних комментариях), и поэтому, лично я, поддерживаю:
pda писал(а):депортировать его обратно в Индию
P.S. Ничего личного...
оставлю это здесь для коллекции решений...
todo: заменить динамическую инициализацию Nums (через InitNumsTable) - статической и сделать его const а не var!
Код: Выделить всё
var
Nums : array [Char] of boolean;
..
if Nums[ss2[1]] then
begin
// Поиск по шифру
End;
...
procedure InitNumsTable;
var
i : char;
begin
FillChar(Nums, sizeof(Nums), 0);
for i:='0' to '9' do
Nums[i]:=true;
end;
initialization
InitNumsTable;
todo: заменить динамическую инициализацию Nums (через InitNumsTable) - статической и сделать его const а не var!
pda писал(а):Потому что за такой код, как и за регулярки, при решении подобной задачи, надо хватать такого "программиста" и депортировать его обратно в Индию.
Ну как сказать, в коде предпочтительней понятность его чтения, и вариант
не так уж плох, так как работает с любыми символами и кодировкамиSSerge писал(а):pos(ss2,'0123456789')<>0) ...
Regexp же способен заменить тонну кода одним выражением, кроме того это стандарт и может использовать уже существующие выражения, такие, как проверка email
Вот еще один способ (2.7.x); работающий, кстати. кто больше?
Код: Выделить всё
{$mode objfpc}
{$H+}
uses character;
function StartsAsDigit(s:string):boolean;
begin
if (length(s)<1) then
result:=FALSE
else
result:=TCharacter.IsDigit(s[1]);
end;
