Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.02.25;
Скачать: CL | DM;

Вниз

Функция, убирающая пробелы в строке   Найти похожие ветки 

 
Ученик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;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.022 c
1-79919
norman
2004-02-08 22:21
2004.02.25
Ошибка при запуске программы на delphi


1-79842
Сережа
2004-02-09 18:32
2004.02.25
работа с рисунками


14-80252
int64
2004-02-04 12:50
2004.02.25
Together от Borland.


1-79727
__Dmitry
2004-01-23 13:27
2004.02.25
Динамическое создание формы с TWebBrowser


1-79988
AGN
2004-02-13 09:52
2004.02.25
Ctrl+F