Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как проверить есть ли встроке пробел


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;


Наверх

Титульная страница Поиск, карта сайта Написать письмо