![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Нетипизированные указатели [D7]
Vitaliy____ © (2008-07-31 05:51:00)Доброе время суток!
Есть такая задача: организовать чтение/запись из файла в формате
параметр=значение.
Программа должна читать те параметры, что ей "известны" по имени.
Положим, они будут 3-х типов: целое, вещественное, строка.
Помогите с синтаксисом структуры, в которой можно бы было хранить указатель на один из этих 3-х типов данных и пример работы (запись значения по этому указателю).
Конечно можно сделать 3 указателя в каждой записи, но 1) могут добавится другие типы данных 2) Наверняка можно без извращений и потерь памяти - просто я не знаю как это в делфи.
Ega23 (2008-08-05 10:05:00) [1]
> Категорически не согласен.
Рекомендую заглянуть в CPU.
Vitaliy____ (2008-08-05 09:00:00) [2]
> Так ты что же, всю эту шнягу затеял искл-но ради отладки
> ?!
Совсем не понял к чему это...
Зачем это все затеяно написано в [12] (там жирненьким даже выделено...).
По-моему все превращается в оффтоп...
Сергей М. (2008-08-05 08:23:00) [3]
> Vitaliy____ (05.08.08 07:37) [20]
Так ты что же, всю эту шнягу затеял искл-но ради отладки ?!
Мда)..
А когда ты собираешься забить гвоздь, ты случаем не вызываешь перед этим бригаду скорой помощи, типо, ежели что, сразу диагноз поставить или в морг отвезти ?)
Vitaliy____ (2008-08-05 07:37:00) [4]Во время работы программы приходится прочитать не один файл. Так что значения по умолчанию хранятся в памяти до завершения работы.
> А её не надо "освобождать".
Категорически не согласен. Сколько пишу - всегда пригождалось: даже если класс существует до конца работы программы и память будет освобождена средой, очень полезно с самого начала сделать конструктор/деструктор и таким образом ловить ошибки типа выхода за границы массива и т.д. - если мы запортили память - удаление обычно не проходит и мы сразу знаем у какой структуры проблемы.
Ega23 (2008-08-04 12:21:00) [5]
> По крайней мере у меня проблем не было (обычно ошибки памяти
> вылазят на деструкторе класса, когда мы пытаемся освободить
> эту самую память).
А её не надо "освобождать".
Так тебе это дело в процессе работы программы надо хранить? И не сохранять_читать в файл (из файла)?
Vitaliy____ (2008-08-04 12:13:00) [6]По-моему, тут мы куда-то не туда лезем....
Есть строка/целое/вещественное, которое надо запомнить на случай если параметр не прочитан. Как верно заметили в [5], чтение справки часто избавляет от многих хлопот. Variant подходит именно для хранения этих типов данных. Как я понимаю, пример из справки
var
V1, V2, V3, V4, V5: Variant;
I: Integer;
D: Double;
S: string;
begin
V1 := 1; { integer value }
V2 := 1234.5678; { real value }
V3 := 'Hello world!'; { string value }
V4 := '1000'; { string value }
V5 := V1 + V2 + V4; { real value 2235.5678}
I := V1; { I = 1 (integer value) }
D := V2; { D = 1234.5678 (real value) }
S := V3; { S = 'Hello world!' (string value) }
I := V4; { I = 1000 (integer value) }
S := V5; { S = '2235.5678' (string value) }
end;
Позволяет быть уверенным, что строки в Variant хранятся нормально. По крайней мере у меня проблем не было (обычно ошибки памяти вылазят на деструкторе класса, когда мы пытаемся освободить эту самую память).
Так что думаю все корректно.
Ega23 (2008-08-01 14:57:00) [7]
> Не понял, он что сам не разберется? В справке просто присваивают
> строку и она где-то хранится, видимо они нормально работу
> со строками реализовали. В ансистринг же мы не задумываемся.
> ..
Я тебя не понимаю.
Опиши ещё раз: что у тебя есть и что ты хочешь получить на выходе.
Vitaliy____ (2008-08-01 13:49:00) [8]Не понял, он что сам не разберется? В справке просто присваивают строку и она где-то хранится, видимо они нормально работу со строками реализовали. В ансистринг же мы не задумываемся...
Ega23 (2008-08-01 13:43:00) [9]Дык в том, что где тогда твой вариант будет храниться? Размер варианта - 16 байт. Ну будет там где-то адрес твоей строки. А сами данные?
Vitaliy____ (2008-08-01 13:14:00) [10]Нет, здоровых там не предполагается. В основном - целые и вещественные параметры. А если строка, то не больше 100 символов.
Кстати, а в чем узкое место? Разве в Variant не так как в AnsiString? Здоровый - ну и пусть себе хранится раз надо... Если есть какие-то мысли, поясни в чем узкость места...
Ega23 (2008-08-01 12:59:00) [11]Узкое место - DefaultValue. Представь, что это какой-то здоровый стринг.
Vitaliy____ (2008-08-01 12:38:00) [12]Связь простая. Может я "быстро" писал первый пост и не совсем понятно что хотел ;)
Все сводится к такой структурке:
type ParamLinkElem=record
name:string; // Имя параметра
type_v:integer; // Тип данных параметра
Initialise:boolean; // Прочитан ли параметр из файла
link:Pointer; // Ссылка на переменную, где хранится параметр
DefaultValue:variant; // Значение по умолчанию для данного параметра
end;
Имеется массив элементов типа ParamLinkElem. В конструкторе класса, занимающегося вводом/выводом прописываются значения этой "связующей" структуры (параметры читаются для других классов, поэтому нужна была нетипизированная ссылка) .
Когда мы читаем из файла параметры, мы находим по имени что это за параметр, получаем его тип и куда надо записать.
Если не все параметры были прочитаны (флаг Initialise при чтении не выставлен), то по адресу link записывается DefaultValue (вот тут потребовался тип variant - так как нужно хранить разные типы данных)
Вот теперь, когда это все работает - можно критиковать :)
Закономерен вопрос " для чего все это нужно". Ситуация такая: для данной формы часто приходится менять сохраняемые параметры (какие-то становятся ненужными или появляются новые). Так вот, прога должна "безболезненно" воспринимать изменение "версии" файла сохранения. Если у нас в нем что-то лишнее - оно будет проигнорировано, так как параметра с таким именем в массиве не найдется; Если мы чего-то не прочтем - будет подставлено значение по умолчанию.
Плохиш (2008-07-31 17:53:00) [13]
> в файле целые должны быть строкой а не бинарно
> variant и pointer достаточно было
Казалось бы, какая связь...
Vitaliy____ (2008-07-31 14:13:00) [14]К сожалению, не пойдет - в файле целые должны быть строкой а не бинарно.
Уже сделано - variant и pointer достаточно было. Тему закрыть можно.
Ega23 (2008-07-31 12:03:00) [15]
procedure StreamReadString(Stream : TStream; var Value : string;
const Size : Integer);
begin
SetLength(Value, Size);
Stream.ReadBuffer(PChar(Value)^, Size);
end;
//*****************************************************************************
procedure StreamWriteString(Stream : TStream; const Value : string;
const TagID : Cardinal);
var
BlockSize : Cardinal;
begin
BlockSize := Length(Value);
Stream.WriteBuffer(TagID, 4);
Stream.WriteBuffer(BlockSize, 4);
Stream.WriteBuffer(PChar(Value)^, BlockSize);
end;
//*****************************************************************************
procedure StreamReadDateTime(Stream : TStream; var Value : TDateTime);
begin
Stream.ReadBuffer(Value, SizeOf(TDateTime));
end;
//*****************************************************************************
procedure StreamWriteDateTime(Stream : TStream; const Value : TDateTime;
const TagID : Cardinal);
var
BlockSize : Cardinal;
begin
BlockSize := SizeOf(TDateTime);
Stream.WriteBuffer(TagID, 4);
Stream.WriteBuffer(BlockSize, 4);
Stream.WriteBuffer(Value, BlockSize);
end;
//*****************************************************************************
procedure StreamReadGUID(Stream : TStream; var Value : TGUID);
begin
Stream.ReadBuffer(Value, SizeOf(TGUID));
end;
//*****************************************************************************
procedure StreamWriteGUID(Stream : TStream; const Value : TGUID;
const TagID : Cardinal);
var
BlockSize : Cardinal;
begin
BlockSize := SizeOf(TGUID);
Stream.WriteBuffer(TagId, 4);
Stream.WriteBuffer(BlockSize, 4);
Stream.WriteBuffer(Value, BlockSize);
end;
//*****************************************************************************
procedure StreamReadBoolean(Stream : TStream; var Value : Boolean);
begin
Stream.ReadBuffer(Value, SizeOf(Boolean));
end;
//*****************************************************************************
procedure StreamWriteBoolean(Stream : TStream; const Value : Boolean;
const TagID : Cardinal);
var
BlockSize : Cardinal;
begin
BlockSize := SizeOf(Boolean);
Stream.WriteBuffer(TagID, 4);
Stream.WriteBuffer(BlockSize, 4);
Stream.WriteBuffer(Value, BlockSize);
end;
//*****************************************************************************
procedure StreamReadInteger(Stream : TStream; var Value : Integer);
begin
Stream.ReadBuffer(Value, SizeOf(Integer));
end;
//*****************************************************************************
procedure StreamWriteInteger(Stream : TStream; const Value : Integer;
const TagID : Cardinal);
var
BlockSize : Cardinal;
begin
BlockSize := SizeOf(Integer);
Stream.WriteBuffer(TagID, 4);
Stream.WriteBuffer(BlockSize, 4);
Stream.WriteBuffer(Value, BlockSize);
end;
//*****************************************************************************
Сергей М. (2008-07-31 11:45:00) [16]
> Вот как, за меня уже все сделали
И даже кучу примеров предоставили по использованию этого самого за тебя сделанного.
oldman (2008-07-31 09:27:00) [17]
> Программа должна читать те параметры, что ей "известны"
> по имени.
Ini файлы отменили?
Vitaliy____ (2008-07-31 09:01:00) [18]Вот как, за меня уже все сделали... Замечательно. А я-то думал. Чтож, это очень даже здорово...
Leonid Troyanovsky (2008-07-31 08:10:00) [19]
> Vitaliy____ (31.07.08 05:51)
> Помогите с синтаксисом структуры, в которой можно бы было
> хранить указатель на один из этих 3-х типов данных и пример
> работы (запись значения по этому указателю).
RTFM: variant type.
--
Regards, LVT.
Vitaliy____ (2008-07-31 07:07:00) [20]Вроде понятно. Отладка покажет. Спасибо ;)
Будем поглядеть...