![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Заменя пробелов [D6, Win2k]
Adam © (2003-01-27 18:13:00)Сдраствуйте мастера!
У меня следующяя проблема:
Имеется строка, в которой слова разделяются проделами. Количество пробелов между двумя словами неизвестно, оно может быть разным. Требуется это количество пробелов заменить всего одним пробелом.. Как это сделать? Помогите, пожалуйста..
Digitman (2003-01-29 16:02:00) [61]а-а-а ... я не обратил внимания ...
а чего вхолостую однократно обработанную уже строку гонять в цикле ? если уж на то пошло, нужно было в цикле по десятку тысяч раз прогнать несколько строк с заранее оговоренным содержимым ...
Johnmen (2003-01-29 15:57:00) [62]>Digitman © (29.01.03 14:51)
>> Johnmen
>Чего то я тебя не понял)
Да, не понял ! Имелась в виду процедура тестирования от Юрий Зотов ©.
Digitman (2003-01-29 14:51:00) [63]
> Johnmen
Чего то я тебя не понял)
> После первого же вызова .. строка Srс уже не та,
> что раньше: все слова в Src разделены одним пробелом.
Разумеется ! На то и in-place-алгоритм...
Убирает лишние (ведущие/терминирующие/межсловные) пробелы в указанном блоке памяти со строковыми данными, терминированными #0
> Все последующие итерации цикла просто ничего не делают.
Какие итерации-то ? Вызов уже сделан, Result указывает на тот же блок данных (либо nil, если Src-строка пуста)
Johnmen (2003-01-29 14:36:00) [64]> Юрий Зотов © (29.01.03 14:08)
> Оно входило в общее время.
А нет ли здесь ошибки ? После первого же вызова Digitman() строка Scr уже не та, что раньше: все слова в Src разделены одним пробелом. Все последующие итерации цикла просто ничего не делают.
Юрий Зотов (2003-01-29 14:08:00) [65]> Johnmen © (29.01.03 10:38)
> как учитывалось время на преобразование string<->pchar в
> варианте Digitman?
Оно входило в общее время. Вызов был таким:
S := String(Digitman(PChar(Src)));
Хотя это, возможно, и не совсем корректно - к коду функции фактически добавляется еще несколько машинных команд (хотя, думаю, это мизер по сравнению с количеством команд в самой функции).
Как Вы понимаете, я и не ставил задачей сделать хороший тест. Это всего лишь оценка на скорую руку. Но даже такие и оценочные результаты дают неплохой материал для выводов, не так ли?
REA (2003-01-29 10:58:00) [66]Может борду открыть "Нет пробелам"? Или "Состязания по переходу с Delphi на Assembler". В принципе можно просто "Загадочки". Победителям давать малиновые штаны.
Johnmen (2003-01-29 10:38:00) [67]>Юрий Зотов ©
Q_SpaceCompress не может участвовать в соревновании, т.к. соревнуются коды, написанные на D.
Юрий, как учитывалось время на преобразование string<->pchar в варианте Digitman © ?
MBo (2003-01-29 10:13:00) [68]>Абсолютный рекорд?
Ну так и должно быть - QStrings - хорошо отлаженная и оптимизированная библиотека, обогнать ее довольно сложно, обычно только на специальных, а не на общих задачах.
Кстати, один из ее авторов - Сергей Щербаков (Mover) - входит в число авторов этого сайта.
Юрий Зотов (2003-01-29 09:57:00) [69]Тест Q_SpaceCompress - 9, 10, 13.
Абсолютный рекорд?
Sectey (2003-01-29 09:46:00) [70]>Юрий Зотов
Q_SpaceCompress - лучше.
ReduceSpaces - 891
исходный код из QStrings v6.06
Q_SpaceCompress удаляет из строки начальные и конечные пробелы и управляющие символы (меньше пробела). Кроме того, все подряд ущие пробелы и управляющие символы в середине строки заменяются одним пробелом. Исходная строка при этом не изменяется. Эта функция работает медленнее, чем Q_SpaceCompressInPlace
function Q_SpaceCompress(const S: string): string;
asm
PUSH ESI
MOV ESI,EDX
TEST EAX,EAX
JE @@qt
MOV ECX,[EAX-4]
TEST ECX,ECX
JE @@qt
PUSH EBX
MOV EBX,EAX
XOR EDX,EDX
MOV EAX,ESI
CALL System.@LStrFromPCharLen
MOV ECX,[EBX-4]
MOV EDX,[ESI]
@@lp1: CMP BYTE PTR [EBX],$20
JA @@ex1
INC EBX
DEC ECX
JNE @@lp1
JMP @@wq
@@ex1: DEC ECX
@@lp2: CMP BYTE PTR [EBX+ECX],$20
JA @@lp3
DEC ECX
JMP @@lp2
@@lp3: MOV AL,BYTE PTR [EBX]
INC EBX
CMP AL,$20
JBE @@me
@@nx: MOV BYTE PTR [EDX],AL
INC EDX
DEC ECX
JNS @@lp3
@@wq: MOV EAX,[ESI]
MOV BYTE PTR [EDX],0
SUB EDX,EAX
MOV [EAX-4],EDX
POP EBX
POP ESI
RET
@@me: MOV BYTE PTR [EDX],$20
INC EDX
DEC ECX
JS @@wq
@@ml: MOV AL,BYTE PTR [EBX]
INC EBX
CMP AL,$20
JA @@nx
DEC ECX
JNS @@ml
JMP @@wq
@@qt: MOV EAX,ESI
CALL System.@LStrClr
POP ESI
end;
Delirium^.Tremens (2003-01-29 09:36:00) [71]Заменя пробелов
А за меня - Забоев.
:-)
Separator (2003-01-29 09:33:00) [72]Кто следующий?
Юрий Зотов (2003-01-29 09:29:00) [73]> Digitman © (29.01.03 09:10)
> in-place-вариант удаления лишних пробелов
И его результат - 14, 14, 13.
На сегодня это рекорд. Кто хочет посостязаться?
Sectey (2003-01-29 09:27:00) [74]Люди ну возмите библиотеку QStrings и не надо изобретать велосипед. Там есть функции пости на все случаи жизни. Если кого интеремует намыл.
Я тут произвел небольшой тест и вот что получилось.
Q_SpaceCompress - 688
sha - 797
Romkin - 1468
Separator - 13219
Antosya - 20250
OneSpace - 29845
Song - 389937
StrDelSpace - умер
процедура теста:
procedure TForm1.Button1Click(Sender: TObject);
var
s : string;
t : DWORD;
i : integer;
begin
t := GetTickCount;
for i:= 0 to 1000000 do
begin
s := "ssd sd sd s s sds d s d sd sd s sd s ";
Separator(s);
end;
ShowMessage(s + #13#10 + IntToStr(GetTickCount - t));
end;
Digitman (2003-01-29 09:12:00) [75]Преимущества : нет перераспределения памяти
Недостатки : не будет работать с read-only-строкой
Digitman (2003-01-29 09:10:00) [76]in-place-вариант удаления лишних пробелов:
function ReduceSpaces(Src: PChar): PChar;
var
i,j,c,f: Integer;
k: Boolean;
begin
Result := Src;
if Assigned(Result) then
begin
if Result[0] <> #0 then
begin
i:= 0;
j:= 0;
c:= 0;
f:= 0;
k:= False;
while Result[i] <> #0 do
begin
if Result[i] <> " " then
begin
if not k then
begin
k:= True;
c:= 0;
Inc(f);
end;
if i > j then
Result[j]:= Result[i];
Inc(j);
end
else
begin
if k then
begin
k:= False;
if i > j then
Result[j]:= Result[i];
Inc(j);
end
else
begin
if (f > 0) and (c = 0) then
begin
if i > j then
Result[j]:= Result[i];
Inc(j);
end;
end;
Inc(c);
end;
Inc(i);
end;
if c > 0 then
Dec(j);
Result[j]:= #0;
end
else
Result := nil;
end;
end;
Separator (2003-01-29 08:26:00) [77]
> Anatoly Podgoretsky © (29.01.03 08:08)
Сапасибо за разъяснение, теперь понял
Бук (2003-01-29 08:10:00) [78]> Юрий Зотов © (28.01.03 15:18)
Если Вы внимательно читали тему, то вопрос был не о скоростивыполнения алгоритма, а о том как. И я не ставил перед собой цель написать высокоскоростной алгоритм удаления пробелов. Что касается скорости - все вопросы к Борланду :))
> Что же касается "сердито"... а что это такое - "сердитый алгоритм"?
Не надо придераться к словам....
-----------------------------------
С уважением Бук
Anatoly Podgoretsky (2003-01-29 08:08:00) [79]Ну если не понял, что было тебе сказано, то вот упрощенным русским языком
Нет начальное инициализации возвращаемого значения. Надо в начале сделать Result := "";, Space то ты нинциализировал.
Separator (2003-01-29 07:43:00) [80]
> Юрий Зотов © (29.01.03 01:29)
Укажите мне на ошибку, а то я её что-то не замечаю. Хоть десять раз по циклу запустить, все равно работает правильно. Все пробелы идущие последовательно и имеющие количество большее одного заменяются на один.