Совместимость и преобразование типов
Как уже неоднократно отмечалось, Турбо Паскаль - это типизированный язык. Он построен на основе строгого соблюдения концепции типов, в соответствии с которой все применяемые в языке операции определены только над операндами совместимых типов. При обсуждении операций над вещественными данными мы уже затрагивали проблему совместимости вещественных и целых типов. Аналогичные проблемы возникают при операциях над строками разной длины, строками и символами и т.д. Ниже приводится более полное определение совместимости типов. Два типа считаются совместимыми, если: · оба они есть один и тот же тип; · оба вещественные; · оба целые; · один тип есть тип-диапазон второго типа; · оба являются типами-диапазонами одного и того же базового типа; · оба являются множествами, составленными из элементов одного и того же базового типа; · оба являются упакованными строками (определены с предшествующим словом PACKED) одинаковой максимальной длины; · один тип есть тип-строка, а другой - тип-строка, упакованная строка или символ; · один тип есть любой указатель, а другой - нетипизированный указатель; · один тип есть указатель на объект, а другой - указатель на родственный ему объект; · оба есть процедурные типы с одинаковыми типом результата (для типа-функции), количеством параметров и типом взаимно соответствующих параметров. Совместимость типов приобретает особое значение в операторах присваивания. Пусть T1 - тип переменной, а Т2 - тип выражения, т.е. выполняется присваивание T1:= T2. Это присваивание возможно в следующих случаях: · T1 и T2 есть один и тот же тип и этот тип не относится к файлам или массивам файлов, или записям, содержащим поля-файлы, или массивам таких записей;
· T1 и T2 являются совместимыми порядковыми типами и значение T2 лежит в диапазоне возможных значений T1; · T1 и T2 являются вещественными типами и значение T2 лежит в диапазоне возможных значений T1; · T1 - вещественный тип и T2 - целый тип;, · T1 - строка и T2 - символ; · T1 - строка и T2 - упакованная строка; · T1 и T2 - совместимые упакованные строки; · T1 и T2 - совместимые множества и все члены T2 принадлежат множеству возможных значений T1; · T1 и T2 - совместимые указатели; · T1 и T2 - совместимые процедурные типы; · T1 - объект и T2 - его потомок. В программе данные одного типа могут преобразовываться в данные другого типа. Такое преобразование может быть явным или неявным. При явном преобразовании типов используются вызовы специальных функций преобразования, аргументы которых принадлежат одному типу, а значение - другому. Таковыми являются уже рассмотренные функции ORD, TRUNC, ROUND, CHR. В гл. 6 описывается функция PTR, преобразующая четырехбайтный целочисленный аргумент к типу-указателю. В Турбо Паскале может использоваться и более общий механизм преобразования типов, согласно которому преобразование достигается применением идентификатора имени) стандартного типа или типа, определенного пользователем, как идентификатора функции преобразования к выражению преобразуемого типа (так называемое автоопределенное преобразование типов). Например, допустимы следующие вызовы функций: type МуТуре = (а, Ь, с, d); ..... МуТуре (2) Integer ('D') pointer (longint(a)+ $FF) Char (127 mod c) Byte (k) При автоопределенном преобразовании типа выражения может произойти изменение длины его внутреннего представления (длина может увеличиться или уменьшиться). В Турбо Паскале определен еще один явный способ преобразования данных: в ту область памяти, которую занимает переменная некоторого типа, можно поместить значение выражения другого типа, если только длина внутреннего представления вновь размещаемого значения в точности равна длине внутреннего представления переменной. С этой целью вновь используется автоопределенная функция преобразования типов, но уже в левой части оператора присваивания:
type byt = array [1..2] of Byte; int = array [1..2] of Integer; rec = record x, у: Integer end; var vbyt: byt; vint: int; vrec: rec; begin byt(vint[1])[2]:= 0; int(vrec)[1]:= 256 end. Неявное преобразование типов возможно только в двух случаях: · в выражениях, составленных из вещественных и целочисленных переменных, последние автоматически преобразуются к вещественному типу, и все выражение в целом приобретает вещественный тип; · одна и та же область памяти попеременно трактуется как содержащая данные то одного, то другого типа (совмещение в памяти данных разного типа). Совмещение данных в памяти может произойти при использовании записей с вариантными полями (см. 4.2.2), типизированных указателей, содержащих одинаковый адрес (см. гл. 6), а также при явном размещении данных разного типа по одному и тому же абсолютному адресу. Для размещения переменной по нужному абсолютному адресу она описывается с последующей стандартной директивой ABSOLUTE, за которой помещается либо абсолютный адрес, либо идентификатор ранее определенной переменной. Абсолютный адрес указывается парой чисел типа WORD, разделенных двоеточием; первое число трактуется как сегмент, второе - как смещение адреса (см. гл. 6). Например: b: Byte absolute $0000:$0055; w: Longlnt absolute 128:0; Если за словом ABSOLUTE указан идентификатор ранее определенной переменной, то происходит совмещение в памяти данных разного типа, причем первые байты внутреннего представления этих данных будут располагаться по одному и тому же абсолютному адресу, например: var х: Real; у: array [1..3] of Integer absolute x; В этом примере переменные X и Y будут размещены, начиная с одного и того же абсолютного адреса. Таким образом, одну и ту же область памяти длиной 6 байт, а следовательно, и размещенные в этой области данные теперь можно рассматривать как данные либо типа REAL, либо как массив из трех данных типа INTEGER. Например, следующая программа выдаст на экран содержимое первых двух байт внутреннего представления вещественного числа п = 3.1415 в виде целого числа:
var х: Real; у: array[1..3] of Integer absolute x; begin х:= pi; WriteLn(y[1]) end. На экран будет выдан результат 8578. Неявные преобразования типов могут служить источником трудно обнаруживаемых ошибок в программе, поэтому везде, где это возможно, следует избегать их. · Глава 5. ФАЙЛЫ o 5.1. Доступ к файлам § 5.1.1. Имена файлов § 5.1.2. Логические устройства § 5.1.3. Инициация файла o 5.2. Процедуры и функции для работы с файлами o 5.3. Текстовые файлы o 5.4. Типизированные файлы o 5.5. Нетипизированные файлы Глава 5 ФАЙЛЫ Под файлом понимается либо именованная область внешней памяти ПК (жесткого диска, гибкой дискеты, электронного «виртуального» диска), либо логическое устройство - потенциальный источник или приемник информации. Любой файл имеет три характерные особенности. Во-первых, у него есть имя, что лает возможность программе работать одновременно с несколькими файлами. Во-вторых, он содержит компоненты одного типа. Типом компонентов может быть любой тип Турбо Паскаля, кроме файлов. Иными словами, нельзя создать «файл файлов». В-третьих, длина вновь создаваемого файла никак не оговаривается при его объявлении и ограничивается только емкостью устройств внешней памяти. Файловый тип или переменную файлового типа можно задать одним из трех способов: <имя> = FILE OF <тип>; <имя> = TEXT; <имя> = FILE; Здесь <имя> - имя файлового типа (правильный идентификатор); FILE, OF - зарезервированные слова (файл, из); TEXT - имя стандартного типа текстовых файлов; <тип> - любой тип Турбо Паскаля, кроме файлов. Например: type product = record name: String; code: Word; cost: comp end; textSO = file of String [80]; var fl: file of char; f2: text; f3: file; f4: text80; f5: file of product; В зависимости от способа объявления можно выделить три вида файлов: · типизированные файлы (задаются предложением FILE OF...); · текстовые файлы (определяются типом TEXT); · нетипизированные файлы (определяются типом FILE). В наших примерах F1, F4 и F5- типизированные файлы, F2 - текстовый файл, F3 -нетипизированный файл. Вид файла, вообще говоря, определяет способ хранения информации в файле. Однако в Турбо Паскале нет средств контроля вида ранее созданных файлов. При объявлении уже существующих файлов программист должен сам следить за соответствием вида объявления характеру файла.
ДОСТУП К ФАЙЛАМ Любой программе доступны два предварительно объявленных файла со стандартными файловыми переменными: INPUT - для чтения данных с клавиатуры и OUTPUT - для вывода на экран. Стандартный Паскаль требует обязательного упоминания этих файлов в заголовке программы, например, так: PROGRAM NameOfProgram(input,output); В Турбо Паскале это необязательно, вот почему заголовок программы можно опускать. Любые другие файлы, а также логические устройства становятся доступны программе только после выполнения особой процедуры открытия файла (логического устройства). Эта процедура заключается в связывании ранее объявленной файловой переменной с именем существующего или вновь создаваемого файла, а также в указании направления обмена информацией: чтение из файла или запись в него. Файловая переменная связывается с именем файла в результате обращения к стандартной процедуре ASSIGN: ASSIGN (<ф.п.>, <имя файла или л.у.>);. Здесь <ф.п.> - файловая переменная (правильный идентификатор, объявленный в программе как переменная файлового типа); <имя файла или л.у.> - текстовое выражение, содержащее имя файла или логическое устройство. Если имя файла задается в виде пустой строки, например, ASSIGN(f, ' '), то в зависимости от направления обмена данными файловая переменная связывается со стандартным файлом INPUT или OUTPUT. 5.1.1. Имена файлов Имя файла - это любое выражение строкового типа, которое строится по правилам определения имен в MS-DOS (операционной системе ПК): · имя содержит до восьми разрешенных символов; разрешенные символы - это прописные и строчные латинские буквы, цифры, и символы: ! @ # $ % ^ & () ' ~ - _ · имя начинается с любого разрешенного символа; · за именем может следовать расширение - последовательность до трех разрешенных символов; расширение, если оно есть, отделяется от имени точкой. Перед именем может указываться так называемый путь к файлу: имя диска и/или имя текущего каталога и имена каталогов вышестоящих уровней. Имя диска - это один из символов A...Z, после которого ставится двоеточие. Имена А: и В: относятся к дисковым накопителям на гибких дискетах, имена С:, D: и т.д. - к жестким дискам. Эти имена могут относиться также к одному или нескольким виртуальным дискам, созданным в оперативной памяти ПК специальной командой VDISK в ходе выполнения файла автоустановки CONFIG.SYS дисковой операционной системы. Если имя диска не указано, подразумевается устройство по умолчанию - то, которое было установлено в операционной системе перед началом работы программы.
За именем диска может указываться имя каталога, содержащего файл. Если имени каталога предшествует обратная косая черта, то путь к файлу начинается из корневого каталога, если черты нет - из текущего каталога, установленного в системе по умолчанию. За именем каталога может следовать одно или несколько имен каталогов нижнего уровня. Каждому из них должна предшествовать обратная косая черта. Весь путь к файлу отделяется от имени файла обратной косой чертой. Максимальная длина имени вместе с путем - 79 символов, например: var finp: text; fout:file of String; const name = 'c:\dir\subdir\out.txt'; begin assign(finp,'123.dat'); assign(fout,name); end. 5.1.2. Логические устройства Стандартные аппаратные средства ПК, такие как клавиатура, экран дисплея, печатающее устройство (принтер) и коммуникационные каналы ввода-вывода, определяются в Турбо Паскале специальными именами, которые называются логическими устройствами. Все они в Турбо Паскале рассматриваются как потенциальные источники или приемники текстовой информации. CON - логическое имя, которое определяет консоль - клавиатуру или экран дисплея. Турбо Паскаль устанавливает различие между этими физическими устройствами по направлению передачи данных: чтение данных возможно только с клавиатуры, а запись - только на экран. Таким образом, с помощью логического устройства CON нельзя, например, прочитать данные с экрана ПК, хотя такая аппаратная возможность существует. Ввод с клавиатуры буферируется: символы по мере нажатия на клавиши помещаются в специальный строковый буфер, который передается программе только после нажатия на клавишу Enter. Буферизация ввода обеспечивает возможность редактирования вводимой строки стандартными средствами ДОС. При вводе символов осуществляется их эхо-повтор на экране ПК. В Турбо Паскале можно прочитать любой символ клавиатуры, в том числе и символ CR, вырабатываемый клавишей Enter, сразу после нажатия на соответствующую клавишу без эхо-повтора. PRN - логическое имя принтера. Если к ПК подключено несколько принтеров, доступ к ним осуществляется по логическим именам LPT1, LPT2 и LPT3. Имена PRN и LPT1 первоначально - синонимы. Средствами ДОС можно присвоить имя PRN любому другому логическому устройству, способному принимать информацию. Стандартный библиотечный модуль PRINTER, входящий в библиотеку TURBO.TPL, объявляет имя файловой переменной LST и связывает его с логическим устройством LPT1. Это дает возможность использовать простое обращение к принтеру. Например, программа Uses Printer; begin WriteLn(LST, 'Привет, мир!') end. выведет на принтер фразу «Привет, мир!», а все необходимые операции по открытию логического устройства выполнит библиотечный блок PRINTER (подробности работы с модулями см. в гл. 9). AUX - логическое имя коммуникационного канала, который обычно используется для связи ПК с другими машинами. Коммуникационный канал может осуществлять и прием, и передачу данных, однако в программе в каждый момент времени ему можно назначить только одну из этих функций. Как правило, в составе ПК имеются два коммуникационных канала, которым даются имена логических устройств СОМ1 и COM2. Первоначально имена AUX и СОМ1 - синонимы. NUL - логическое имя «пустого» устройства. Это устройство чаще всего используется в отладочном режиме и трактуется как устройство-приемник информации неограниченной емкости. При обращении к NUL как источнику информации выдается признак конца файла EOF. Связывание логического устройства с файловой переменной осуществляется процедурой ASSIGN, например: var fi,fo: text; begin assign(fi,'AUX'); assign(fо,'LPT2'); end. Турбо Паскаль никогда не связывает имена логических устройств с дисковыми файлами, в этом смысле эти имена можно считать зарезервированными. Иными словами, нельзя, например, обратиться к дисковому файлу с именем PRN, так как Турбо Паскаль всегда интерпретирует такой запрос как обращение к принтеру. 5.1.3. Инициация файла Инициировать файл означает указать для этого файла направление передачи данных. В Турбо Паскале можно открыть файл для чтения, для записи информации, а также для чтения и записи одновременно. Для чтения файл инициируется с помощью стандартной процедуры RESET: RESET (<ф.п.>); Здесь <ф.п.> - файловая переменная, связанная ранее процедурой ASSIGN с уже существующим файлом или логическим устройством-приемником информации. При выполнении этой процедуры дисковый файл или логическое устройство подготавливается к чтению информации. В результате специальная переменная-указатель, связанная с этим файлом, будет указывать на начало файла, т.е. на компонент с порядковым номером 0. Если делается попытка инициировать чтение из несуществующего файла или из логического устройства PRN, возникает ошибка периода исполнения, которая может быть сообщена программе ненулевым значением встроенной функции IORESULT типа WORD. Например, следующий фрагмент программы позволяет установить, существует ли требуемый файл на диске: var f: file of char; begin assign(f,'myfile.dat'); {$I-} {Отключаем контроль ошибок ввода-вывода} reset(f); {$I+} {Включаем контроль ошибок ввода-вывода} if IOResult <> 0 then ..... {Файл не существует} else ..... {Файл существует} end. В этом фрагменте с помощью директивы компилятора {$I-} отключается автоматический контроль ошибок ввода-вывода. Если этого не сделать, то отсутствие файла приведет к аварийному завершению программы. В Турбо Паскале разрешается обращаться к типизированным файлам, открытым процедурой RESET (т.е. для чтения информации), с помощью процедуры WRITE (т.е. для записи информации). Такая возможность позволяет легко обновлять ранее созданные типизированные файлы и при необходимости расширять их. Для текстовых файлов, открытых процедурой RESET, нельзя использовать процедуру WRITE или WRITELN. Стандартная процедура REWRITE (<ф.п.>). инициирует запись информации в файл или в логическое устройство, связанное ранее с файловой переменной <ф.п.>. Процедурой REWRITE нельзя инициировать запись информации в ранее существовавший дисковый файл: при выполнении этой процедуры старый файл уничтожается и никаких сообщений об этом в программу не передается. Новый файл подготавливается к приему информации и его указатель принимает значение 0. Стандартная процедура APPEND (<ф.п.>) инициирует запись в ранее существовавший текстовый файл для его расширения, при этом указатель файла устанавливается в его конец. Процедура APPEND применима только к текстовым файлам, т.е. их файловая переменная должна иметь тип TEXT (см. выше). Процедурой APPEND нельзя инициировать запись в типизированный или нетипизированный файл. Если текстовый файл ранее уже был открыт с помощью RESET или REWRITE, использование процедуры APPEND приведет к закрытию этого файла и открытию его вновь, но уже для добавления записей.
Читайте также: А. типової клінічної картини Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|