Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Можно ли задавать размер динамического массива, несколько раз без потери данных? 
:(
    Опции темы
poiuyt1234
  Дата 17.2.2009, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 135
Регистрация: 30.4.2008

Репутация: нет
Всего: нет



Пишу прогу. Одна из ее функций анализирует текст. Ищет по определенным условиям слова. Если находит слово заносит его в ячейку массива. Так вот. Слов может быть от 0 до 1000000. Создавать массив с запасом наверно не стоит.  А лучше динамически. Но тогда как установить размер массива? При каждом обнаружении нужного слова счетчик будет увеличиваться на еденицу и это слово надо занести в массив.
Можно ли при каждой итерации(обнаружении нужного слова) цикла увеличивать размерность динамического массива на еденицу с помощью setlength ,без потери ранее записанных в него данных?
PM MAIL   Вверх
SneG0K
Дата 17.2.2009, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Max Mara
***


Профиль
Группа: Завсегдатай
Сообщений: 1887
Регистрация: 1.12.2007
Где: Wis Dells

Репутация: 1
Всего: 54



Цитата(poiuyt1234 @  17.2.2009,  19:39 Найти цитируемый пост)
увеличивать

Да. Предыдущие данные не теряются.
PM WWW Skype   Вверх
Poseidon
Дата 18.2.2009, 01:09 (ссылка) |   (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(poiuyt1234 @  17.2.2009,  20:39 Найти цитируемый пост)
Можно ли при каждой итерации(обнаружении нужного слова) цикла увеличивать размерность динамического массива на еденицу с помощью setlength ,без потери ранее записанных в него данных?
Изменять размерность массива в большую сторону можно без потери данных. В меншую - нет. Только стоит заметить, что выделение памяти - это очень ресурсоемкая и медленная задача. И если ты на каждую итерацию цикла будешь вызывать setlength, это может оказаться гораздо "тыжелее" и медленнее, чем если бы ты сразу выделил 1000000. Я бы увеличивал размерность блоками. Допустим, по 1000 единиц. Размер блока во многом зависет от того, что будет хранится в массиве. Если сеществует большая вероятность того, что практически все 1000000 будут использованы, то лучше сразу выделять память для 1000000 элементов массива. Если большая вероятность, что элементов будет не более 500000, увеличивать размеронсть по 500000 и т.п. В любом случае, выделить память для 10000 элементов гораздо быстрее, чем 10000 раз выделять память по одному элементу. А вообще, само правильно было бы пронализировать входные данные и выделить ровно столько, сколько надо. Для поставленной задачи это значит "посчитать сколько слов и выделить ровно такое количество элементов". В любом случае будет быстрее, чем делать setlength для каждого слова.



--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Virtuals
Дата 18.2.2009, 07:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 3
Всего: 11



poiuyt1234

в дополнение к 
Poseidon, в двух словах.
setlength
1. создает новую переменную требуемого размера
2. копирует в нее содержимое предыдущей переменной
3. уничтожает старую.

соответственно для переменной размером в 1000 при setlength 2000? потребуется минимум 1000+2000=3000!!! не забываем об этом.
PM MAIL ICQ   Вверх
Alexeis
Дата 18.2.2009, 10:47 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(Virtuals @  18.2.2009,  06:42 Найти цитируемый пост)
setlength
1. создает новую переменную требуемого размера
2. копирует в нее содержимое предыдущей переменной
3. уничтожает старую.


Все не так просто как кажется, чтобы в этом убедиться можно выполнить следующий код
Код

procedure TForm1.FormCreate(Sender: TObject);
var
 c : array of integer;
 p1, p2, p3 : Pointer;
begin
 setLength(c, 100);
 p1 := c;
 setLength(c, 50);
 p2 := c;
 c[49] := 1010101;
 setLength(c, 58);
 p3 := c;
 c[57] := 1010101;
 showmessage(IntToHex(Integer(p1), 8) + ' ' +
             IntToHex(Integer(p2), 8) + ' ' +
             IntToHex(Integer(p3), 8));
end;


Память выделяется если ее не хватает, но не возвращается при уменьшении, потому удобно предварительно выделить памяти побольше, это зарезервирует большой блок, затем повторным setLength установить тот размер который вам нужен сейчас, это избавит вас от создании лишней переменной - размера используемой части. 

  В результате мы имеем, то что увеличение размера массива при помощи setLength не будет приводить к перераспределению памяти, а функции High() и Length() будут давать правильный (а не зарезервированный размер). 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Christoph
Дата 18.2.2009, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 667
Регистрация: 23.1.2008
Где: Харьков

Репутация: 1
Всего: 11



Чуть не вкурил,Зачем выделять память побольше? если при нехватки памяти она сама выделить сколько ей надо, ну например выделили память 
Код

SetLength(a,1000);

И это получается что если я туда запишу какое то одно число, а остальная память будет гулять, потому получается что эту память может использоваться массив, хотя могу и ошибаться 
И например если написать так
Код

SetLength(a,10);
a[50]:=10;
 
Так зачем переживать за память? если присвоится без проблем

И еще вот что из кода Alexeis, p1,p2,p3 - выводят начальный адресс массива, я прав?



--------------------
user posted image
PM MAIL ICQ   Вверх
Snowy
Дата 18.2.2009, 15:50 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Поясняю на пальцах:
1. Создаём массив a, размером 1
Получаем в памяти: [a][свободное место]
Дальше в работе нам понадобилась переменная i
Имеем в памяти: [a][i][свободное место]
Теперь мы хотим увеличить массив а до 2.
Но вот проблема - место за [a] уже занято. Значит, чтобы увеличить, нужно перенести весь массив [а] туда, где место есть.
То есть [ ][i][a ][свободное место]
Если массив [a] имеет большой размер, то выделение 1 места приведёт к копированию всего массива, что при большом размере довольно чувствительно.
Однако, не вижу особых причин этого боятся в целом алгоритме.
При обработке данных в цикле, такое перераспределение произойдёт всего 1 раз, пока массив маленький.
Если мы не выделяем постоянно память, то вероятность дальнейших переносов невелика.
Хотя, если выделить сразу большой блок, то вовсе исключается.
Выделение большого блока, с последующим уменьшением тоже вариант, но тоже не гарантия, хотя снижает количество перераспределений.
Впрочем, если счёт идёт не на десятки мегабайт в процессе, чувствительном к задержке в пару-тройку миллисекунд, то я бы и заморачиваться не стал.
Всё равно в фиксированном цикле перераспределений немного, а в нефиксированом частота перераспределений невысока.
Для массивов до мегабайта это не чувствительно.
Поскольку речь идёт о массиве, предельный размер которого 4Мб, то не стоит и голову ломать.
На фоне основного алгоритма, перераспределение будет абсолютно нечувствительно.
PM MAIL   Вверх
Alexeis
Дата 18.2.2009, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(Christoph @  18.2.2009,  14:29 Найти цитируемый пост)
И еще вот что из кода Alexeis, p1,p2,p3 - выводят начальный адресс массива, я прав?

  Указатель на память массива. Поскольку значение адреса не меняется, то память не перераспределялась. Тут видно что если перваночально памяти было выделено много, то последующие уменьшения и увеличения размера не приводят к перераспределению, пока хватает памяти.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
bems
Дата 18.2.2009, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Alexeis, а если так попытаться работать с объемом больше 64-х кило, оно так же работает?


--------------------
Обижено школьников: 8
PM MAIL   Вверх
poiuyt1234
Дата 18.2.2009, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 135
Регистрация: 30.4.2008

Репутация: нет
Всего: нет



а обрезать лишние ячейки тож можно без потери данных в заполненных ячейках с помощью setlength? т.е. понадобилось фактически  700000 из 1000000, а потом setlength(a,700000)
PM MAIL   Вверх
Riply
Дата 18.2.2009, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 3
Всего: 32



Цитата(Alexeis @  18.2.2009,  15:56 Найти цитируемый пост)
Поскольку значение адреса не меняется, то память не перераспределялась. Тут видно что если перваночально памяти было выделено много, то последующие уменьшения и увеличения размера не приводят к перераспределению, пока хватает памяти. 


Я бы, наверное, не рискнула быть столь категоричной.

SetLength(a, 1000000);
SetLength(a, 1);
// Здесь "система" считает хвостик свободным и вольна поступать с ним как ей хочеться
//... что-то происходит
SetLength(a, 10); - перераспределения не произошло, если в "//..." 
хвостик "системой" не был использован, что может зависеть от расположения звезд smile


PM MAIL   Вверх
Christoph
Дата 18.2.2009, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 667
Регистрация: 23.1.2008
Где: Харьков

Репутация: 1
Всего: 11



AlexeisSnowy,  спасибо за разъяснения, если кто то может киньте ссылку про менеджер памяти в делфи


--------------------
user posted image
PM MAIL ICQ   Вверх
cemick
Дата 18.2.2009, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 416
Регистрация: 6.7.2006
Где: Санкт-Петербург

Репутация: 2
Всего: 6



Цитата(Christoph @  18.2.2009,  17:59 Найти цитируемый пост)
если кто то может киньте ссылку про менеджер памяти в делфи

вроде менеджер памяти тут не причем(вроде как), все делается в DynArraySetLength в System..
PM MAIL WWW   Вверх
Alexeis
Дата 18.2.2009, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Riply, обычная схема предполагает, что раз один раз понадобилось, то может понадобиться еще раз. Делфийский менеджер памяти не очень любит отдавать память, а при уменьшении размера массива он и вовсе не отдает. Это общая стратегия выделения памяти. Гарантировать такое поведение нельзя, но наедятся можно.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Christoph
Дата 18.2.2009, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 667
Регистрация: 23.1.2008
Где: Харьков

Репутация: 1
Всего: 11



Цитата(cemick @ 18.2.2009,  18:08)
Цитата(Christoph @  18.2.2009,  17:59 Найти цитируемый пост)
если кто то может киньте ссылку про менеджер памяти в делфи

вроде менеджер памяти тут не причем(вроде как), все делается в DynArraySetLength в System..

Да, но мне интересно почитать )

Прочитал пост Riply и написал код, вроде тот хвостик никто не трогает, хотя немного не уверен 

Код

procedure TForm1.FormCreate(Sender: TObject);
var Int: PInteger;
    arr: array of integer;
    p1,p2:Pointer;
begin
  SetLength(arr,15);
  arr[5]:=2;
  p1:=arr;
  SetLength(arr,10);
  New(Int);
  Int^:=1000;
  arr[13]:=9898;
  p2:=arr;
  showmessage(IntToHex(Integer(p1), 8) + ' ' +
               IntToHex(Integer(p2), 8)) ;
   dispose(Int);
end;



Alexeis, ответил уже  smile 

Это сообщение отредактировал(а) Christoph - 18.2.2009, 18:35


--------------------
user posted image
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0942 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.