Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 12.11.2014, 12:45
NoSilence NoSilence вне форума
Прохожий
 
Регистрация: 11.09.2010
Сообщения: 6
Репутация: 10
По умолчанию Циклы, строки, символы

Добрый день.

Очень часто вижу в исходниках обработку строк в виде:
Код:
p:= PChar(line);
while p^ <> #0 do begin
  if p^ ...
  inc(p);
end;
Есть ли реальные преимущества перед обычным циклом типа:
Код:
for i:= 1 to len do begin
  if line[i] ...
end;
?
Ответить с цитированием
  #2  
Старый 12.11.2014, 13:03
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

Цикл while удобен тем, что у него можно управлять шагом итерации т.е. возможно пропустить\прокрутить нужное колво символов в строке, for последователен и в этом его минус
Ответить с цитированием
  #3  
Старый 12.11.2014, 13:42
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

А еще удобно тем, что если продолжать расценивать P как PChar, то он в каждый момент времени указывает заодно и на всю оставшуюся строку от текущего символа до конца. В некоторых случаях может быть полезно.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #4  
Старый 12.11.2014, 14:07
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

Цитата:
Сообщение от Alegun
Цикл while удобен тем, что у него можно управлять шагом итерации т.е. возможно пропустить\прокрутить нужное колво символов в строке
Эта особенность незаменима при написании различных парсеров, начиная от раскодировки UTF-8 и заканчивая лексическим анализом в компиляторе.
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
  #5  
Старый 12.11.2014, 14:13
NoSilence NoSilence вне форума
Прохожий
 
Регистрация: 11.09.2010
Сообщения: 6
Репутация: 10
По умолчанию

А я предполагал, что есть какой-то профит в быстродействии. Не всегда ведь строчка из 10 символов.

Вот еще что интересует:
Есть строчка "123456789", необходимо преобразовать в "3456789".
Через Copy, Delete понятно, а вот через ссылку как?

Если я просто укажу теперь ссылку на символ "3", то что произойдет с "12"?
Или же скопирую память Move'ом в позицию "1", то что с "9"?

Всё это нужно подчищать? Или же, если изначально была объявлена переменная типа string, то это сделает менеджер памяти?
Ответить с цитированием
  #6  
Старый 12.11.2014, 15:14
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

Цитата:
Сообщение от NoSilence
А я предполагал, что есть какой-то профит в быстродействии.
Выигрыш в быстродействии теоретический, за счет отказа от индексной адресации и (в теории) уменьшения надобности в регистрах для хранения отдельно начала строки и отдельно индекса.
Код:
function Rewind(Source: string): string;
var
  Src, Dst: PChar;
  L: Integer;
begin
  if Source <> '' then
  begin
    L := Length(Source);
    SetLength(Result, L); // выделение памяти
    Src := Pointer(Source);
    Dst := @Result[L];
    while Src^ <> #0 do
    begin
      Dst^ := Src^;
      Inc(Src);
      Dec(Dst);
    end;
  end
  else
    Result := ''; // nil в nil
end;
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
  #7  
Старый 12.11.2014, 15:52
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Выигрыш в быстродейсвиив том, что за кодом
Код:
Src[i]
стоит проверка на выход за границу массива, а за кодом
Код:
Dst[i]:=что-то
, стоит, кроме того проверка, что на строку есть ровно одна ссылка, и если это не так, производится создание новой строки.
Если Вы гарантируете невыход за границу массива и единственность указателя на строку, то можно обойтись и
Код:
Src^
Ответить с цитированием
  #8  
Старый 12.11.2014, 16:06
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 576
Версия Delphi: 6
Репутация: выкл
По умолчанию

Цитата:
Сообщение от icWasya
стоит проверка на выход за границу массива
Только при {$R+}, иначе при выходе за границы такой же AV, как и при разыменовании PChar.

Цитата:
Сообщение от icWasya
Если Вы гарантируете невыход за границу массива и единственность указателя на строку
Как уже говорил, данный способ чаще всего используется в парсерах, где исходная строка лишь читается и остается неизменной, число ссылок на нее не имеет значения. А если строка только что создана в самой функции, как в случае с результатом функции Rewind, ссылка на нее пока одна, и писать в нее можно безбоязненно.
__________________
Не стоит путать форумы с богадельнями. © Bargest
Ответить с цитированием
  #9  
Старый 14.11.2014, 13:36
Аватар для madMonia
madMonia madMonia вне форума
Новичок
 
Регистрация: 25.02.2014
Сообщения: 50
Версия Delphi: Delphi XE3
Репутация: 2545
По умолчанию

Цитата:
Сообщение от NoSilence
А я предполагал, что есть какой-то профит в быстродействии. Не всегда ведь строчка из 10 символов.
Профит есть, но незначительный, лучше на него не полагатся.


Цитата:
Сообщение от NoSilence
Если я просто укажу теперь ссылку на символ "3", то что произойдет с "12"?
Если вы просто переназначите Pchar с ячейки, содержащей "1", на ячейку, содержащую "3", то ячейки "1" и "2" останутся в памяти, пока строка не уничтожится. Далее все зависит от как строка создавалась и очищается.

Цитата:
Сообщение от NoSilence
Или же скопирую память Move'ом в позицию "1", то что с "9"?
Если вы скопируете Move'ом, то у вас получится строка "345678989"

Чтобы изменить длину строки вам нужно создать другую строку, в нее скопировать нужное содержимое из исходной, и почистить старую строку. Это если вы работаете через PChar и GetMem. Если вы используете String то можно просто SetLength обойтись
__________________
Невозможно заточить карандаш тупым топором. Столь же тщетно пытаться сделать это десятком тупых топоров
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 18:06.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter