Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.03.2014, 10:23   #1
xrob
Форумчанин
 
Регистрация: 18.10.2010
Сообщений: 419
По умолчанию копирование участка памяти

необходимо реализовать такую штуку:
в произвольное место в памяти записываются последовательно разные данные - числа, текст, отдельные символы.
при этом "курсор" перемещается по мере записывания данных.
память при этом будет выглядеть примерно вот так:
[4 байта] - какое-то число
[1 байт] - 1 буковка
[10 байт] - какое-то слово
и т.д.

данные записываются в место, на которое указывает pointer,
при этом после записи pointer увеличивается на длину записанных данных?
чтобы следующие данных дописывались в конец предыдущих.


написал функцию для записи в память строки.
на входе:
1. указатель на место записи (pointer)
2. строка (string)


Код:
procedure WriteString(var p:pointer;  str:string);
var
i,d:integer;
pc1,pc2:^byte;
begin

pc1:=@str[1];
pc2:=p;
for i:=1 to Length(str) do begin pc2^:=pc1^; Inc(pc1); Inc(pc2); end;
p:=pc2;

end;
в принципе все работает как надо, но хотелось бы услышать мнение знающих людей,
насколько оптимальна такая процедура.
Главный вопрос - есть ли более быстрые функции копирования памяти?

по этой теме нашел функцию move, но что-то она у меня не вызывает доверия.
кривое название, непонятные аргументы, попробовал ее вместо своего кода -
прога работать перестала. Да, знаю как это звучит =). пока особо не разбирался в причинах,
но с моим то кодом все работало, а с move - нет.

т.е. как по аналогии с текстом - можно посимвольно копировать одну строку в другую,
а есть функция Copy, которая вроде как быстрее, потому что реализована на более низком уровне.

Последний раз редактировалось xrob; 27.03.2014 в 10:48.
xrob вне форума Ответить с цитированием
Старый 27.03.2014, 12:43   #2
Somebody
Участник клуба
 
Регистрация: 08.10.2007
Сообщений: 1,185
По умолчанию

Цитата:
по этой теме нашел функцию move, но что-то она у меня не вызывает доверия.
кривое название, непонятные аргументы, попробовал ее вместо своего кода -
прога работать перестала.
Действительно, название кривоватое, но это идёт ещё из старого Pascal'я. Но вообще она для данного случая как раз подходит. Что непонятно с аргументами?
Somebody вне форума Ответить с цитированием
Старый 27.03.2014, 13:19   #3
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
т.е. как по аналогии с текстом - можно посимвольно копировать одну строку в другую,
а есть функция Copy, которая вроде как быстрее, потому что реализована на более низком уровне.
функция Copy, делает тоже самое
только она оптимизирована, а ваш цикл нет.

и строки давно уже лучше просто присваивать.

move то что нужно для копирования, но возможно вы не до конца понимаете как лежат данные в памяти или копируете хз куда.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 27.03.2014, 15:35   #4
xrob
Форумчанин
 
Регистрация: 18.10.2010
Сообщений: 419
По умолчанию

аргументы функции move:

procedure Move(const Source; var Dest; count:Integer);

по-хорошему компилятор на такой строчке должен выдать синтаксическую ошибку ,
мол "не охренели ли вы не указывать тип данных аргумента".
но нет, все ок, как буд-то так и надо...
не, на практике функция, конечно, принимает pointer'ы,
но это все-таки не дело. по мне так такой интефейс у функции
это такой же плохой тон, как и неинициализированный указатель

хотя, конечно, возможно что я чего-то не знаю,
и такой способ указания аргументов это крутая фишка вроде defaul-свойств,
которая позволяет передавать в качестве параметра переменные любого типа.
впрочем не суть. неуютно =(


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

на более низком уровне все сложнее, если загуглить эту тему,
то узнаешь про страницы памяти, при минимальный блок памяти, кучи и т.д.
но как я понял, память, выделенная под строку представляет собой
монолитный кусок чистых байтов (ключевое слово "монолитный"), правильно?

кстати, ребята с вашего же форума меня и научили, что
лучше сразу выделить необходимую память под строку,
чем увеличивать ее в цикле, поскольку каждое увеличение -
это перекладывание данных на новое место.

если это так, тогда я все делаю правильно =)

по поводу того, что строки нужно присваивать - вообще не врубился к чему это вы))
у меня ведь задача не s1:=s2, и даже не s:=s+IntToStr(i).
задача в том, чтобы в один поток данных сложить разные типы данных.
под число 4 байта - имеется в виду не четырехзначное число, а именно тип integer, который занимает 4 байта.

опишу контекст, в котором работаю:
есть таблица, допустим StringGrid, но это не суть.
главное что есть сетка строк - двумерный массив.
надо все это сохранить в файл. как?

один из вариантов - текстовый файл с разделением табами (#9)
строки таблицы разделяются переносом строки,
а ячейки - символом табуляции.
при загрузке из файла соответственно разбивается на ячейки таблицы.
при таком подходе у меня таблица 75 метров загружается за 10 секунд.

еще один вариант - придумать определенную структуру хранения данных в файле.
я решил сделать так:
данные хранятся в виде блоков.
первый байт блока - его тип
потом четыре байта - длина блока
далее содержимое блока.

соответственно алгоритм чтения:
1. читаем первый байт
2. читаем 4 байта - получаем длину блока
3. читаем контент - указанное кол-во байтов

благодаря тому, что здесь не надо сравнивать каждый символ,
а время тратится в основном на копирование данных,
75-метровая таблица грузится за 2 секунды, что гораздо приятнее десяти =)

память под поток данных выделяю с помощью строки: SetLength(s,100500);.
указатель: p:=@s[1]; на первый символ строки.
этот указатель и передается в мои функции WriteString, WriteInteger, WriteByte,
а так же в аналогичные для чтения.

вот, например, ReadInteger:

Код:
function ReadInteger(var p:pointer):integer;
var
i:integer;
pc1:^byte;
pc2:^byte;
begin 

pc1:=@Result;
pc2:=p;
for i:=1 to 4 do begin pc1^:=pc2^; Inc(pc1); Inc(pc2); end;
p:=pc2;

end;
в принципе везде одна и та же операция - копирование памяти с места на место.
Пепел Феникса, что тут еще можно оптимизировать?
xrob вне форума Ответить с цитированием
Старый 27.03.2014, 15:39   #5
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
задача в том, чтобы в один поток данных сложить разные типы данных.
зачем Move тогда?
потомки TStream в чем вам не угодили?
я лично приводил пару раз примеры как писать строки в файл и тп.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 27.03.2014, 15:40   #6
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
по-хорошему компилятор на такой строчке должен выдать синтаксическую ошибку
Эта фишка называется нетипизированным параметром и используются, когда тип данных не важен
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Выделение участка памяти RAZOR1703 Общие вопросы C/C++ 3 24.11.2011 19:18
C# Копирование участка программы в буфер как изображение Forcer Помощь студентам 5 04.07.2011 10:55
Копирование участка памяти Celestia Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 1 21.02.2011 09:18
Сортировка участка матрицы random7 Общие вопросы C/C++ 7 23.06.2010 08:13
Копирование участка текста из Экселя в Ворд Devourer12345 Microsoft Office Excel 3 30.07.2008 08:13