Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001
- Название:Советы по Delphi. Версия 1.4.3 от 1.1.2001
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001 краткое содержание
…начиная с 1001. Смотрите другие файлы…
Советы по Delphi. Версия 1.4.3 от 1.1.2001 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Result := workPtr;
end;
– Ralph Friedman
Как мне перекодировать строки из Win-кодировки в Dos-кодировку и наоборот?
Одной строкой
Как мне перекодировать строки из Win-кодировки в Dos-кодировку и наоборот?
Nomadicотвечает:
A: CharToOEM, OEMToChar, CharToOEMBuff, OEMToCharBuff. Заметьте однако, что эти функции не умеют делать таких, например, вещей, как koi8-r в DOS и т. п.
Типы
У меня константы могут иметь значение, отличное от заданного. Как лечить?
Nomadicсоветует:
DX.Bug: Const из другого unit'а дает неверное значение.
Симптоматика –
UnitMain;
Interface
UsesVData;
ConstWko=0.9;
…
UnitVData;
…Implementation
UsesMain;
Procedure ...;
Begin
{ вот здесь Wko=...E+230 - наверное, бесконечность }
End;
Похоже, это действительно bug, причем ОСОБО ОПАСНЫЙ, т.к. может исказить результаты расчетов, не вызвав заметных нарушений работы программы.
В общем так. Эксперимент показал, что любая вещественная константа, определенная в интерфейсе модуля, может быть неверно (и не обязательно очень неверно – например, вместо 0.7 может появиться 0.115) прочитана в другом модуле. Баг особенно опасен тем, что он неустойчив и может пропадать и возникать без видимых причин (например, возникнуть, если предыдущая компиляция была неудачной и исчезнуть после использования константы в модуле, где она определена).
Лечится (вpоде бы) указанием типа
constWko: double = 0.9;
правда, теперь это уже не совсем константа…
Значение вычисляемого поля Paradox вместо 25.55 становится 24.5499999…
Delphi 1
Значение вычисляемого поля вместо 25.55 у меня выводится как 24.5499999. Скажите, что я делаю неправильно?
Вы не виноваты в ошибке калькуляции!
Я обнаружил ту же проблему в пакете учета, который я сейчас создаю. Мне кажется, что Borland сам делает в своем коде некий перерасчет значений.
Вы можете обойти проблему с помощью функции Round:
SalesIncVAT:=round(SalesIncVAT*100)/100; {дает вам два десятичных порядка}
ничего экстраординарного, это основное свойство математики плавающей точки, которая обеспечивает точность только в заданном интервале десятичных цифр. Точнее говоря, тип float точен для промежуточных целых чисел и для долей, которые представляют собой сумму компонентов в степени 2, любое другое число округляется исходя из переменной точности (7 цифр для «одинарной» точности, 15 для двойной и 20 для расширенной). Можно использовать процедуру Round или str:
vars : string;
begin
str(SalesIncVat:10:2,s); {10 символов для целой части (с точкой) и 2 десятичных цифры}
Label1.Caption:=s;
В справке написано, что функция FloatToStr преобразует число в строку с 15 десятичными цифрами – вот почему ваше число отображается столь причудливым образом, попробуйте эту функцию с числами типа 25.5, 25.25, 25.125 или подобными, которые имеют конечное представление в двоичной нотации, и эта проблема должна у вас исчезнуть.
Или используйте функцию FloatToStrF, которой в параметрах необходимо указать общую длину строки и количество десятичных цифр.
Классовые/статические/переменные общего доступа
Delphi 1
Здесь кроется небольшая хитрость: получение эквивалентной функциональности с помощью классового метода. Просто объявите NodeCount как регулярную типизированную константу в секции implementation вашего файла .
typeTNode = class
public
NodeCount: Integer = 0; {ЭТО НЕ ДОПУСКАЕТСЯ}
constructorCreate;
Class FunctionGetNodeCount : word;
{другой необходимый код}
end;
implementation
const
NodeCount : word = 0;
TNode.Create;
begin
inheritedCreate;
Inc(NodeCount);
end;
FunctionTNode.GetNodeCount : word;
begin
result := NodeCount;
end;
Итак, теперь ваш код может выглядеть так, как вы хотели:
SampleNode := TNode.Create;
x := SampleNode.GetNodeCount;
следующая строка также корректна:
x := TNode.GetNodeCount;
Чем отличается тип String в Delphi 2 и выше от аналогичного в Delphi 1?
Nomadicсоветует:
B D2 и выше на самом деле используется тип LongString вместо String, а старый тип тепеpь обзывается ShortString (о чем, кстати, написано в help). Из того же help можно узнать, что указатель LongString указывает на nullterminated string и потому возможно обычное приведение типа LongString к PChar (о чем я и написал), которое сводится просто к смене вывески. Там же можно узнать, что длина строки хранится в dword перед указателем. Есть также намек на то, что при присваивании другой строке информация не копируется, а увеличивается только счетчик ссылок. Более подробную информацию можно почерпнуть из system.pas:
typeStrRec = record
allocSiz: Longint;
refCnt: Longint;
length: Longint;
end;
От себя добавлю:
Сама переменная LongString указывает на байт, непосредственно следующий за этой процедурой, там же находится собственно значение строки. Значение '' (пустая строка) представляется как указатель nil, кстати, поэтому сpавнение str='' это быстpая операция.
Теперь подробнее о счетчике ссылок. Я уже говорил, что при присваивании копирования не происходит, а только увеличивается счетчик. Когда он уменьшается? Ну, очевидно, когда в результате операции значение строки меняется, то для старого значения счетчик уменьшается. Это понятно. Более непонятно, когда освобождаются значения, на которые ссылаются поля некого класса. Это происходит в System. TObject.FreeInstance пpи вызове _FinalizeRecord, а информация берется из vtInitTable (кстати, здесь же очищаются Variant). Ещё более непонятно, когда освобождаются переменые String, которые описаны как локальные в пpоцедурах/функциях/методах. Здесь работает компилятор, которые вставляет эти неявные операции в код этой функции.
Тепеpь о типе PString. Hа самом деле переменные этого типа указывают на такие же значения, как и LongString, но для переменных этого типа для всех опеpаций по созданию/копиpованию/удалению нужно помнить об этих самых счетчиках ссылок. Иногда без этого типа не обойтись. Вот опеpации для этого типа (sysutils.pas):
{ String handling routines }
{ NewStr allocates a string on the heap. NewStr is provided for backwards compatibility only. }
functionNewStr( constS: string): PString;
{ DisposeStr disposes a string pointer that was previously allocated using NewStr.DisposeStr is provided for backwards compatibility only. }
procedureDisposeStr(P: PString);
{ AssignStr assigns a new dynamically allocated string to the given string pointer.AssignStr is provided for backwards compatibility only. }
Интервал:
Закладка: