Как изменить тип переменной паскаль

Работа по теме: Программирование. Глава: 20. Приведение типов в Паскале.. ВУЗ: НГТУ.

При
компиляции программы выполняется
контроль правильности использования
типов данных в выражениях и операторах
присваивания.

“Type
mismatch”
(несоответствие типов)

Var
k:byte;

x:integer;

y:real;

ch:char;

Правила работы с типами данных

  1. y:=x,
    x:=k
    – повышение типов (разрешено в Паскале)

x:=10/k
— – понижение типов (запрещено)

x:=10+’5’
– понижение типов (запрещено)

  1. x:=round
    (y);
    x:=trunc
    (y);
    {вещественное в целое (целая часть /
    округление}

  2. k:=ord(ch);
    ch:=chr(k);
    {символ в код(число) и наоборот}

  3. val
    (str:string,
    var
    number,
    var
    code:byte)
    {Текстовые строки, представляющие
    запись числовых констант – в числа}

В ряде
случаев в Pascal происходит автоматический
переход от одного типа данных к другому
(от целого к действительному, от
символьного к строковому и т.д.). Существует
также ряд функций, осуществляющих
преобразование типов (ord, chr, trunc, round).
Наряду с этим в Паскаль возможно явное
преобразование типов (ретипизация
данных). Для того, чтобы осуществить
явное преобразование типа, необходимо
использовать имя типа аналогично тому,
как используется имя функции. В качестве
параметра в этом случае указывается
имя преобразуемой переменной.

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

Пример задачи, где используется явное преобразование типов

Вычислить
значение функции sign(x) = 1 при x>0; 0 при
x=0; -1 при x<0.

var

x:
real;

sign:
integer;

begin

readln(x);

sign:=
byte(x>0)-byte(x<0);

writeln(sign);

end.

В
программе при положительном значении
x выражение x>0 принимает значение true,
а выражение x<0 — false. В результате
получается, что byte(x>0) = 1, byte(x<0)=0, а
sign=1. При отрицательном значении x
byte(x>0)=0, byte(x<0)=1, sign=-1. При нулевом
значении x sign=0.

21. Тип множество (Set).

В
языке программирования Pascal существует
понятие множества, имеющее смысл
некоторого собрания элементов, одно и
того же базового типа. Базовый тип
определяет перечень всех элементов,
которые вообще могут содержаться в
данном множестве. В качестве базового
типа может выступать любой простой
порядковый тип. Но вещественные числа
(realне порядковый тип) и строки (не
простой и не порядковый тип) не могут
быть элементами множества.

Отрицательные
элементы множеств в Turbo Pascal не допускаются.
Поэтому базовыми типами не могут быть
типы shortint, integer, longint. Если же необходимо
множество целочисленных объектов, то
базовый тип должен объявлен как диапазон
типаbyte.

Порядок
элементов во множестве не имеет значения.
Так, записав [3, 6, 9] или [9, 3, 6], мы будем
иметь дело с одним и тем же множеством.
Более того, многократное повторение
одного и того же элемента не меняет
множество. Например, [4, 7, 3] и [3, 7, 4, 4] –
это одно и то же множество.

По
форме записи объявление переменной
типа множество сходно с объявлением
одномерного массива:

var

имя:
set
of
тип;

Например,
объявление переменной ch,
рассматриваемой как множество с базовым
типомchar, имеет вид:

var

ch:
set
of
char;

В
отличие от элементов массива, элементы
множества не упорядочены и не имеют
индексов.

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

type

week_days
=
(Mon,
Tue,
Wed,
Thu,
Fri);

var

work_days:
set
of
week_days;

lett:
set
of
‘A’..’Z’;

Объявление
переменной-множества не дает ей
определенного значения.

Построение
множества

Чтобы
во множестве появились элементы,
необходимо выполнить оператор
присваивания, в левой части которого
стоит имя переменной-множества, а в
правой — конструктор множества или
некоторое выражение над множествами.

Конструктор
множества

— это заключенный в квадратные скобки
перечень элементов, разделенных запятыми.
В качестве элементов могут использоваться
диапазоны значений:

type

week_days
=
(Mon,
Tue,
Wed,
Thu,
Fri);

var

work_days:
set
of
week_days;

lett:
set
of
‘A’..’Z’;

begin

work_days
:=
[Mon,
Wed,
Thu];

lett
:=
[‘C’,
‘E’..’M’,
‘Z’]

end.

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

Множество,
в котором нет элементов, называется
пустым (или нуль-множеством). В языке
программирования Паскаль обозначается
квадратными скобками, между которыми
нет элементов:

work_days
:=
[
];

Элементы
множества нельзя вводить и выводить.
Для организации ввода-вывода элементов
множества следует использовать
вспомогательные переменные. В то же
время можно использовать множества как
элементы типизированных файлов.

Операции,
применимые к множественному типу:

  1. Объединение

[1,3,4]+[1,2,4,6]=[1…4,6]

  1. Пересечение

[1,3,4]*[1,2,6]=[1]

  1. Вычитание
    (элементы первого множества, не вошедшие
    во второе)

[1,3,4]-[1,2,4,6]=[3]

  1. Проверка
    эквивалентности

P:=([1,2,5]=[1..5]);
{p=false}

  1. Проверка
    неэквивалентности

P:=([1,2,3]<>[1..5]);
{p=true}

  1. Проверка
    на принадлежность элементов множеству

2
in
[1,2,4,6] – true

  1. Включение
    подмножества в множество

[1,5]<=[1,3,5,6]
– true

[1,5]>=[1,3,5]
– false

Манипулируя
операциями над множествами, можно
добавлять элементы к множествам или
удалять их.

Для
вставки и удаления элементов при работе
с множествами в Pascal введены две процедуры:

include
(имя_множества, элемент)

exclude
(имя_множества, элемент)

Первая
из них позволяет выполнить добавление
одного элемента в указанное множество,
а вторая удалить. Например:

include
(chs1,
‘g’);
{
аналогично
chs1 + [‘g’] }

exclude
(chs2,
‘a’); {
аналогично
chs2 — [‘a’] }

Другие
операции над множествами

Над
множествами можно выполнять четыре
операции сравнения: =, <>, >=, <=.

Два
множества A и B равны (A = B), если каждый
элемент множества A является элементом
множества B и наоборот.

Два
множества A и B не равны (A <> B), если
они отличаются хотя бы одним элементом.

Множество
A является подмножеством множества B (A
<= B, или B >= A), если каждый элемент из
A присутствует в B.

Имеется
также возможность выяснить, принадлежит
ли данный элемент некоторому множеству.
Для этого служит операция in. ПустьA– множество элементов некоторого
базового типа, аx– переменная (константа, выражение)
этого типа. Тогда выражениеx
in
Aистинно, если значениеxявляется элементом множестваA.

Все
операции сравнения множеств, а также
операция inвозвращают логическое
значениеtrueилиfalse.

В
сложных выражениях над множествами
операции имеют следующие приоритеты:

  1. *

  2. +,

  3. =,
    <>, <=, >=, in

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #







Deutsch (de)
English (en)




français (fr)










русский (ru)









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

Определение

Различают два варианта приведения типов:

Неявное приведение типов

Если полный диапазон значений, которые может иметь источник, может быть сохранен целевым операндом, происходит автоматическая — то есть «неявная» — передача типа. Например, все значения типа byte могут быть сохранены в int64. Присвоение значения типа byte для int64 работает без проблем, поскольку пропущенные нулевые биты заполняются автоматически, то есть неявно.
Программист не должен вставлять дополнительный код.


Прим.перев.: иными словами, преобразование переменных с меньшим диапазоном значений в переменные с большим диапазоном значений происходит автоматически (неявное преобразование).


Явное приведение типов

Если диапазон значений источника не вписывается в диапазон целевого операнда, компилятор не скомпилирует программу, если ему не дано [указаний явно] игнорировать это.


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


Существует два разных варианта явного приведения типа:

Value typecasts (приведение типа для значения)

Преобразование типов осуществляется путем добавления идентификатора типа данных и заключения выражения для преобразования типов в круглые скобки, например: dataType(expression).
Лишние биты просто отбрасываются.
Этот подход обычно используется, если есть абсолютная уверенность, что фактическое значение expression будет соответствовать ожидаемому.
Иногда этот эффект также используется вместо применения оператора Mod.

Variable typecasts (приведение типа для переменной)

Такое приведение типа обрабатывает переменную, как если бы это был другой тип.
Извлечение и сохранение переменной выполняется, как если бы это был указанный тип данных.
Так же, как и в случае приведения типа для значения, перед типом данных добавляется идентификатор типа, а в этом случае круглые скобки окружают идентификатор переменной:
dataTypeIdentifier(variableIdentifier).
В отличие от приведения типа для значения, приведения типа для переменной может происходить с обеих сторон присваивания.

Преобразование в сравнении с приведением типов

Преобразование типов — это упорядоченный процесс отображения значений домена в совместный домен, что может привести к возникновению исключений или ошибок времени выполнения. Это делается с помощью правильно определенных функций. Простое приведение типов, с другой стороны, это всегда грубая сила. Оно обрезает и заталкивает биты 1:1 адресату. Однако вы можете задать перегрузку оператора, переопределяя это поведение.

В некоторых случаях вы можете конвертировать значения:

возможности конверсии

исходный тип данных конечный тип данных вариант преобразования типа метод
integer real неявный оператор присваивания
real integer явный
  • trunc отсекает дробную часть
  • round округляет дробную часть
integer string явный sysUtils.intToStr
real string явный
  • sysUtils.floatToStr
  • sysUtils.floatToStrF
string integer явный sysUtils.strToInt
string real явный sysUtils.strToFloat
string char явный stringVariable[indexExpression]
char/ANSIChar/wideChar string неявный оператор присваивания
char/ANSIChar byte явный
  • ord
  • byte(characterVariableOrExpression)
byte char/ANSIChar явный
  • chr
  • ANSIChar(byteVariableOrExpression)
перечислимый тип string явный system.writeStr(stringVariable, enumeratedVariableOrExpression)

В других случаях вы должны вручную выполнить явное приведение типов:

приведение типов

исходный тип данных конечный тип данных вариант преобразования типов метод
qWord byte явный byte(qWordVariableOrExpression)
qWord word явный word(qWordVariableOrExpression)
qWord cardinal явный cardinal(qWordVariableOrExpression)
qWord longWord явный longWord(qWordVariableOrExpression)
longWord byte явный byte(longWordVariableOrExpression)
longWord word явный word(longWordVariableOrExpression)
longWord cardinal неявный оператор присваивания
int64 byte явный byte(int64variableOrExpression)
int64 shortInt явный shortInt(int64variableOrExpression)
comp byte явный byte(compVariableOrExpression)
comp shortInt явный shortInt(compVariableOrExpression)
comp real явный real(compVariableOrExpression)

Предостережение

  • Явное приведение типов отключает проверку диапазона в полной строке кода.

См.также

  • «Кастинг типов (компьютерное программирование)» в русской Википедии
  • § “value typecasts” в справочном руководстве FreePascal
  • § “variable typecasts” в справочном руководстве FreePascal
  • § “unaligned typecasts” в справочном руководстве FreePascal
  • Перегрузка операторов (особая группа операторов присваивания и § «маршрутизация»)

В Паскале оператор присваивания не всегда работает, даже если он написан синтаксически верно. Когда мы производим вычисления с известными числами, результат известен и проблем не возникает. С переменными же все проходит не всегда так гладко, поскольку переменные типов Integer и Real хранятся по-разному (занимают разный объем памяти). Компьютер устроен так, что выполнять действия он может только с одинаковыми объектами. Возьмем следующую программу: program wrong; var a :Integer; b :Real; begin b : =2; a : =2. 9; {Здесь содержится ошибка!} end.

Если набрать эту программу и попробовать ее оттранслировать, получим сообщение об ошибке Нарушение соответствия типов. Курсор при этом укажет на ту строку, у которой в комментарии сказано, что здесь содержится ошибка. Давайте разберемся в причинах появления данного сообщения. В первом операторе переменной вещественного типа присваивается целое число 2. Ошибки здесь нет, поскольку произойдет так называемое преобразование типа, при котором число 2 будет представлено в виде десятичной дроби 2. 0 и записано в b. А наоборот нельзя — в целую переменную a дробное число 2. 9 не запишется, и транслятор выдаст ошибку. Такие ситуации возникают очень часто, и сложнее всего бывает разобраться со случаем, когда используется операция деления «/» (например, что будет с результатом f / 2, где f — целое число?). Существует несколько правил, два из которых уже были описаны ранее (в переменную вещественного типа можно записать целое число, а наоборот — нельзя). Остальные правила, касающиеся выполнения арифметических операций, представлены в следующей таблице.

Операция Тип операнда Тип результата Пример Результат первый второй

+,*, — Integer Integer Integer 2 + 27 29

+,*, — Integer Real Real 2 -3. 5 -1. 5

+,*, — Real Integer Real 3. 0 — 27 -24. 0

+,*, — Real Real Real 2. 5 * 2. 5 6. 25

/ любой любой Real 8/2 4. 0

Что делать, если надо получить в результате целое число, пусть даже округленное? В этом случае можно воспользоваться одной из двух встроенных функций Паскаля: Trunc(a) или Round (а). Встроенные функции пока можно считать обычными операторами языка Паскаль. Здесь Тrunс отбрасывает дробную часть аргумента, a Round округляет его по правилам математики до ближайшего целого. Примеры:

Trunc(2. 73) = 2;

Trunc(-3. 4) = -3;

Trunc(1. 9) = 1;

Round (2. 5) = 3;

Round(-3. 7) = -4. 0.

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

Программа для вычисления этого выражения пишется очень просто — в две строчки. В первой вводим значение х, а во второй выводим результат: program polynomial; var х :Real; begin

Write(‘Введите x:’);

Readln(x);

Write(x*x*x*x*x+7*x*x*x*x-18*x*x*x+9*x*x-x+8); end.

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

= х (х (х (х (х+7)- 18) + 9) — 1) + 8.

После преобразования количество операций уменьшилось до 9, то есть тот же результат мы получим быстрее: program polynomial_fast; var х :Real; begin

Write(‘Введите х:’);

ReadLn(x);

Write(x * (x *(х * (х *(х + 7) — 18) + 9) — 1) + 8); end.

Этот метод вычисления значения многочлена называется схемой Горнера.

Встроенные функции. Кроме упомянутых функций Round и Trunc в Паскале существует целый ряд других встроенных функций. Далее приводятся наиболее распространенные из них.

Функция Тип аргумента х Результат

Sqrt(x) Real или Integer корень квадратный из х

Abs(x) Real или Integer модуль х

Sin(x) Real или Integer синус х

Cos(x) Real или Integer косинус х

Pred(x) Integer следующее целое после х

Succ(x) Integer предыдущее целое до х

Sqr(x) Real или Integer квадрат х

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

+ Sin(x), Cos(x), Sqrt(x) —вещественного;

+ Pred(x), Succ(x) — целого;

+ Sqr(x), Abs(x) — того же типа, что и аргумент.

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

Мы теоретически подкованы. Теперь можно перейти к практической части.

В Турбо Паскале имеется очень мощное средство, позволяющее обойти всевозможные ограничения на совместимость типов или значений: определена операция приведения типа. Она применима только к переменным и значениям. Суть этой операции в следующем. Определяя тип, мы определяем форму хранения информации в ОЗУ, и переменная данного типа будет представлена в памяти заранее известной структурой. Но если «взглянуть» на ее образ в памяти с точки зрения машинного представления другого типа, то можно будет трактовать то же самое значение как принадлежащее другому типу. Для этого достаточно использовать конструкцию

ИмяТипа( ПеременнаяИлиЗначение )

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

— 90 —

| TYPE

| Arr4Byte = Array[1..4] of Byte; { массив из 4-х байтов }

| Arr2Word = Array[1..2] of Word; { массив из двух слов }

| RecType = RECORD

| Word1, Word2 : Word { запись из двух слов }

| END;

| VAR

| L : LongInt; { четырехбайтовое целое со знаком }

| S : ShortInt; { однобайтовое целое со знаком }

| В : Byte; { однобайтовое целое без знака }

| W : Word; { двухбайтовое целое без знака }

| a4 : Arr4Byte; { массив из четырех байтов }

| a2 : Arr2Word; { массив из двух слов по два байта }

| Rec : RecType; { запись из двух слов по два байта }

| BEGIN

| L := 123456; { некое значение переменной L }

| S := -2; { некое значение переменной S }

| a2 := arr2Word( L ); { два слова L перешли в массив a2 }

| a4 := arr4Byte( L ); {четыре байта L перешли в a4 }

| W := RecType( L ).Word1; { доступ к L по частям

| W := arr2Word( L )[ 1 ];

| RecType(L).Word1 := 0; { обнуление первого слова в L }

| B := Byte( S ); { если S=-2, то B станет 254 }

| B := Arr4Byte( a2 )[1]; { запись в B значения первого }

{полуслова массива a2 }

| END.

Приведение типов не переопределяет типы переменных. Оно лишь дает возможность нарушить правила совмещения типов при условии, что соответствующие значения совместимы в машинном представлении. При преобразовании типа переменной ее размер всегда должен быть равен размеру типа, к которому приводится значение. Если после приведения переменной к структуре мы хотим воспользоваться отдельным ее элементом, то просто приписываем индекс (для массивов) или поле (для записей). Вообще говоря, конструкцию ИмяТипа( Переменная ) можно условно считать именем некой необъявленной переменной типа «ИмяТипа» и со значением, хранимым в «Переменной». Приведение типа переменной может стоять как слева, так и справа, т.е. может участвовать в выражениях. Допускается вложенность преобразований при условии сохранения размеров. Как видно из примера, можно изменять определенные байты общей структуры переменной в памяти независимо от ее типа.

— 91 —

Аналогично изменению типа переменных можно изменять тип значений как таковых, а также результирующий тип выражений, т.е. разрешены такие преобразования:

Integer( ‘Y’ ) { код символа ‘Y’ в формате Integer }

Boolean( 1 ) { это логическое значение True }

LongInt( 1 ) { значение 1, размещенное в четырех байтах}

Char ( 130-1 ) { символ с кодом ASCII номер 129 }

В этом случае происходит трактование значения в скобках как значения другого типа. Например, символ ‘Y’ хранится как код 89 и занимает один байт. Но конструкция Integer (‘Y’) представляет собой значение 89 в формате целого числа со знаком (в двух байтах). Как видно, при преобразовании типа значений соблюдение размера уже не нужно. Новый тип может быть шире, а может быть и короче, чем естественный тип значения.

При приведении значения в более широкий тип (например, LongInt(1)) значения будут целиком записаны в младшие (наименее значащие) байты, что сохранит само значение. В противоположном случае, когда значение приводится к более короткому типу, от него берутся уже не все, а лишь самые младшие байты. При этом старшие байты игнорируются, и приведенное значение не равно исходному. Например, выражение Byte( 534 ) равно 22, поскольку значение 534 кодируется в тип Word и раскладывается на младший и старший байты как 22 + 2*256. Младший байт (22) мы получим, а старший (со значением 2) проигнорируем.

Преобразование типа значения внешне похоже на преобразование типа переменной. Но эффект от него несколько иной (за счет возможности изменения размера), и ограничения на применение другие. В частности, как задаваемый тип, так и тип значения (выражения) должны быть перечислимыми (это все целочисленные типы, тип Char, Boolean и вводимые перечисления) или адресными (адресные значения хранятся как значения LongInt). По понятным причинам преобразование значения не может появиться в левой части присваивания.

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

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

— 92 —

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

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

— 93 —

страницы: 1 2 3

Содержание

  • Содержание
  • Совместимость типов данных
    • Эквивалентность
    • Совместимость
    • Совместимость по присваиванию
    • Приведение типов данных
      • Неявное приведение типов данных
      • Явное приведение типов данных
      • Функции, изменяющие тип данных
  • Примечания

Совместимость типов данных

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

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

Правила, по которым различные типы данных считаются взаимозаменяемыми, мы приводим ниже.

Эквивалентность

Эквивалентность — это наиболее высокий уровень соответствия типов. Она требуется при действиях с указателями (см. лекцию 10), а также при вызовах подпрограмм. «А как же тогда быть с оговоркой, сделанной двумя абзацами выше?» — спросите вы. Мы не станем сейчас описывать механизм передачи аргументов процедурам и функциям, поясним лишь, что эквивалентность типов требуется только для параметров–переменных (см. лекцию 8).

Итак, два типа — Т1 и Т2 — будут эквивалентными, если верен хотя бы один вариант из перечисленных ниже:

  • Т1 и Т2 совпадают;
  • Т1 и Т2 определены в одном объявлении типа;
  • Т1 эквивалентен некоторому типу Т3, который эквивалентен типу Т2.

Поясним это на примере:

type T2 = T1;
  T3 = T1;
  T4, T5 = T2;

Здесь эквивалентными будут Т1 и Т2; Т1 и Т3; Т1 и Т4; Т1 и Т5; Т4 и Т5. А вот Т2 и Т3 — не эквивалентны!

Совместимость

Совместимость типов требуется при конструировании выражений, а также при вызовах подпрограмм (для параметров–значений). Совместимость означает, что для переменных этих типов возможна операция присваивания — хотя во время этой операции присваиваемое значение может измениться: произойдёт неявное приведение типов данных (см. п. «Приведение типов данных» ниже).

Два типа Т1 и Т2 будут совместимыми, если верен хотя бы один вариант из перечисленных ниже:

  • Т1 и Т2 эквивалентны (в том числе совпадают);
  • Т1 и Т2 — оба целочисленные или оба вещественные;
  • Т1 и Т2 являются подмножествами одного типа;
  • Т1 является некоторым подмножеством Т2;
  • Т1 — строка, а Т2 — символ (см. лекцию 5);
  • Т1 — это тип Pointer, а Т2 — типизированный указатель (см. лекцию 10);
  • Т1 и Т2 — оба процедурные, с одинаковым количеством попарно эквивалентных параметров, а для функций — с эквивалентными типами результатов (см. лекцию 8).

Совместимость по присваиванию

В отличие от простой совместимости, совместимость по присваиванию гарантирует, что в тех случаях, когда производится какое–либо присваивание (используется запись вида a := b; или происходит передача значений в подпрограмму1 или из неё и т. п.), не произойдёт никаких изменений присваиваемого значения.

Два типа данных Т1 и Т2 называются совместимыми по присваиванию, если выполняется хотя бы один вариант из перечисленных ниже:

  • Т1 и Т2 эквивалентны, но не файлы2;
  • Т1 и Т2 совместимы, причём, Т2 — некоторое подмножество в Т1;
  • Т1 — вещественный тип, а Т2 — целый.

Приведение типов данных

Неявное приведение типов данных

Как мы упомянули в п. «Арифметические операции» выше, тип результата арифметических операций (а следовательно, и выражений) может отличаться от типов исходных операндов. Например, при «дробном» делении ( / ) одного целого числа на другое целое в ответе всё равно получается вещественное. Такое изменение типа данных называется неявным приведением типов.

Если в некоторой операции присваивания участвуют два типа данных совместимых, но не совместимых по присваиванию, то тип присваиваемого выражения автоматически заменяется на подходящий. Это тоже неявное приведение. Причём, в этих случаях могут возникать изменения значений. Скажем, если выполнить такую последовательность операторов

a := 10;   {a : Byte}
a := a;
WriteLn(a);

то на экране мы увидим не -10, а 246 (246 = 256 — 10).

Неявным образом осуществляется и приведение при несоответствии типов переменной–счётчика и границ в циклах for (см. лекцию 3).

Неявное приведение типов данных можно отключить, если указать директиву компилятора {$R+}, которая принуждает компилятор всегда проверять границы и диапазоны. Если эта директива включена, то во всех ситуациях, в которых по умолчанию достаточно совместимости типов данных, будет необходима их эквивалентность.

По умолчанию такая проверка отключена, поэтому во всём дальнейшем изложении (если, конечно, явно не оговорено противное) мы будем считать, что эта директива находится в выключенном состоянии {$R-}.

Явное приведение типов данных

Тип значения можно изменить и явным способом: просто указав новый тип выражения, например: a := Byte(b). В этом случае переменной а будет присвоено значение, полученное новой интерпретацией значения переменной b. Скажем, если b имеет тип ShortInt и значение -23, то в a запишется 233 (= 256 — 23).

Приводить явным образом можно и типы, различающиеся по длине. Тогда значение может измениться в соответствии с новым типом. Скажем, если преобразовать тип LongInt в тип Integer, то возможны потери из–за отсечения первых двух байтов исходного числа. Например, результатом попытки преобразовать число 100 000 к типу Integer станет число -31 072, а к типу Word — число 34 464.

Функции, изменяющие тип данных

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

страницы: 1 2 3

Примечания

  1. ^ В параметр–значение (см. лекцию 8).
  2. ^ Запрещается даже участие файлового типа как поля любого уровня в структурированных типах данных.

изменить тип переменной

Модератор: Модераторы

Вот есть переменная slovo типа string и она принимает значения в том числе числовые. Подскажите как числовой переменной присвоить значение строковой, если конечно это возможно.
Иными словами. я разбил строку на слова
154318 EURUSD 04.01.2005 2:00:01 700000 1.3535 0.00 0.00 -2
с некоторыми из них мне нужно сделать арифметические действия, но ведь они строковые…

baklan
новенький
 
Сообщения: 18
Зарегистрирован: 23.10.2005 21:07:00
Откуда: Москва
  • Профиль
  • Сайт


Сообщение STAKANOV » 28.10.2005 23:50:20

а так же IntToStr и FloatToStr

Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград
  • Профиль
  • Сайт
  • ICQ

Сообщение baklan » 29.10.2005 09:54:05

Да , спасибо, оказалось все просто, применил
Val(slovo, znachenie,code)
Жаль, что искать пришлось оооочень долго. Документации для чайников не нашел нигде.

baklan
новенький
 
Сообщения: 18
Зарегистрирован: 23.10.2005 21:07:00
Откуда: Москва
  • Профиль
  • Сайт

Сообщение Guest » 29.10.2005 21:44:08

baklan писал(а): Да , спасибо, оказалось все просто, применил
Val(slovo, znachenie,code)
Жаль, что искать пришлось оооочень долго. Документации для чайников не нашел нигде.

Теперь главное — всешда помни о важгости десятичной точки, для этой процедуры это всегда «.»

Guest
 

Сообщение baklan » 30.10.2005 13:34:20

Guest писал(а): Теперь главное — всешда помни о важгости десятичной точки, для этой процедуры это всегда «.»

не понял про точку… , разве в целое число я не могу преобразовать?

baklan
новенький
 
Сообщения: 18
Зарегистрирован: 23.10.2005 21:07:00
Откуда: Москва
  • Профиль
  • Сайт

Сообщение STAKANOV » 30.10.2005 14:16:46

baklan писал(а):

Guest писал(а): Теперь главное — всешда помни о важгости десятичной точки, для этой процедуры это всегда «.»

не понял про точку… , разве в целое число я не могу преобразовать?

Можешь ) Прсто при преобразованиях вещественных значений для Str и Val десятичная точка это всегда «.», а для FloatToStr и StrToFloat это зависит от настроек локализации системы.

Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград
  • Профиль
  • Сайт
  • ICQ

Сообщение baklan » 30.10.2005 16:07:09

Понял, спасибо, я все на точку настроил, так что у меня везде точка будет.

baklan
новенький
 
Сообщения: 18
Зарегистрирован: 23.10.2005 21:07:00
Откуда: Москва
  • Профиль
  • Сайт

Сообщение baklan » 30.10.2005 16:56:02

Теперь другая проблема, функция StrToFloat описана так
Function StrToFloat(Const S : String) : Extended;
выходит, что она может преобразовать только константу? а как же с простой переменной?

baklan
новенький
 
Сообщения: 18
Зарегистрирован: 23.10.2005 21:07:00
Откуда: Москва
  • Профиль
  • Сайт

Сообщение Sphinx » 31.10.2005 14:08:55

Function StrToFloat(Const S : String) : Extended;

тут Const имеет несколько инной смысл — в саму процедуру величина передается как константа, то есть при выходе из процедуры не сохраняется результат преобразований переменной S, если такое имело место быть в процедуре.

Sphinx
новенький
 
Сообщения: 33
Зарегистрирован: 27.09.2005 21:52:09

Сообщение baklan » 31.10.2005 14:26:55

Компилируется нормально, но при выполнении выдает
An unhandled exception occurred at $00408B79 :
EConvertError : «» is an invalid float

Вот фрагмент кода

var
middle : single;
slovo : string;
…….
middle := StrToFloat (slovo);

baklan
новенький
 
Сообщения: 18
Зарегистрирован: 23.10.2005 21:07:00
Откуда: Москва
  • Профиль
  • Сайт

Сообщение Гость_PVOzerski » 31.10.2005 14:49:45

Почти наверняка несоответствия либо с разделителем десятичным, либо с разделителем тычяч. Проверь значения переменных ThousandSeparator+’##0’+DecimalSeparator

Гость_PVOzerski
 

Сообщение PVOzerski » 31.10.2005 14:53:12

Имелось в вид следующее: :) Сорри за невовремя нажатую кнопку :)

Почти наверняка несоответствия либо с разделителем десятичным, либо с разделителем тычяч. Проверь значения переменных ThousandSeparator и DecimalSeparator.

PVOzerski
постоялец
 
Сообщения: 109
Зарегистрирован: 19.05.2005 13:45:10
Откуда: СПб
  • Профиль
  • Сайт

Сообщение STAKANOV » 31.10.2005 21:11:11

baklan писал(а): Компилируется нормально, но при выполнении выдает
An unhandled exception occurred at $00408B79 :
EConvertError : «» is an invalid float

Вот фрагмент кода

var
middle : single;
slovo : string;
…….
middle := StrToFloat (slovo);

а slovo чему равно ?

Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград
  • Профиль
  • Сайт
  • ICQ

Сообщение baklan » 31.10.2005 21:27:39

переменная slovo собирается по символам slovo := slovo + c;
и если вывести его не преобразовывая, то оно выводится примерно так 1.2305
Я пробовал и менять точку на запятую, результат тот же. Ну собственно я уже бросил, терпения не хватило, ща накачал кучу документации, разбираюсь пока теоретически. В голове каша, все языки разные…

baklan
новенький
 
Сообщения: 18
Зарегистрирован: 23.10.2005 21:07:00
Откуда: Москва
  • Профиль
  • Сайт


Вернуться в Free Pascal Compiler

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7

0 / 0 / 0

Регистрация: 21.03.2010

Сообщений: 8

1

Смена типа данных

21.03.2010, 23:32. Показов 8727. Ответов 4


Люди помогите плз, у меня тут возникла небольшая проблемка. У меня дано число K: Integer (Например 1999) и дана числовая переменная Str: String. Как к тексту в переменной str добавить число K?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



76 / 62 / 23

Регистрация: 11.07.2009

Сообщений: 730

21.03.2010, 23:40

2

если во фрипаскале, то там вроде бы есть приведение классов как StrToInt & IntToStr, c ТП не знаю как поступить



0



NeroAngelo

0 / 0 / 0

Регистрация: 21.03.2010

Сообщений: 8

21.03.2010, 23:47

 [ТС]

3

Нее, у меня в ТП задачка поставленна, я почти её сделал, только с этим проблемка

Добавлено через 4 минуты
Вот программка:

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Program example_3;
const M=1000; C=100; X=10; V=5; I=1;
Var
    iSymbol,
    iWord,
    n,j,k:Integer;
    s,ch,q:Char;
    str:String;
    f1,f2:Text;
Begin
    Assign(f1,'file.txt');Reset(f1);
    Assign(f2,'file_r.txt');Rewrite(f2);
    WriteLn(f2,'Pochatkovuy tekst':30);
    While Not Eof(f1) do
       Begin  ReadLn(f1,str);
    k:=0;
    for j:=1 to length(str) do
    begin
     case str[j] of
     'I': if (str[j]='I') and (str[j+1]='V') then begin k:=k+4;inc(j);end
     else if (str[j]='I') and (str[j+1]='X') then begin k:=k+9;inc(j);end
     else if (str[j]='I') and (str[j+1]='C') then begin k:=k+99;inc(j);end
     else if (str[j]='I') and (str[j+1]='M') then begin k:=k+999;inc(j);end
     else k:=k+i;
     'V': k:=k+v;
     'X': if (str[j]='X') and (str[j+1]='C') then begin k:=k+90;inc(j);end
     else if (str[j]='X') and (str[j+1]='M') then begin k:=k+990;inc(j);end
     else k:=k+x;
     'C': if (str[j]='C') and (str[j-1]='M') then begin k:=k+900;inc(j);end
     else k:=k+c;
     'M': k:=k+m;
     end;
     end;
    WriteLn(f2,str);
         End;
    iSymbol:=0;iWord:=0;n:=0;str:='';
    WriteLn(f2,'Pereroblennuy tekst':30);
    Reset(f1);
    [U]str:=k;[/U]                            {Type missmatch}
    Close(f1);Close(f2);Reset(f2);
    While Not Eof(f2) do
         Begin ReadLn(f2,str);WriteLn(str); End;
     Close(f2);
End.

Не знаю что с этим сделать



0



Retired

7726 / 2558 / 671

Регистрация: 17.10.2009

Сообщений: 5,100

21.03.2010, 23:51

4

NeroAngelo, для перевода строки в число есть процедура Val, а для перевода числа в строку есть процедура Str.



1



0 / 0 / 0

Регистрация: 21.03.2010

Сообщений: 8

22.03.2010, 00:01

 [ТС]

5

Цитата
Сообщение от Inadequate
Посмотреть сообщение

NeroAngelo, для перевода строки в число есть процедура Val, а для перевода числа в строку есть процедура Str.

Большое спасибо, как я раньше не вспомнил за них. =)



0



Понравилась статья? Поделить с друзьями:

Читайте также:

  • Как изменить тип открытия файла
  • Как изменить тип окс
  • Как изменить тип объявления на авито
  • Как изменить тип общения
  • Как изменить тип оборудования

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии