Форум: "Основная";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];
ВнизФункция, убирающая пробелы в строке Найти похожие ветки
← →
Ученик2 (2004-02-11 17:58) [0]никто не подскажет, есть ли такая функция?
а то самому писать не очень хочется
← →
MBo (2004-02-11 17:59) [1]>а то самому писать не очень хочется
а придется
← →
Юрий Федоров (2004-02-11 17:59) [2]StringReplace
← →
TUser (2004-02-11 18:06) [3]function DeleteSpaces(s:string):string;
begin
while pos(" ",s) do
delete(s,pos(" ",s),1);
result:=s;
end;
Ctrl-C->Ctrl-V
← →
Ученик2 (2004-02-11 18:13) [4]to TUser
у Юрия Федотова прикольнее
← →
Amoeba (2004-02-11 18:27) [5]Скачай библиотеку QStrings
function Q_DeleteText(var S: string; const SubStrToDel: string): Integer;
{ Q_DeleteText удаляет из строки S все вхождения подстроки SubStrToDel. Поиск
подстроки ведется без учета регистра символов. Функция возвращает количество
найденных (и удаленных) фрагментов. }
procedure Q_ReplaceCharsByOneChar(var S: string; const ChOldSet: TCharSet;
ChNew: Char);
← →
VID (2004-02-11 18:29) [6]Бысрее, потому что не дёргает POS постоянно
function DeleteSpaces2(s:string):string;
Var I,L:Integer;
begin
Result := "";
L:=Length(S);
IF L = 0 then exit;
For i := L downto 1 do
IF S[i] = " " then
Delete(S, I, 1);
result:=s;
end;
Ctrl-C->Ctrl-V
← →
Владислав (2004-02-11 18:30) [7]> TUser © (11.02.04 18:06) [3]
Не завидую тому, кто использует pos на современных процах в реализации D6 и ниже (как на счет выше, не знаю). Конечно, если разговор не о строках размером в пару килобайт и меньше.
Гораздо быстрее работает сканирование от конца строки с Move. При чем алгоритм - проще, наверное, не бывает.
Вот пример:
procedure RemoveChars(var AStr: string);
var
LOriginLen: Integer;
LLen: Integer;
LCurChar: PChar;
LRemoveChars: PChar;
LSource: PChar;
LNextSource: PChar;
LDest: PChar;
LCount: Integer;
LFound: Boolean;
begin
LOriginLen := Length(AStr);
if LOriginLen = 0 then
Exit;
LLen := (LOriginLen shl 1) + Length(CRLF);
SetLength(AStr, LLen);
LCurChar := Pointer(AStr);
LSource := LCurChar;
LDest := LCurChar;
Inc(LDest, LOriginLen);
LDest^ := CR;
Inc(LDest);
LDest^ := LF;
Inc(LDest);
LFound := False;
while LCurChar <= (PChar(Pointer(AStr)) + LOriginLen) do
begin
if LCurChar^ in [ #$21..#$2F] then
begin
LFound := True;
LRemoveChars := LCurChar;
while LCurChar^ in [ #$21..#$2F] do
Inc(LCurChar);
LNextSource := LCurChar;
LCount := LRemoveChars - LSource;
if LCount = 0 then
begin
LSource := LNextSource
end
else
begin
Move(LSource^, LDest^, LCount);
LSource := LNextSource;
Inc(LDest, LCount)
end
end;
Inc(LCurChar)
end;
LCount := (PChar(Pointer(AStr)) + LOriginLen) - LSource;
if LCount > 0 then
begin
Move(LSource^, LDest^, LCount);
Inc(LDest, LCount)
end;
LLen := LOriginLen;
if LFound then
LLen := LDest - PChar(Pointer(AStr));
SetLength(AStr, LLen)
end;
Процедура удаляет из строки символы в диапазоне [ #$21..#$2F]
← →
Sandman25 (2004-02-11 18:32) [8]SetLength(Result, Length(S));
J := 0;
for I := 1 to Length(S) do
begin
if S[I] <> " " then
begin
inc(J);
Result[J] := S[I];
end;
SetLength(Result, J);
← →
Владислав (2004-02-11 18:36) [9]> VID © (11.02.04 18:29) [6]
Ну его нафиг этот Delete.
> Amoeba © (11.02.04 18:27) [5]
QStrings надо юзать с умом. Некоторые функции от туда работают с некоторыми ограничениями. Они в большинстве случаев срабатывают (предположения), но в частных случаях могут не работать. Хотя библиотека очень быстро работает.
← →
Владислав (2004-02-11 18:38) [10]> Sandman25 © (11.02.04 18:32) [8]
То же не фигово. Только памяти в два раза больше занимает.
← →
Sandman25 (2004-02-11 18:39) [11][10] Владислав © (11.02.04 18:38)
Не обязательно. Если у параметра счетчик ссылок был больше 1, то все равно при изменении придется заводить новую строку.
← →
Digitman (2004-02-11 18:45) [12]
> Ученик2 (11.02.04 17:58)
лишние ? т.е терминирующие + лидирующие + более чем один между "словами" ? или в принципе - "долой пробелы !" ?
← →
Владислав (2004-02-11 18:46) [13]> Sandman25 © (11.02.04 18:39) [11]
SetLength(Result, Length(S));
Это говорит об обязательности.
← →
Владислав (2004-02-11 18:48) [14]> Digitman © (11.02.04 18:45) [12]
В точку вопрос ;)
← →
Тимохов (2004-02-11 18:48) [15]может ему trim нежен?
← →
Sandman25 (2004-02-11 18:49) [16][13] Владислав © (11.02.04 18:46)
Я имел ввиду, что при изменении/удалении одного символа в параметре произойдет полное копирование всей строки. И в таком случае мой алгоритм требует столько же памяти, сколько и другие.
← →
Тимохов (2004-02-11 18:52) [17]
> Я имел ввиду, что при изменении/удалении одного символа
> в параметре произойдет полное копирование всей строки. И
> в таком случае мой алгоритм требует столько же памяти, сколько
> и другие.
ИМОХ вы не правы.
Если это делать через move, то копирование не будет.
← →
Владислав (2004-02-11 18:52) [18]> Sandman25 © (11.02.04 18:49) [16]
Не все. Глянь [7]. Там такого нет.
← →
Sandman25 (2004-02-11 18:54) [19][17] Тимохов © (11.02.04 18:52)
Согласен. Но в принципе, неважно, как делать.
Была строка "qwer tyu", на которую указывали 2 переменные.
После удаления пробела получаем 2 строки:
"qwer tyu" и "qwertyu". Памяти требуется почти столько же, как в моем алгоритме.
← →
Sandman25 (2004-02-11 18:55) [20][18] Владислав © (11.02.04 18:52)
См. [19]. Почти все. Если, конечно, у нас в строке не 50% пробелов :)
← →
Владислав (2004-02-11 19:11) [21]> Sandman25 © (11.02.04 18:55) [20]
Ошибаешься, однако :)
← →
Тимохов (2004-02-11 19:14) [22]Владислав.
Вот я над вами посмеюсь когда НЭТ придет - как же, поюзаешь там move :))))))) Метод классный - я его даже себе взял, на память. Но ведь переделывать имхо придется все.
← →
Владислав (2004-02-11 19:22) [23]> Тимохов © (11.02.04 19:14) [22]
Смейтесь... Придет, буду плакать. За то сейчас мои пользователи улыбаются. Раньше на все тратилось в два раза больше времени, а сейчас я его съекономил. Там еще много всяких "штучек" используется. Вот пример:
...
asm
MOV EAX, LMessage
MOV EDX, LMessageLen
MOV ECX, [EAX - $04]
MOV LMessageLen, ECX
MOV [EAX - $04], EDX
end;
try
LCheckResult := RESULT_NOT_SPAM;
if Length(LMessage) > 0 then
LCheckResult :=
CheckMessage(TUserInfo(ASender.Thread.Data),
Pointer(LMessage), TUserInfo(ASender.Thread.Data).Adjust);
finally
asm
MOV EAX, LMessage
MOV EDX, LMessageLen
MOV ECX, [EAX - $04]
MOV LMessageLen, ECX
MOV [EAX - $04], EDX
end;
end;
...
Вот это код код съекономил мне 20% времени на исполнение.
← →
Тимохов (2004-02-11 19:31) [24]
> Владислав © (11.02.04 19:22) [23]
Да я ничего такого ругательного не говорю.
Сам люблю пооптимизировать.
← →
Владислав (2004-02-11 19:35) [25]> Тимохов © (11.02.04 19:31) [24]
Дык и ни кто не возмущается ;)
← →
Sandman25 (2004-02-12 10:39) [26][21] Владислав © (11.02.04 19:11)
Возможно, я и ошибаюсь. Сейчас вот сижу, изучаю Ваш алгоритм.
Дошел до строчек
LLen := (LOriginLen shl 1) + Length(CRLF);
SetLength(AStr, LLen);
и теперь я считаю, что в моем алгоритме всегда используется меньше памяти, чем в Вашем :)
В моем добавляется Length(Str) байт, в Вашем - Length(Str)+Length(CRLF).
← →
Владислав (2004-02-12 12:00) [27]> Sandman25 © (12.02.04 10:39) [26]
Упс... Вот это я ступил. Собственно ручно неделю назад переписал эту процедурку :)
Дело в том, что в первоначальном варианте строка не дублировалась, а из нее действительно вырезались символы в диапазоне. Потом понадобилось иметь и оригинал строки и обработанную строку. Во как :) Виноват.
Изначально алгоритм был такой. Бежим по строке от конца и ищем вхождение символов в диапазоне. Если есть последовательные символы в этом диапазоне, считаем их количество. Потом строку (часть строки), которая была до этих символов сдвигаем влево на количество символов (те, что в ненужном диапазоне). Длину строки уменьшаем на количество символов (не SetLength, а просто уменьшаем значение переменной). И так до начала строки. В самый последний момент делаем SetLength. К сожалению реализации у меня не сохранилось, так что все голословно.
← →
Sandman25 (2004-02-12 12:15) [28][27] Владислав © (12.02.04 12:00)
Может, это нескромно звучит, но мне такой алгоритм тоже приходил в голову. Но мне тогда не понравилось, что один и тот же символ может перемещаться несколько раз (сколько пробелов слева от него, столько и раз), и что при удалении первых (с начала строки) символов будет перемещаться почти вся строка. Для наихудшего случая
"1 2 3 4 5 6 7 8 9 10" будет 9 перемещений, сначала 1 символа, потом 2, потом 3 и так далее до 9.
← →
Владислав (2004-02-12 12:20) [29]А в итоге получим те же Move. Просто добавяться лишние вызовы процедур, смысла в которых немного.
А так не будет перераспределения памяти. Ну короче, быстрее работает. :)
← →
Sandman25 (2004-02-12 12:25) [30][29] Владислав © (12.02.04 12:20)
Ну, перераспределения памяти нет и в моем алгоритме.
ИМХО s[J] := s[I] выполняется гораздо быстрее, чем Move.
Но если перемещаться будут блоки (как оно обычно и бывает - пробелы ставят только между словами), то действительно, Ваш алгоритм может быть быстрее.
Вроде все ясно, спасибо за обсуждение :)
← →
Владислав (2004-02-12 12:31) [31]Да не за что :)
Мне тоже познавательно :)
← →
Johnmen (2004-02-12 13:02) [32]>Уважаемые оптимизаторы
Всё уже заоптимизировано !
http://delphibase.endimus.com/?action=viewfunc&topic=strchange&id=10395
По вопросам оптимизации обращайтесь к Sha ©
← →
Владислав (2004-01-23 13:41) [33]Как раз оптимизаторам предложенное и не подходит :)
Но все равно спасибо.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.033 c