![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как проверить есть ли встроке пробел
Nick © (2008-05-29 16:59:00)Как проверить есть ли встроке пробел
Loginov Dmitry (2008-05-31 19:01:00) [1]Малюсенькое замечание по новой PosEx() :))
Раньше (в D7) в PosEx() в качестве индекса можно было передать 0, и он выполнял поиск с начала строки. В D2006 и далее PosEx() отказывается работать, если задать нулевой индекс. Может быть это работает более эффективно, однако появилась несовместимость с предыдущими версиями. Имхо, раньше удобнее было :)
Renegat (2008-05-31 18:46:00) [2]Печально =(
Мдя. Что МАСМу хорошо, то Делфям смерть...
*ушёл в газенваген, вернусь не скоро*
Sha (2008-05-31 18:09:00) [3]> Anatoly Podgoretsky © (31.05.08 18:01) [12]
Согласен. Но парень осваивает ассемблер, а это надо пощрять.
> Renegat (31.05.08 13:49) [9]
10. Выполняя следующую последовательность операторов получаем 6,5, вместо 6,6:
ShowMessage(IntToStr(RChPos('123456','6')));
ShowMessage(IntToStr(RChPos('123466','6')));
Т.е. функция ищет справа, но иногда немножко слева.
Anatoly Podgoretsky (2008-05-31 18:01:00) [4]То есть не функция, а сплошной глюк.
Sha (2008-05-31 17:49:00) [5]> Renegat (31.05.08 13:49) [9]
9. Фасткодовсие функции, как и RTL, никогда не читают данные за пределами двойного слова, в котором лежит терминатор. Твоя читает, что может привести к AV. Строить пример мне не хочется, но можешь поверить на слово. А еще лучше скачай соответствуюшие "Validation and Benchmark Tools", там множество тестов.
Sha (2008-05-31 16:26:00) [6]> Renegat (31.05.08 13:49) [9]
Быстрая программа никому не нужна, усли она работает неправильно :)
Я бы не рекомендовал пользоваться функцией приведенной в [5], т.к.:
1. Порядок следования аргументов в ней отличается от стандартной Pos и от фасткодовской CharPos, что может озадачить пользователя.
2. Ее результат имеет тип dword, что также отличается от общепринятого, как следствие, мы получаем варнинги при вычислениях с целыми на операторах видаi:=i+RChPos(s,'1');
3. При использовании этой функции на пустых строках получаем AV.
4. Выполняя следующую последовательность операторов получаем
6,5,4,3,0,0, вместо 6,5,4,3,2,1:
ShowMessage(IntToStr(RChPos('123456','6')));
ShowMessage(IntToStr(RChPos('123456','5')));
ShowMessage(IntToStr(RChPos('123456','4')));
ShowMessage(IntToStr(RChPos('123456','3')));
ShowMessage(IntToStr(RChPos('123456','2')));
ShowMessage(IntToStr(RChPos('123456','1')));
5. Выполняя следующую последовательность операторов получаем
4,0,0,0, вместо 0,3,2,1:
ShowMessage(IntToStr(RChPos('123',#0)));
ShowMessage(IntToStr(RChPos('123','3')));
ShowMessage(IntToStr(RChPos('123','2')));
ShowMessage(IntToStr(RChPos('123','1')));
7. Выполняя следующую последовательность операторов получаем 7 вместо 0:
s:='123456';
s:=s+'7';
SetLength(s,5);
i:=RChPos(s,'7');
ShowMessage(IntToStr(i));
8. И, наконец, по поводу скорости. Фасткодовские функции полностью совместимы с RTL и много чего учитывают. Например, они нормально работают со строками нулевой длины даже тогда, когда указатель на данные не равен nil. Поэтому съэкомив на чем-нибудь, можно попытаться их обогнать. Но даже после истравления всех твоих ошибок, уверен, Фасткодовские функции будут обгонять твою на строках порядка 200 знаков. На коротких строках все функции быстры, различие наблюдается в основном из-за несовершенства метода измерения.
Успехов в дальнейшей работе :)
Renegat (2008-05-31 13:49:00) [7]> за 10^6 проходов
10^8, прошу прощения.
Renegat (2008-05-31 13:46:00) [8]> Так быстро, что ты отдыхаешь :))
Уважаемый господин Johnmen, Вы оскорбили меня в лучших чувствах! +)
Если бы Вы соблаговолили посмотреть код функций POS и иже с ними из этого набора, то Вы увидели бы, что приведённый в данном треде алгос есть не что иное как в несколько раз урезанная и упрощённая модификация того, что представлено на данном сайте. Ибо, как я уже говорил,
> Алгоритм, конечно, стар как мир
Но если уж нужны измерения, то для строки 'abcdefghijklmnop' и паттерна 'h' за 10^6 проходов самая быстрая в либах Фасткода процедура отработала за 1891 мс, выложенная мной - за 1408 мс. Результат естессно один и тот же - 8. Вывод: йа не отдыхаю, йа работаю %)
ЗЫЖ сорри за флуд.
Johnmen (2008-05-29 18:50:00) [9]Ага. А здесь ещё быстрее http://fastcode.sourceforge.net
Так быстро, что ты отдыхаешь :))
И что дальше?
Renegat_ (2008-05-29 18:05:00) [10]вызывать так:
i:=RChPos(str_to_find_spaces, ' ');
обход строки идёт с конца. Поэтому возвернётся не первый пробел в строке, а последний. Однако для проверки наличия - сойдёт...
Renegat_ (2008-05-29 18:03:00) [11]Для поиска одного символа рекомендую вот это. Работает гораздо быстрее, нежели Pos.
function RChPos(_s:string; _c:Char):DWORD;
asm
PUSH EBX;
PUSH EDI;
// <-- Забивка всего EDX паттерном символа
MOV DH, DL;
MOVZX ECX, DX;
SHL EDX, 16;
OR EDX, ECX;
// <-- ЕСХ = длина_строки + 4
MOV ECX, DWORD PTR [EAX-4];
ADD ECX, 4;
@loop:
ADD ECX, -4;
JL @nqlp; // <-- Достигнуто начало строки и до сих пор ничего не найдено? Выходим
MOV EBX, DWORD PTR [EAX+ECX];
XOR EBX, EDX; // <-- Зануляются все вхождения нужного символа
LEA EDI, [EBX-01010101h];
NOT EBX;
AND EDI, EBX; // <-- 00h-01h=0FFh. NOT(00h) тоже равно 0FFh.
AND EDI, 80808080h; // <-- Где был 0FFh, там стала единица в знаковом разряде
JE @loop;
// <-- Перевод позиции первого включённого бита в позицию символа
BSF EDI, EDI;
SHR EDI, 3;
LEA EAX, [ECX+EDI+1];
POP EDI;
POP EBX;
RET;
@nqlp:
POP EDI;
POP EBX;
XOR EAX, EAX; // <-- Символа в строке нет - вернём 0
RET;
end;
ЗЫ Алгоритм, конечно, стар как мир, однако до сих пор эффективен =)
korneley (2008-05-29 17:10:00) [12]Я видел у некоторых исполнителей, что-то похожее на
Memo1.Text := AnsiReplaceStr(MyStr, #32, #13#10);
ShowMessage('Количество пробелов: ' + inttostr(Memo1.Lines.Count));
Сергей М. (2008-05-29 17:08:00) [13]
> !!!
Угу, наоборот)
han_malign (2008-05-29 17:03:00) [14]
> Pos('стр ока', ' ')
Pos(' ','стр ока') !!!
Сергей М. (2008-05-29 17:01:00) [15]ВСтрокеЕстьПробел := Pos('стр ока', ' ')>0;