Форум: "Начинающим";
Текущий архив: 2008.09.14;
Скачать: [xml.tar.bz2];
ВнизНетипизированные указатели Найти похожие ветки
← →
Vitaliy____ (2008-07-31 05:51) [0]Доброе время суток!
Есть такая задача: организовать чтение/запись из файла в формате
параметр=значение.
Программа должна читать те параметры, что ей "известны" по имени.
Положим, они будут 3-х типов: целое, вещественное, строка.
Помогите с синтаксисом структуры, в которой можно бы было хранить указатель на один из этих 3-х типов данных и пример работы (запись значения по этому указателю).
Конечно можно сделать 3 указателя в каждой записи, но 1) могут добавится другие типы данных 2) Наверняка можно без извращений и потерь памяти - просто я не знаю как это в делфи.
← →
multiflex (2008-07-31 06:37) [1]Приз за лучшую головоломку года тебе обеспечен.
> Помогите с синтаксисом структуры, в которой можно бы было
> хранить указатель на один из этих 3-х типов данных
> могут добавится другие типы данных
type
struktura = record
uk : Pointer;
end;
вот пожалуйста, структура хранит указатель на ЛЮБОЙ тип данных.
> Наверняка можно без извращений и потерь памяти - просто
> я не знаю как это в делфи.
Да, если постораться, то в Delphi можно и без потерь памяти и извращений.
ЗЫ. Виталий, помедленнее изложи, чего же ты хочеш, ато ничо не понятно чо ты говориш =(
← →
Vitaliy____ (2008-07-31 06:42) [2]Без проблем. Помедленнее :)
Ты почти ответил кстати. Напиши еще приведение pointer к integer скажем... и дальше я сам.
Скажем есть переменная v1:integer.
Надо 1) присвоить uk ее адрес
2) По uk обратится к v1
Меня интересует синтаксис приведения указателя к нужному типу данных в делфи - дальше разберусь.
← →
MultIfleX (2008-07-31 06:49) [3]о_О
> Напиши еще приведение pointer к integer
i := Integer(Ptr);
i := integer(Pointer(string));
ЗЫ. Integer ненада, нада Cardinal (если канешно у тебя нет областей памяти с отрицательными указателями, в чом я уже не уверен %))
ЗЗЫ. Это только для передачи параметров в какую либо функцию по указателю, или как? Типа в библиотеку? Надеюсь всетаки не запись в файл.... =( ...ато не покатит.
← →
Vitaliy____ (2008-07-31 07:07) [4]Вроде понятно. Отладка покажет. Спасибо ;)
Будем поглядеть...
← →
Leonid Troyanovsky © (2008-07-31 08:10) [5]
> Vitaliy____ (31.07.08 05:51)
> Помогите с синтаксисом структуры, в которой можно бы было
> хранить указатель на один из этих 3-х типов данных и пример
> работы (запись значения по этому указателю).
RTFM: variant type.
--
Regards, LVT.
← →
Vitaliy____ (2008-07-31 09:01) [6]Вот как, за меня уже все сделали... Замечательно. А я-то думал. Чтож, это очень даже здорово...
← →
oldman © (2008-07-31 09:27) [7]
> Программа должна читать те параметры, что ей "известны"
> по имени.
Ini файлы отменили?
← →
Сергей М. © (2008-07-31 11:45) [8]
> Вот как, за меня уже все сделали
И даже кучу примеров предоставили по использованию этого самого за тебя сделанного.
← →
Ega23 © (2008-07-31 12:03) [9]
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;
//*****************************************************************************
← →
Vitaliy____ (2008-07-31 14:13) [10]К сожалению, не пойдет - в файле целые должны быть строкой а не бинарно.
Уже сделано - variant и pointer достаточно было. Тему закрыть можно.
← →
Плохиш © (2008-07-31 17:53) [11]
> в файле целые должны быть строкой а не бинарно
> variant и pointer достаточно было
Казалось бы, какая связь...
← →
Vitaliy____ (2008-08-01 12:38) [12]Связь простая. Может я "быстро" писал первый пост и не совсем понятно что хотел ;)
Все сводится к такой структурке:
type ParamLinkElem=record
name:string; // Имя параметра
type_v:integer; // Тип данных параметра
Initialise:boolean; // Прочитан ли параметр из файла
link:Pointer; // Ссылка на переменную, где хранится параметр
DefaultValue:variant; // Значение по умолчанию для данного параметра
end;
Имеется массив элементов типа ParamLinkElem. В конструкторе класса, занимающегося вводом/выводом прописываются значения этой "связующей" структуры (параметры читаются для других классов, поэтому нужна была нетипизированная ссылка).
Когда мы читаем из файла параметры, мы находим по имени что это за параметр, получаем его тип и куда надо записать.
Если не все параметры были прочитаны (флаг Initialise при чтении не выставлен), то по адресу link записывается DefaultValue (вот тут потребовался тип variant - так как нужно хранить разные типы данных)
Вот теперь, когда это все работает - можно критиковать :)
Закономерен вопрос "для чего все это нужно". Ситуация такая: для данной формы часто приходится менять сохраняемые параметры (какие-то становятся ненужными или появляются новые). Так вот, прога должна "безболезненно" воспринимать изменение "версии" файла сохранения. Если у нас в нем что-то лишнее - оно будет проигнорировано, так как параметра с таким именем в массиве не найдется; Если мы чего-то не прочтем - будет подставлено значение по умолчанию.
← →
Ega23 © (2008-08-01 12:59) [13]Узкое место - DefaultValue. Представь, что это какой-то здоровый стринг.
← →
Vitaliy____ (2008-08-01 13:14) [14]Нет, здоровых там не предполагается. В основном - целые и вещественные параметры. А если строка, то не больше 100 символов.
Кстати, а в чем узкое место? Разве в Variant не так как в AnsiString? Здоровый - ну и пусть себе хранится раз надо... Если есть какие-то мысли, поясни в чем узкость места...
← →
Ega23 © (2008-08-01 13:43) [15]Дык в том, что где тогда твой вариант будет храниться? Размер варианта - 16 байт. Ну будет там где-то адрес твоей строки. А сами данные?
← →
Vitaliy____ (2008-08-01 13:49) [16]Не понял, он что сам не разберется? В справке просто присваивают строку и она где-то хранится, видимо они нормально работу со строками реализовали. В ансистринг же мы не задумываемся...
← →
Ega23 © (2008-08-01 14:57) [17]
> Не понял, он что сам не разберется? В справке просто присваивают
> строку и она где-то хранится, видимо они нормально работу
> со строками реализовали. В ансистринг же мы не задумываемся.
> ..
Я тебя не понимаю.
Опиши ещё раз: что у тебя есть и что ты хочешь получить на выходе.
← →
Vitaliy____ (2008-08-04 12:13) [18]По-моему, тут мы куда-то не туда лезем....
Есть строка/целое/вещественное, которое надо запомнить на случай если параметр не прочитан. Как верно заметили в [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-04 12:21) [19]
> По крайней мере у меня проблем не было (обычно ошибки памяти
> вылазят на деструкторе класса, когда мы пытаемся освободить
> эту самую память).
А её не надо "освобождать".
Так тебе это дело в процессе работы программы надо хранить? И не сохранять_читать в файл (из файла)?
← →
Vitaliy____ (2008-08-05 07:37) [20]Во время работы программы приходится прочитать не один файл. Так что значения по умолчанию хранятся в памяти до завершения работы.
> А её не надо "освобождать".
Категорически не согласен. Сколько пишу - всегда пригождалось: даже если класс существует до конца работы программы и память будет освобождена средой, очень полезно с самого начала сделать конструктор/деструктор и таким образом ловить ошибки типа выхода за границы массива и т.д. - если мы запортили память - удаление обычно не проходит и мы сразу знаем у какой структуры проблемы.
← →
Сергей М. © (2008-08-05 08:23) [21]
> Vitaliy____ (05.08.08 07:37) [20]
Так ты что же, всю эту шнягу затеял искл-но ради отладки ?!
Мда)..
А когда ты собираешься забить гвоздь, ты случаем не вызываешь перед этим бригаду скорой помощи, типо, ежели что, сразу диагноз поставить или в морг отвезти ?)
← →
Vitaliy____ (2008-08-05 09:00) [22]
> Так ты что же, всю эту шнягу затеял искл-но ради отладки
> ?!
Совсем не понял к чему это...
Зачем это все затеяно написано в [12] (там жирненьким даже выделено...).
По-моему все превращается в оффтоп...
← →
Ega23 © (2008-08-05 10:05) [23]
> Категорически не согласен.
Рекомендую заглянуть в CPU.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2008.09.14;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.066 c