Bounds — Функция Delphi


Bounds — Функция Delphi

Описание
Функция создает массив значений типа Variant. Границы размерностей массива определяются параметром Bounds, который должен содержать пары значений (нижняя и верхняя граница). Тип элементов массива указывается в параметре VarType, и должен соответствовать одному из значений поля TvarData.VarType (См. описание функции VarType), за исключением значений varArray, varByRef и varString. Для создания Variant-массива строк необходимо в параметре VarType указать значение varOleStr.

Если для элементов массива задан тип значе-ний varVariant, то они, в свою очередь, могут представлять собой Variant-массивы.

Пример
var
S: string;
Mas: Variant;
begin
Mas:= VarArrayCreate([0, 3], varVariant);
Mas[0]:= VarArrayHighBound(Mas, 1);
Mas[1]:= ‘Быть или не быть?’;
Mas[2]:= 12.34567;
Mas[3]:= VarArrayOf( [7, 354, 0, 21, 66, 189] );
S:= VarToStr( Mas[1] ); // S:= ‘Быть или не быть?’
S:= VarToStr( Mas[3][1] ); // S := 354
end;

RoundTo и SimpleRoundTo в Delphi

Практически всегда при вычислении дробных чисел результатом выходит значение с большим количеством знаков после запятой, что неудобно для восприятия человека. Людям удобно воспринимать дробные числа, когда в дробной части максимум четыре знака. Значит, число-результат нужно привести к удобочитаемому виду. Числа можно округлить с помощью функций RoundTo() и SimpleRoundTo().

Для начала нужно подключить модуль математических функций Math, чтобы получить доступ к интересующим нас функциям.

Синтаксис функции RoundTo() таков:

RoundTo(число; кол-во_знаков);

function RoundTo(const AValue: Double; const ADigit: TRoundToRange): Double;

Здесь AValue – округляемое число типа Double, объявленное как константа. ADigit – порядок округления, то есть фактически количество знаков, которое должно остаться в дробной части после округления. ADigit также объявлен как константа типа TRoundToRange. Сама функция тоже имеет тип Double. На будущее заметим, что опытные программисты используют для хранения вещественных чисел не Double, а Extended, как более точный тип. Кроме того, для чисел, округляемых не более чем до четвертого знака после запятой, можно использовать тип Currency, который хранит данные как масштабированное целое значение, исключая проблему с погрешностями при вычислениях.

Приведем пример округления значение переменной V до двух знаков после запятой. В переменную V записываем новое значение:

V:=RoundTo(V, -2);
Приведем пример деления двух чисел:

var R1,R2,R: Real;

Функция SimpleRoundTo() сходна с RoundTo() – различие лишь в способе округления последнего знака. SimpleRoundTo() округляет последнее число в большую сторону, а RoundTo() использует так называемое банковское округление, приводя число к ближайшему четному. Добавим, что обе функции умеют округлять не только дробные, но и целые числа, обнуляя разряды младше указанного порядка. Так, например, если округлять число 1234567, указав количество разрядов (ADigit) равное трем, то на выходе получим число 1234000.

. roundto delphi как округлять значения в delphi 2001 delphi ss10893 схама работы Delphi SimpleRoundTo pascal округление числа в большую сторону

Delphi list index of bounds

Всем доброго времени суток.

Получаю ошибку list index of bounds -1 . Как помню эта ошибка означает обращение к несуществующему элементу. Однако тут вроде как все правильно.

1 ответ 1

Код сделан копипастой, отсюдова и ошибки. В коде есть три if-блока. В первом работают с Tag1, в втором с Tag2, а в третьем и с Tag3 и с Tag2. Так как текст в Tag3 скорее всего не загружен, то вот она проблема.

Как бы я для начала сделал. Сделал дополнительную процедуру.

код стал явно понятнее, и что самое главное, теперь можно добавить ещё десяток edit/memo и не боятся сделать ошибку. Но я бы логику кода пересмотрел немного.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками delphi или задайте свой вопрос.

Похожие

Подписаться на ленту

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

дизайн сайта / логотип © 2020 Stack Exchange Inc; пользовательское содержимое попадает под действие лицензии cc by-sa 4.0 с указанием ссылки на источник. rev 2020.11.11.35399

Диагностические сообщения компилятора Delphi

Типов сообщений компилятора — более двухсот. Рассмотрим перечень наиболее встречающихся сообщений класса Error

    0. expected but found. Обычно это сообщение возникает при синтаксической ошибке.Например,в случае небаланса скобок,компилятор сообщит: ‘)’ expected but ‘;’ found (вместо ожидавшейся скобки найдена запятая).

Компилятор часто сообщает, что ‘end’ ожидается,например:x:= 5,7; здесь неуместен разделитель-запятая, а сообщается про end. (‘END’ expected but ‘,’ found)

  • 1. is not a type identifier. Данное не является именем типа.
  • 2. ‘;’ not allowed before ‘Else’. Перед else нельзя ставить точку с запятой
  • 3. Abstract method must be virtual or dynamic. Абстрактный метод должен быть виртуальным или динамическим.
  • 4. Ambiguous overloaded call to . Компилятор не может однозначно выбрать перегружаемый блок. Измените параметр.
  • 5. Array type required. Ошибка возникает в случаях, когда в индексе элемента массива указано больше уровней, чем предусмотрено описанием, и если массив не описан. Например, после объявления двумерного массива х или простой переменной х ошибочно записывают элемент х[2,1,1] (в нем показано три измерения).
  • 6. Assignment to FOR-loop variable . Присваивание значения параметру FOR-цикла в теле цикла.

    Например, вследствие описки дважды используется имя i в кратном цикле:

  • 7. Break or Continue outs >. Компиляция присоединенного модуля невозможна.
  • 14. Data type too large. Тип определяет структуру размером более 2 Гбайт; это слишком много.
  • 15. Declaration expected but found. Пропущено описание или оператор.
  • 16. Declaration of differs from previous declarations. Данный заголовок блока не соответствует упреждающему объявлению блока.
  • 17. Default parameter must be by-value or constant. Необязательный параметр (со значением по умолчанию) не должен вызываться по ссылке.
  • 18. Expression expected. В этом месте программы должно стоять выражение.
  • 19. Expression too complicated. Выражение излишне сложно для компиляции.
  • 20. File type not allowed here. В этом месте или в этой роли файловую переменную нельзя использовать. Например, она не может быть формальным параметром-значением.
  • 21. For loop control variable must be simple local variable. Параметр цикла должен быть простой локальной (описанной в этом же блоке) переменной.
  • 22. For loop control variable must have ordinal type. Параметр цикла должен иметь порядковый тип.Вещественный тип запрещен.
  • 23. Function needs result type. В заголовке функции надо указывать тип ее результата.
  • 24. Identifier expected but found. В этом месте должно стоять имя. Например, пропущено имя функции после Function.
  • 25. Identifier redeclared . описано повторно, но в пределах блока имя можно описать лишь раз. Проверьте, не обозначена ли локальная переменная тем же именем, что и формальный параметр блока.
  • 26. Illegal character in input file . Запретный знак, например «русская» буква, либо вы оставили скобку >, убрав открывающую скобку <.
  • 27. Illegal type in Read/Readln (Write/Writeln) statement. Элемент запрещенного типа в списке ввода/вывода.
  • 28. Incompatible types . Несоответствие типов по присваиванию или типов операндов одной операции. Сообщение выдается и при неверном использовании структур. Например, z — запись, ошибочно записано присваивание z:= 0 (работать надо с полями записи).
  • 29. Invalid function result type. Недопустимый тип результата функции.
  • 30. Label already defined: . уже помечает другой оператор.
  • 31. Left side cannot be assigned to. He может быть такой левой части в присваивании. Примеры: попытка присвоить значение файловой переменной, присвоение значения формальному параметру-константе.
  • 32. Line too long. В строке программного текста больше 255 знаков.
  • 33. Low bound exceeds high bound. Нижняя граница превышает верхнюю.
  • 34. Missing operator or semicolon.Пропуск операции (например перед скобкой) или пропуск точки с запятой. При пропуске ‘;’ маркер ошибки стоит на очередном предложении (объявлении или операторе).
  • 35. Missing parameter type. He указан тип формального параметра-значения или параметра процедурного типа.
  • 36. Not enough actual parameters. He хватает фактических параметров.
  • 37. Need to specify at least one dimension . Нужно задавать в операторе SetLength хотя бы один размер динамического массива.
  • 38. Number of elements differs from declaration. Число элементов в структурной константе не соответствует ее описанию.
  • 39. Operator not applicable to this operand type. Операция не применима к операндам данного типа. Например: ‘А’ or ‘В’; ‘Text1’* ‘Text2’.
  • 40. Order of fields in record constant differs from declaration. Порядок полей в записи-константе не соответствует описанию записи.
  • 41. Ordinal type required. Требуется порядковый тип (например, в индексе).
  • 42. Out of memory. Компилятору не хватает памяти.
  • 43. Statement expected but found. В этом месте должен стоять оператор. Сообщение выдается во всех случаях, когда в тело блока или секцию инициализации ошибочно помещают описание ( ). Ошибочная форма обращения к процедуре Procedure или к функции Function также вызывает сообщение.
  • 44. Sets may have at most 256 elements. Множество (тип Set) не может содержать более 256 элементов.
  • 45. Slice standard function only allowed as open array argument. Функцию Slice можно использовать лишь как фактический параметр
  • 46. Statement not allowed in interface part. Предложения в секции интерфейса программного модуля недопустимы.
  • 47. Syntax error in real number. Синтаксическая ошибка в записи числа вещственного типа.
  • 48. There is no overload version of that can be called with these arguments.Не предусмотрен перегружаемый блок , который мог бы вызываться с таким аргументом. Пример: IntToStr(x), где х – выражение вещественного типа.
  • 49. Too many actual parameters. Фактических параметров больше, чем формальных.
  • 50. Type actual and formal var parameters must be identical. Тип фактического параметра должен быть идентичен типу формального параметра-переменной.
  • 51. Type of expression must be . Выражение должно быть указанного типа. Например,после While и Until должно стоять логическое выражение.
  • 52. Undeclared identifier: .Не описано . Проверьте есть ли описание в нужном месте,нет ли описок в имени. Если указано имя компонента формы, проверьте,поместили ли компонент на данную форму.
  • 53. Unexpected end of file in comment started on line . Неожиданный конец файла при незавершенном комментарии, начало комментария — в строке N.
  • 54. Unit name mismatch: . Имя модуля ошибочно.
  • 55. Unsatisfied forward or external declaration . Отсутствует описание блока, объявление которого было дано (заголовок в интерфейсе или в описании объектного типа, либо упреждающее описание).
  • 56. Unterminate string. He закрыта апострофом строка-константа типа string.
  • Илон Маск рекомендует:  Пример 2 таблица имен

    Рассмотрим также некоторые сообщения классов warning и hint.

    • Return value of function might be undefined. В теле функции нет присваивания ее результата.
    • Variable might not have been initialized. Указывает имя переменой, которой не задали значения.
    • For-Loop variable may be undefined after loop. Попытка использования значения параметра For-цикла после завершения этого цикла.
    • Text after final ‘END.’ ignored by compiler. Текст, идущий за конечной строкой модуля, игнорируется компилятором.
    • Variable is declared but never used in . Обращает внимание на переменную , описанную,но не нашедшую применения.
    • Value assigned to never used. Хотя бы одно значение переменной никак не использовано.

    Несколько рекомендаций

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

    Не удаляйте прежний вариант кода,пока не убедитесь,что ошибка устранена. Лучше на время закомментировать код,заключив его в скобки:

    Компилятор не анализирует, как будет выполняться программа, поэтому выход значения индекса из диапазона выявляет только если индекс задан константным выражением. Деление на ноль вообще пропускается, кроме оператора div, в случае если делитель — константное выражение.

    Округление чисел в Delphi

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

    В программировании можно выделить несколько возможных вариантов округления – округление до целого или до заданной точности знаков после запятой. Так же оно различается по механизму округления – до ближайшего целого, в сторону большего целого или наименьшего целого значения. Для всех этих задач в Delphi используется набор математических функций, доступных после добавления в разделе описания соответствующей библиотеки:

    Округление числа до целого значения

    Для округления до целого числа используется следующий набор функций:

    Ceil(X) — до целого в большую сторону;

    Floor(X) — до целого в меньшую сторону;

    Round(X) — число до целого в ближайшую сторону;

    Trunc(X) — число до целого путем отбарасывания дробной части.

    В качестве параметра эти функции используют дробное значение X и возвращают целое. Примеры округления чисел:

    // до ближайшего большего целого:
    A := Ceil(15.15); // A = 16
    В := Ceil(15.95); // В = 16

    // до ближайшего меньшего целого:
    A := Floor(15.15); // A = 15
    В := Floor(15.95); // В = 15

    // по математическим правилам до ближайшего целого:
    A := Round(15.15); // A = 15
    B := Round(15.95); // B = 16
    C := Round(15.5); // C = 16
    D := Round(15.4999); // D = 15

    // отбрасывание дробной части
    A := Trunc(15.15); // A = 15
    В := Trunc(15.95); // В = 15

    * Несмотря на схожесть результата, Floor и Trunc имеют некоторое отличие. Floor возвращает значение типа Integer, тогда как Trunc — Int64, имеющий больший диапазон значений. Ceil так же возвращает значение Integer. Round возвращает Int64.

    Округление до заданной точности знаков после запятой

    Наиболее удобной функцией для этих вычислений является SimpleRoundTo. В качестве параметров ей нужно указать дробное число, а вторым параметром отрицательным целым числом. Второй параметр указывает на количество необходимых знаков после запятой.


    A := SimpleRoundTo(15.1219, -1); // A = 15.1
    B := SimpleRoundTo(15.1219, -2); // B = 15.12
    C := SimpleRoundTo(15.1219, -3); // C = 15.122
    D := SimpleRoundTo(15.1219, -4); // D = 15.1219
    E := SimpleRoundTo(15.1219, -5); // E = 15.1219

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

    Другие механизмы округления чисел

    Используя ту же функцию SimpleRoundTo можно так же выполнить округление до целого, указав вторым параметром ноль:

    A := SimpleRoundTo(15.1219, 0); // A = 15

    Если указывать положительные значения, то задается округление до нужной разрядности числа:

    A := SimpleRoundTo(1235.1219, 1); // A = 1240 – до десятков
    B := SimpleRoundTo(1235.1219, 2); // B = 1200 – до сотен
    C := SimpleRoundTo(1235.1219, 3); // C = 1000 – до тысяч

    Функция Frac(x) позволяет отбросить целое число, оставив только дробную часть:

    Функции Delphi

    Стандартные функции Delphi:

    Для проведения всевозможных математических вычислений и многочисленных преобразований язык программирования Delphi содержит библиотеки стандартных процедур и функций. Давайте подробнее рассмотрим стандартные функции Delphi.

    Между значением и именем функции существует зависимость. Поэтому всякая функция может быть представлена как операнд некоторого выражения (к примеру, в инструкции присваивания). Для возведения числа в n-ую степень достаточно записать

    откуда ln — функция, вычисляющая натуральный логарифм числа exp(x), exp — функция, вычисляющая экспоненту в степени x, x — число, n-ую степень которого надо найти, а n — степень числа x. Каждая функция обладает следующими характеристиками: тип значений, тип параметров.

    Должно существовать соответствие между типом переменной (ей присваивается определенное значение функции) и типом функции. И в то же время необходимо соответствие между типом фактического параметра данной функции (фактический параметр — это параметр, который указывается при обращении к функции) и типом формального параметра. В противном случае компилятором выводится сообщение об ошибке.

    Математические функции Delphi:

    Библиотеки языка Delphi включаются в себя и множество математических функций:

    Величину угла при использовании тригонометрических функций необходимо выражать в радианах. Чтобы преобразовать угол из градусов в радианы, используйте следующую формулу:

    где a выражает угол в градусах; 3.1415926 означает число pi. На месте константы 3.1415926 с дробной частью для достижения большей точности чаще всего пользуются стандартной именованной константой pi. Тогда выражения для угла в пересчете в радианы будет выглядеть следующим образом:

    Функции преобразования Delphi:

    Наиболее частое использование функций преобразования связано с инструкциями, которые обеспечивают ввод/вывод какой-либо информации. Например, для вывода значения переменной c типом real в поле вывода диалогового окна (компонент Label), нужно провести преобразование числа в строку символов, которая собственно изображает данное число. Это можно достичь, применяя функцию FloatToStr, которая заменяет значение выражения (оно указано как параметр функции) его строковым представлением.

    Пример.

    В приведенном примере значение переменной m будете выведено в поле Label. В таблице ниже Вам будут представлены основные функции преобразования Delphi:

    Применение функций Delphi:

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

    Примеры.

    Структура функции Delphi

    Как организована инструкция функции в языке Delphi? В любом языке программирования на первом этапе описания функции указывается ее заголовок. Далее за заголовком программист описывает раздел объявления констант const (если таковы имеются), затем занимается описанием раздела объявления типов type, далее следует раздел объявления переменных var и, наконец, раздел инструкций.

    В приведенном примере в заголовке функции вначале указывается зарезервированное слово function, а следом идет имя функции. Далее в скобках программист перечисляет список параметров, и вслед за ним, используя символ «:», указывает тип значения функции. В конце каждого заголовка стоит символ «;». После заголовка следуют раздел констант, раздел типов, раздел переменных. Внутри раздела инструкций кроме констант и переменных, описанных соответственно в разделах const и var, может находится переменная result.

    Илон Маск рекомендует:  Что такое код func_get_args

    Когда инструкции функции завершат свое выполнение, значению переменной result присваивается значение функции. Таким образом, среди всех инструкций функций необходимое присутствие инструкции, которая бы присваивала переменной result окончательное значение функции. Обычно подобная инструкция есть последняя исполняемая инструкция функции. Представим пример функции FuntToKg, преобразующей фунты в килограммы.

    DelphiComponent.ru — бесплатно видеоуроки по Delphi, статьи, исходники

    Процедуры и функции в Delphi

    Посмотрите видеоурок по процедурам и функциям (подпрограммы):

    Скачайте бесплатно видеокурс Мастер Delphi Lite прямо сейчас — в нем больше видеоуроков — СКАЧАТЬ БЕСПЛАТНО!

    Процедуры и функции — это наиболее важный материал, который необходимо усвоить, прежде чем можно будет называть себя программистом. Объектно-ориентированное программирование в целом и программирование в Delphi в частности в огромной степени основано на использовании процедур и функций.

    Использование процедур Write и WriteLn действительно не представляет особой сложности, поскольку они встроены в компилятор Delphi. Компилятор содержит лишь небольшое количество встроенных процедур. Большинство процедур и функций можно найти в отдельных исходных файлах, называемых модулями. Все модули Delphi имеют расширение . pas.

    Прежде чем процедуру можно будет использовать в приложении, следует знать имя процедуры, модуль, в котором она объявлена, и принимаемые процедурой параметры. Имя процедуры и список параметров — составные части заголовка процедуры. Заголовок простой процедуры выглядит следующим образом:

    После зарезервированного слова procedure всегда указывается имя процедуры, которым может быть любой допустимый идентификатор. В приведенном примере процедура не имеет параметров. Заголовок процедуры со списком параметров выглядит следующим образом:

    Список параметров — это механизм передачи значений процедурам (равно как и функциям). Список параметров может содержать один или более параметров. Если список содержит более одного параметра, они разделяются точкой с запятой. Ниже приведен пример заголовка процедуры, которая принимает единственное строковое значение:

    Показать скрытое содержание
    unit Unit1;
    interface
    implementation
    end.

    Использование замыканий и функций высших порядков в Delphi

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

    Delphi не является языком функционального программирования, но тот факт, что программы на нем могут манипулировать функциями как объектами означает, что в Delphi можно использовать приемы функциональной парадигмы. Цель статьи — не подтолкнуть к использованию этого стиля, но обозначить некоторые примеры и возможности.

    Конструирование функций

    Функции высшего порядка (ФВП) – это функции, которые оперируют функциями, принимая одну или более функций и возвращая новую функцию.
    Следующий пример показывает, как с помощью ФВП можно конструировать другие функции.

    Функция Negate в примере выше, является ФВП, потому что она принимает функцию IsOdd в виде аргумента и возвращает новую функцию IsEven, которая передает свои аргументы Negate и возвращает логическое отрицание значения, возвращаемого функцией IsOdd.

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

    Композиция функций

    Ниже приводится пример еще одной, более универсальной функции, которая принимает две функции, F и G, и возвращает новую функцию, которая возвращает результат F(G()).

    Здесь функция Compose вычисляет F(G(X, Y)). Возвращаемая функция передает все свои аргументы функции G, затем передает значение, полученное от G, функции F и возвращает результат вызова F.

    Частичное применение

    Этот термин описывает преобразование функции с несколькими аргументами в функцию, которая принимает меньшее количество аргументов, при этом значения для опущенных аргументов задаются заранее. Этот прием вполне адекватен своему названию: он «частично применяет» некоторые аргументы функции, возвращая функцию, принимающую остающиеся аргументы.
    Функция BindLeft в примере ниже берет функцию Calc, принимающую n аргументов, связывает первые k из них с наперед заданными значениями и возвращает функцию Partial, которая может принять (n-k) аргументов (первые k аргументов будут уже применены к ней).

    Здесь интересен момент, когда после вызова BindLeft локальная переменная StoredArgs не прекращает свое существование и используется далее, сохраняя в себе значения аргументов, которые потом используются при вызове Partial и передаются в Calc. Этот эффект называется замыканием. При этом каждый вызов BindLeft будет порождать новые «экземпляры» StoredArgs. Замыкания использовались и в предыдущих примерах, когда в них сохранялись аргументы ФВП.
    Определить частичное применение справа можно следующим образом:

    Карринг

    В то время как частичное применение преобразует функцию с n параметрами в функцию с n-k параметрами, применяя k аргументов, карринг декомпозирует функцию на функции от одного аргумента. Мы не передаем никаких дополнительных аргументов в метод Curry, кроме преобразуемой функции:

    • Curry(F) возвращает функцию F1, такую что.
    • F1(A) возвращает функцию F2, такую что.
    • F2(B) возвращает функцию F3, такую что.
    • F3(С) вызывает F(A, B, C)
    Мемоизация

    Мемоизованная функция — это функция, которая сохраняет ранее вычисленные результаты. Другими словами, для функции создаётся таблица результатов, и, будучи вычисленным при определённых значениях параметров, результат заносится в эту таблицу. В дальнейшем результат берётся из данной таблицы. Эта техника позволяет за счёт использования дополнительной памяти ускорить работу программы. Разумеется, мемоизируемая функция должна работать без побочных эффектов и ей желательно иметь дискретную область определения.
    В следующем примере демонстрируется функция Memoize высшего порядка, которая принимает функцию в виде аргумента и возвращает ее мемоизованную версию.

    Функция Memoize создает объект TCache для использования в качестве кэша и присваивает его локальной переменной, благодаря чему он остается доступным (через замыкание) только для возвращаемой функции. Возвращаемая функция преобразует свой аргумент в ключ. Если значение присутствует в кэше, оно просто возвращается в качестве результата. В противном случае вызывается оригинальная функция, вычисляющая значение для заданного аргумента; полученное значение помещается в кэш и возвращается.

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

    Генераторы

    Здесь под генератором понимается ФВП, которая возвращает функцию, вызов которой приводит к получению следующего члена некоторой последовательности. В примере ниже создаются два генератора: для последовательности Фибоначчи и генератор факториалов. Предыдущие элементы генераторов запоминаются в замыкании.

    Польза генераторов заключается в том, что для вычисления каждого следующего элемента не требуется вычислять всю последовательность с самого начала. Генераторы позволяют работать даже с бесконечными последовательностями, но они обеспечивают только последовательный доступ к своим элементам и не позволяют обращаться к своим элементам по индексу: чтобы получить n-e значение придется выполнить n-1 итераций.

    Отложенные вычисления

    Генераторы бывает удобно использовать для последовательной обработки данных — элементов списка, строк текста, лексем в лексическом анализаторе и т.д. Генераторы можно объединять в цепочки, подобно конвейеру команд в Unix. Самое интересное в этом подходе заключается в том, что он следует принципу отложенных вычислений: значения «извлекаются» из генератора (или из конвейера) по мере необходимости, а не все сразу. Эту особенность демонстрирует следующий пример, в котором исходный текст фильтруется, построчно проходя через цепочку генераторов.

    List index out of bounds (5) в Delphi че за.

    При использовании процедуры:

    procedure SaveBase(fname: string);
    var
    f: TFile; base: TData; k: integer;
    begin
    try
    AssignFile(f, fname);
    Rewrite(f);
    with main.mainlist, base do begin
    for k:=0 to main.mainlist.Items.Count-1 do
    begin
    numeral:=StrToInt(Items[k].Caption);
    date:=Items[k].SubItems[0];
    tipe:=Items[k].SubItems[1];
    statya:=Items[k].SubItems[2];
    human:=Items[k].subitems[3];
    sum:=StrToFloat(Items[k].subitems[4]);
    comment:=Items[k].subitems[5];
    write(f, base);
    end;
    end;
    finally
    CloseFile(f);
    end;
    end;

    Появляется List index out of bounds (5) . Когда в списке было 1 строка, проблем не было, когда стало 2 — появляется. Не знаю почему, в других прогах таким же принципом делал и проблем нету, а в этой не знаю почему.

    Использование функций Delphi в приложениях CBuilder

    Если вы можете использовать форму Delphi в приложении, то почему бы не попробовать использовать модуль Delphi без формы, ассоциированной с ним? Как было бы здорово использовать все реализованные ранее в Delphi возможности при написании кода на C++! К счастью, это возможно.

    Хочу предложить вам хороший пример, подтверждающий мои слова. Когда я приступал к написанию этой книги, я решил, что отличным примером возможностей CBuilder может послужить код, отображающий на экране текст, повернутый на определенный угол. Изящно смотрится, еще изящнее пишется. Короче говоря, идеальный пример. Пошарив по самым дальним закоулкам своего жесткого диска, я таки нашел код, который делал как раз то, что надо — поворачивал текст при выводе на экран под определенным углом. Я давно уже забыл, где и для чего я его использовал, но главное — он был, и он работал. Это все плоды моей идеи о хранилище кода. Но опустим это сейчас, вернемся к коду. Итак, я раскопал его только для того, чтобы убедиться, что он, конечно же, для Delphi. Чуть ниже в книге, когда мы будем говорить о работе с компонентами, вы увидите, как я перевел его на C++. А сейчас это станет потрясающим примером использования кода Delphi в CBuilder.

    Илон Маск рекомендует:  Прижатый подвал, 5 способов

    Код реализован в виде модуля Delphi. Это «самодостаточный» модуль, то есть в нем содержится и описание (interface) функций, и сами функции. В отличие от языка C++, в котором есть отдельный заголовочный файл для описания и исходный (source) файл для реализации, Object Pascal использует один модуль для того и другого. Это проще в эксплуатации, но плохо вяжется с C++. Или все-таки. Давайте посмотрим.

    Рис. 11.3. Форма примера поворота текста

    Создайте форму CBuilder. Добавьте на нее надпись, поле редактирования и кнопку, так, как показано на рис. 11.3. Пространство в центре поля формы будет использовано для отображения повернутого текста. Одно замечание по поводу этой формы: для того чтобы все работало как надо, вам необходимо установить один из шрифтов типа True Type. Если вы выберете свойство font (шрифт) и в его поле в

    Object Inspector щелкнете по кнопке , то увидите список шрифтов, отображен ный в левой части Object Inspector. В этом списке представлены все шрифты, которые могут быть выбраны в системе. Нам нужен один из тех шрифтов, перед названием которого в списке стоят две перекрывающиеся буквы T (TT — True Type). Шрифты True Type масштабируемы, и их можно повернуть при отображении на экран. Обычные, символьные шрифты не могут быть повернуты, и с ними этот пример работать не будет.

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

    unit Rotate; interface Uses

    Graphics, WinTypes, WinProcs;

    procedure AngleTextOut(C : TCanvas; Angle,X,Y :Integer; Str :String); implementation

    procedure AngleTextOut(C : TCanvas; Angle,X,Y :Integer; Str :String); var

    OldFontHandle, NewFontHandle HFONT; begin

    GetObject(C.Font.Handle, SizeOf( LogRec ), Addr( LogRec )); LogRec.lfEscapement := Angle * 10;

    NewFontHandle := CreateFontIndirect( LogRec ); OldFontHandle := SelectObject(C.Handle, NewFontHandle); C.TextOut(X, Y, Str);

    NewFontHandle := SelectObject(C.Handle,OldFontHandle); DeleteObject( NewFontHandle );

    Сохраните этот модуль под именем rotate.pas. Этот модуль способен осуществить всю работу, необходимую для поворота текста в поле формы. Он отображает текст путем временного создания нового шрифта, выбором этого шрифта в контекст устройства (device context) формы и непосредственно отрисовывания текста, после чего избавляется от старого шрифта. Программа не слишком сложна, но вполне отвечает своему назначению.

    Для того чтобы использовать новую форму, вам надо включить новый модуль в модуль формы. Откройте код модуля формы и выберите в главном меню команду File д Include Unit Hdr. Выберите модуль Rotate и нажмите кнопку OK. При этом автоматически сгенерируется новый заголовочный файл для кода модуля rotate.pas формата C++. Если вы теперь взглянете в каталог проекта, то увидите там файл rotate.hpp, который содержит все описания и функции, находящиеся в файле rotate.pas, переведенные на C++. Вот как этот файл выглядит:

    // Rotate.hpp – bcbdcc32 generated hdr (DO NOT EDIT) rev: 0

    #include namespace Rotate

    //–var, const, procedure———————————— extern void __fastcall AngleTextOut(Graphics::Tcanvas* C, int Angle, int X, int Y, System::AnsiString Str);

    extern void __fastcall AngleTextOut(Graphics::Tcanvas* C, int Angle, int X, int Y, System::AnsiString Str);

    extern void __fastcall AngleTextOut(Graphics::Tcanvas* C, int Angle, int X, int Y, System::AnsiString Str);

    #if !defined(NO_IMPLICIT_NAMESPACE_USE) using Namespace Rotate;

    Не стоит пытаться изменить этот файл, о чем предупреждает и комментарий в начале файла. Если вы все же попробуете его изменить, то CBuilder автоматически перепишет его, когда файл rotate.pas будет компилироваться в следующий раз, и ваши изменения, скорее всего, вступят в противоречие с содержимым самого модуля Rotate. Итак, если вы измените этот файл, то в

    лучшем случае программа не скомпилируется, а в худшем — повиснет во время работы.

    Обратите внимание, что CBuilder автоматически генерирует именованную область видимости (namespace), внутрь которой заключает все функции и определения модулей, а также добавляет предложение using в заголовочный файл. Как мы уже говорили ранее на страницах этой книги, это не лучший способ работы с именованными областями видимости, но он позволяет нам вызывать в нашем коде функции напрямую, не волнуясь о том, в которой области она находится. И, что даже более важно, это дает возможность подключать несколько модулей, не заботясь о том, к которому из них принадлежит та или иная функция или объект.

    Замечание

    Если в подключенном модуле оказался объект Pascal, то, как нетрудно убедиться, в сгенерированном заголовочном файле будет полный перевод этого объекта как класса C++. CBuilder практически полностью совместим со всеми типами, используемыми в Object Pascal.

    Последнее, на что стоит обратить внимание в преобразовании, — это на последний параметр функции. В модуле Pascal параметр Str имеет тип String. Этот тип — реализованный в Pascal генеральный тип String. Однако в CBuilder нет класса String, который бы напрямую был связан с этим типом. Вместо этого параметр воспринимается как тип AnsiString, который эквивалентен типу String в Delphi.

    Кроме прочего, для вызова функции нам нужны строка текста и значение угла поворота. Строку мы будем использовать, заранее заданную в коде программы, а угол поворота позволим пользователю вводить в поле редактирования на форме. Для завершения примера нам осталось добавить обработчик для кнопки Отобразить текст. Добавьте обработчик для нее, а в него добавьте следующие строки:

    void __fastcall TForm1::Button1Click(TObject *Sender)

    AngleTextOut(Canvas, atoi(Edit1->Text.c_str()), Width/2, Height/2, «Повернутый текст»);

    Цвет фона текста мы сделали таким же, как цвет формы, чтобы текст не выглядел крикливой, криво налепленной этикеткой. После этого мы устанавливаем начальную точку текста в центр формы, поделив пополам параметры Height (высота) и Width (ширина). От пользователя мы получаем значение угла поворота, заданное им в поле редактирования формы. Угол представляет собой число (градусы) от 0 (соответствующего нормальному, горизонтальному расположению текста) до 360. Теперь, после того как весь код набран, давайте пойдем дальше и скомпилируем и соберем наше приложение в CBuilder. При этом автоматически скомпилируются модуль Pascal и модуль формы C++, после чего они будут собраны воедино.

    Отметьте, что компилятор Pascal автоматически запускается для модулей с расширением .pas.

    После того как со сборкой приложения будет покончено, попробуйте запустить его. Введите несколько различных значений угла поворота, нажимая каждый раз на кнопку Отобразить текст. После этого ваша форма будет выглядеть примерно так же, как показано на рис. 11.4. На этом пример программы поворота текста закончен, надеюсь, он достаточно наглядно показал вам, насколько просто можно использовать функции Pascal в приложениях на CBuilder.

    Рис. 11.4. Программа поворота текста в действии

    Несмотря на то что этот пример был не чересчур сложным, в нем показано все, что вам надо знать об использовании модулей Pascal в CBuilder. Если модуль компилируется в Delphi, он, скорее всего, будет компилироваться и в CBuilder. Ограничения существуют только для версии CBuilder 1.0. В приложениях, написанных на Delphi 3.0, нельзя использовать никаких новых компонентов VCL для форм, которые будут экспортироваться в CBuilder 1.0. Точно так же нельзя использовать и функции Delphi 3.0, которых нет в версии Delphi 2.0. CBuilder 1.0 совместим с Delphi 2.0 и почти совместим с Delphi 3.0, хотя, конечно, между ними и существуют различия. В отношении CBuilder 3.0 подобных ограничений не обнаружено.

    Когда я работал над созданием форм в Delphi 3.0 для последующего использования в CBuilder, то выяснил, что обычно практически все переводится правильно. Использование любого из новых компонентов (например, таких как TCoolBar) в Delphi 3.0 влечет за собой невозможность использования этой формы в CBuilder 1.0. Версия CBuilder 3.0 полностью совместима с Delphi 3.0. К середине 1998 года фирма Borland привела в соответствие друг другу два своих главных программных продукта, так чтобы все последующие их версии были полностью совместимы.

    Замечание

    Вы можете поинтересоваться, а нет ли возможности (при том, что CBuilder может использовать формы Delphi 3.0) использовать формы CBuilder в Delphi 3.0? Как ни странно, нет. Delphi 3.0 поставляется без компилятора C++, в то время как CBuilder включает в себя полный компилятор Pascal. Так что формы CBuilder использовать в Delphi 3.0 нельзя.

    Источник: Теллес М. – Borland C++ Builder. Библиотека программиста – 1998

    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL