![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Удалить подстроку из очень большой строки (больше 2 ГБ ) [D7, WinXP]
*Ray* © (2007-09-07 18:42:00)Здравствуйте, уважаемые мастера! Столкнулся со стандартной вроде бы задачей, но с интересного ракурса. Задача проста: Нужно написать функцию, удаляющую все вхождение подстроки в строке. Но есть одно условие: строка очень большая - около 2 Гб, может и больше, и нужно чтобы функция была максимально оптимизирована. Вот здесь я немного теряюсь.
Я сделал так:
Function Del_Str (longstring, string: string):string;
begin
while pos(str, longsting)>0 do
begin
del(longstring, pos(str, longstring), length(str)) ;
end;
result:=longstring;
end;
Функция работает, но одно даже присваивание result значение longstring займет в памяти 4 Гб, если строка 2 Гб. Не говря уже о других операциях. Надо что-то придумать.
Заранее всем ольшое спасибо за предложенные варианты!
Инс (2007-09-07 20:54:00) [101]
> ну вышло у меня сообщение "Form1", так я это и (до/по)казывал
> вообще то :)
Что, скопировать не смогли правильно??? Ну-ка еще раз ;) Или может голосование устроим, какое сообщение появилось :)))
Palladin (2007-09-07 20:52:00) [102]:) я что то не пойму... что этот код должен показать? ну вышло у меня сообщение "Form1", так я это и (до/по)казывал вообще то :)
в своем коде я показывал то, что работы по модифицированию string параметров процедуры передаваемых не по ссылке (var не указанно в параметрах) обязательно будут проводить к созданию другого string (а так оно и есть по все канонимам паскаля), другое дело что, если модифицирование строки переданной без var не происходит, тут Юрий прав абсолютно счетчик просто увеличивается... потому и 1 : 0.5
Инс (2007-09-07 20:48:00) [103]А если сделаете не так:
s:=Caption;
а так:
s:='12345';
то получите AV. Знаете почему? ;)
Инс (2007-09-07 20:44:00) [104]
> [8],[21],[22] объяснение ситуации и практические рекомендации
> по работе с большими объемами данных... потому что портировать
> функциональность move (Copy/Move Mem на работу с файлами
> большого объема не составляет труда)
Плохое объяснение, так как неверное, а именно:
> во вторых операция со строкой не переданной как var приводит
> к ее дубляжу и модификации дубликата
Здесь причина дубляжа - это операция Copy, а не передача строки в процедуру. При передачи строки дубляж не происходит, копируется указатель. В доказательство - код:
procedure pp(s:String);
Begin
PChar(s)^:='!';
End;
procedure TForm1.Button1Click(Sender: TObject);
var
s:String;
begin
s:=Caption;
pp(s);
showmessage(s);
end;
Palladin (2007-09-07 20:33:00) [105]
> Инс © (07.09.07 20:27) [30]
объясню...
[4], [7] это рассказ автору о том, что он описывает что то не реальное и такого вообще быть не может...
[8],[21],[22] объяснение ситуации и практические рекомендации по работе с большими объемами данных... потому что портировать функциональность move (Copy/Move Mem на работу с файлами большого объема не составляет труда)
Инс (2007-09-07 20:32:00) [106]
> не может абсолютно принять несущественность своей реплики
> и его ответ конечно автору не посуществу...
Кстати, совершенно с этим несогласен. Считаю, что в изначальной формулеровке, любой ответ не по существу (даже более того - неверный), кроме того, что на Win32 это невозможно, потому что (см. выше).
Инс (2007-09-07 20:27:00) [107]
> [29] Palladin © (07.09.07 20:22)
Не совсем понял смысл Вашего комментария. Я в своем ответе сослался на уважаемого тезку из-за того, что меня попросили объяснить мои посты [4] и [7]. Заметив, что все, что хотел по этому поводу сказать я, уже сказано, мне нечего другого не оставалось, как сослаться на это. Да и добавить в общем то нечего, как мне этого не хотелось.
Palladin (2007-09-07 20:22:00) [108]
> Инс © (07.09.07 20:14) [27]
Юрий акцентирует внимание на циферках потому, что человек (в природе у него заложено, зря писал чтоли :) ) не может абсолютно принять несущественность своей реплики и его ответ конечно автору не посуществу...
его пост абсолютно верен, но понимания происходящего приносит гораздо меньше чем мое замечание...
и я Юрия понимаю потому что сам такой же :)
да не обидится на меня мэтр :)
Rial (2007-09-07 20:15:00) [109]> [26] Denis_ © (07.09.07 19:49)
> > небольшой длины
> 2 ГБ?!
2 ГБ - строка средних размеров. Используется, например,
в качестве заголовка окна.
На строках большой длины (от 4 ГБ) не проверял, так как
почти не приходилось работать с именами файлов. %)
Инс (2007-09-07 20:14:00) [110]
> Объясните пожалуйста поподробнее. Прошу прощения, что сразу
> не заметил.
Юрий Зотов уже объяснил. 2 Гб адресного пространства всего доступно приложению в Win32 (еще два - система забирает под свои нужды). Из этих двух часть будет уже занята.
Denis_ (2007-09-07 19:49:00) [111]
> небольшой длины
2 ГБ?!
Rial (2007-09-07 19:48:00) [112]
procedure DelInsides(Var sValue : String; Const sSubString : String);
Var
L : Integer;
LS : Integer;
Tmp : Integer;
P : Integer;
P1 : Integer;
P2 : Integer;
PS : Integer;
begin
L :=Length(sValue);
LS :=Length(sSubString);
Tmp :=L - LS + 1;
P1 :=1;
P :=1;
While (P1 <= Tmp)do begin
PS :=1;
P2 :=P1;
While(PS <= LS)and(sValue[P2] = sSubString[PS]) do begin
Inc(P2);
Inc(PS);
end;
If(PS > LS)then begin
P1 :=P2;
end else begin
sValue[P] :=sValue[P1];
Inc(P1);
Inc(P);
end;
end;
If(P1 < L)then begin
Tmp :=L - P1 + 1;
Move(sValue[P1], sValue[P], Tmp);
Inc(P, Tmp);
end;
SetLength(sValue, P - 1);
end;
Можно еще кое-что оптимизировать, конечно,
но для строк небольшой длины мне хватало.
Denis_ (2007-09-07 19:40:00) [113]
> Dib@zol © (07.09.07 19:22) [18]
> Ваще убит наповал... ОТКУДА берутся такие строки???????
Тебя что то смущает? (с)Anatoly Podgoretsky
Palladin (2007-09-07 19:33:00) [114]
> *Ray* ©
я не сказал нельзя, я сказал, что не рекомендую, бо str одно из стандартных ключевых слов Паскаля... да и 2Гб это вполне реально, на 64x системах и 64x приложениях..
у Riply © (07.09.07 19:27) [21] хорошо описан механизм "дефрагментации" строки... нужно его релизовать используя > oxffff © (07.09.07 19:28) [22]
> Юрий Зотов © (07.09.07 19:20) [15]
"но" принято... 1 : 0.5 :)
oxffff (2007-09-07 19:28:00) [115]function FastDel(const A:string;Pos,Count:integer):boolean;
var pi:pinteger;
begin
result:=false;
if (length(a)+1<pos+count) or (pos<1) then exit;
CopyMemory(pointer(DWORD(A)+Pos-1),pointer(DWORD(A)+Pos+Count-1),length(a)-pos-count+2);
pi:=pointer(a);
dec(pi);
PI^:=PI^-count;
result:=true;
end;
procedure TForm1.Button1Click(Sender: TObject);
var a,b:string;
c:pointer;
begin
a:='abc'+'dfs';
b:=a+'asdf';
FastDel(b,3,8);
showmessage(b);
end;
Riply (2007-09-07 19:27:00) [116]> [20] *Ray* © (07.09.07 19:26)
Можно попробовать посчитать кол-во вхождений SubStr в LongString при помощи PosEx
Один раз сделать SetLength(Result,..) , и в него переместить подстроки Move()
*Ray* (2007-09-07 19:26:00) [117]Спасибо всем большое за новые знания! Я понял что 2 Гб-это нереально. Может вы напишите как Вы бы работали просто с очень большой строкой, не будет конкретизировать размер. Может это совсем будет по-другому, чем у меня.
*Ray* (2007-09-07 19:23:00) [118]to Юрий Зотов:
Вполне возможно, что с 2 Гб я преувеличил. Я просто хотел сказать, что строка очень большая, и при обработке строки будет занято много ресурсов и поэтому даже малейшая оптимизация будет существенна.
Dib@zol (2007-09-07 19:22:00) [119]Ваще убит наповал... ОТКУДА берутся такиестроки???????
Вася Правильный (2007-09-07 19:21:00) [120]
> большой строки (больше 2 ГБ )
из справки
String types
Type Maximum length Memory required Used for
ShortString 255 characters 2 to 256 bytes backward compatibility
AnsiString ~2^31 characters 4 bytes to 2GB 8-bit (ANSI) characters, DBCS ANSI, MBCS ANSI, etc.
WideString ~2^30 characters 4 bytes to 2GB Unicode characters; multi-user servers and multi-language applications