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

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

Удалить подстроку из очень большой строки (больше 2 ГБ ) [D7, WinXP]


Страницы:   1 2 3 4 5 6 7

*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 Гб. Не говря уже о других операциях. Надо что-то придумать.

Заранее всем ольшое спасибо за предложенные варианты!


oxffff   (2007-09-09 13:34:00) [61]


> Sha ©   (08.09.07 18:32) [70]
> > oxffff ©   (07.09.07 19:28) [22]
>
> В твоей совершенно замечаьельной процедуре имеется грубая,
>  
> но трудноуловимая ощибка.
>
> Попробуй угадать, что будет выдано, если вызвать ее так:
>
>
> procedure TForm1.Button5Click(Sender: TObject);
> var
>  a, b: string;
> begin
>  a:='123456789'; FastDel(a,2,3);  ShowMessage(a);
>  a:='123456789'; FastDel(a,2,3);  ShowMessage(a);
>  b:='123456789'; ShowMessage(a);
> end;


А [60] не смотрели?

VirtualProtect?


Sha   (2007-09-09 11:44:00) [62]

> Riply ©   (09.09.07 09:45)
> Неувязочка в том, что у строки "a" RefCount = -1 ?

Ага, и параметр объявлен как const.
Попытка изменить строку-константу.


Riply   (2007-09-09 09:45:00) [63]

>[73] Sha ©   (08.09.07 23:03)
> Хуже. И намного прикольнее.
Неувязочка в том, что у строки "a" RefCount = -1 ?


Sha   (2007-09-08 23:03:00) [64]

> Riply ©   (08.09.07 21:54) [72]
> Пересечение областей копирования ?

Хуже. И намного прикольнее. Скомпилируй - не пожалеешь :)


Riply   (2007-09-08 21:54:00) [65]

>[70] Sha ©   (08.09.07 18:32)
> В твоей совершенно замечаьельной процедуре имеется грубая,
> но трудноуловимая ощибка.
Пересечение областей копирования ?


Sha   (2007-09-08 18:34:00) [66]

Посдедняя строка должна выглядеть так
b:='123456789'; ShowMessage(b);

Но в данном случае это совершенно не важно :)


Sha   (2007-09-08 18:32:00) [67]

> oxffff ©   (07.09.07 19:28) [22]

В твоей совершенно замечаьельной процедуре имеется грубая,
но трудноуловимая ощибка.

Попробуй угадать, что будет выдано, если вызвать ее так:

procedure TForm1.Button5Click(Sender: TObject);
var
 a, b: string;
begin
 a:='123456789'; FastDel(a,2,3);  ShowMessage(a);
 a:='123456789'; FastDel(a,2,3);  ShowMessage(a);
 b:='123456789'; ShowMessage(a);
end;


Dib@zol   (2007-09-08 16:03:00) [68]

> [67] Инс ©   (08.09.07 16:01)

Тфублн. Я твой код а не этот на предмет Аксесса Виалейшна тестировал.


Инс   (2007-09-08 16:01:00) [69]


> Дык ничем!

Ой ли ничем? А где в моем коде VirtualProtect? ;-)


oxffff   (2007-09-08 16:01:00) [70]


> Инс ©   (08.09.07 15:54) [65]
>
> > Да! А у меня ить тоже не было ж!
>
> А чем мой код отличается от oxffff?


VirtualProtect(pointer(a),length(a),PAGE_EXECUTE_READWRITE,Old);


Dib@zol   (2007-09-08 15:58:00) [71]

> [65] Инс ©   (08.09.07 15:54)

Дык ничем! О том и речь, что при таком раскладе АВ не возникает!


Инс   (2007-09-08 15:54:00) [72]


> Да! А у меня ить тоже не было ж!

А чем мой код отличается от oxffff?


Dib@zol   (2007-09-08 15:48:00) [73]

> [63] Инс ©   (08.09.07 15:46)

Да! А у меня ить тоже не было ж!


Инс   (2007-09-08 15:46:00) [74]


> А у меня нет AV.

Поздравляю.


Sha   (2007-09-08 11:15:00) [75]

Вкралась ошибка, правильно будет так:

procedure DeleteString(var s: string; const t: string);
var
 i, pto, pfrom, count, tlen: integer;
 q: pchar;
begin;
 i:=Pos(t,s);
 if i>0 then begin;
   tlen:=Length(t);
   q:=pointer(s); //чтобы компилятор не вставлял вызовы UniqueString
   pto:=i;
   repeat;
     pfrom:=i+tlen;
     i:=PosEx(t,s,pfrom);
     if i=0 then count:=Length(s)+1 else count:=i;
     dec(count,pfrom);
     Move(q[pfrom-1],q[pto-1],count);
     inc(pto,count)
     until i=0;
   SetLength(s,pto-1);
   end;
 end;


Sha   (2007-09-08 11:09:00) [76]

> Rial ©   (07.09.07 19:48) [25]

 sValue[P] :=sValue[P1];  //Сводим на нет всю оптимизацию

Избавиться от вызовов Uniquestring можно, например, так:

procedure DeleteString(var s: string; const t: string);
var
 i, pto, pfrom, count, tlen: integer;
 q: pchar;
begin;
 pto:=Pos(t,s);
 if pto>0 then begin;
   tlen:=Length(t);
   q:=pointer(s); //чтобы компилятор не вставлял вызовы UniqueString
   repeat;
     pfrom:=pto+tlen;
     i:=PosEx(t,s,pfrom);
     if i=0 then count:=Length(s)+1 else count:=i;
     dec(count,pfrom);
     Move(q[pfrom-1],q[pto-1],count);
     inc(pto,count)
     until i=0;
   SetLength(s,pto-1);
   end;
 end;


oxffff   (2007-09-08 10:39:00) [77]


> Инс ©   (07.09.07 20:48) [34]
> А если сделаете не так:
> s:=Caption;
> а так:
> s:='12345';
> то получите AV. Знаете почему? ;)


А у меня нет AV.

procedure abc(s:string);
begin
pchar(s)^:='!';
end;

procedure TForm1.Button1Click(Sender: TObject);
var a:string;
   Old:DWORD;
begin
a:='34322314';
VirtualProtect(pointer(a),length(a),PAGE_EXECUTE_READWRITE,Old);
abc(a);
showmessage(a);
end;


reonid   (2007-09-07 22:37:00) [78]

Несколько замечаний.

Если строка действительно большая,
возможно, стоит использовать специальные методы поиска, вроде
  http://www.rsdn.ru/article/alg/textsearch.xml

Далее, так как подстрок может быть много,
неэффективно при удалении подстроки перемещать (Move)
кусок от конца вхождения подстроки до конца строки.
Лучше перемещать кусками от конца одного вхождения
до начала следующего.


Инс   (2007-09-07 21:54:00) [79]


> [57] Palladin ©   (07.09.07 21:49)

Ну да, я типа об этом и кричу, вот уже где-то десяток постов... И еще думаю, как же "Мастер Delphi" - и не знает такой простой вещи... ))) Приятно, что все-таки знает. Ладно, нормальное обсуждение получилось. Для рядового читателя может быть много нового интересного.


Palladin   (2007-09-07 21:49:00) [80]

если кратко, то я хотел сказать, что, естественно, сам факт передачи переменной типа String в Delphi параметром процедуры(функции) ниразу не означает дубляжа информации содержащейся в переменной типа String :)


Страницы:   1 2 3 4 5 6 7

Наверх

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