Немного о программировании |
Программирование |
Программи́рование — процесс создания компьютерных программ. По известному выражению Никлауса Вирта «Программы = алгоритмы + структуры данных»; иными словами, ключевыми непосредственными задачами программирования являются создание и использование алгоритмов и структур данных. В более широком смысле под программированием понимают весь спектр деятельности, связанный с созданием и поддержанием в рабочем состоянии программ — программного обеспечения. Эта инженерно-техническая дисциплина называется «программная инженерия». Сюда входят анализ и постановка задачи, проектирование программы, построение алгоритмов, разработка структур данных, написание текстов программ, отладка и тестирование программы (испытания программы), документирование, настройка (конфигурирование), доработка и сопровождение. Программирование основывается на использовании языков программирования, на которых записываются инструкции для компьютера. Современное приложение содержит множество таких инструкций, связанных между собой. Текстовый редактор среды программирования может иметь специфичную функциональность, такую, как индексация имен, отображение документации, подсветка синтаксиса, средства визуального создания пользовательского интерфейса (GUI/UI). С помощью текстового редактора программист производит набор и редактирование текста создаваемой программы, который называют исходным кодом. Язык программирования определяет синтаксис и изначальную семантику исходного кода. В настоящее время активно используются интегрированные среды разработки, включающие в свой состав также редактор для ввода и редактирования текстов программ, отладчики (т. н. дебаггеры) для поиска и устранения ошибок, трансляторы с различных языков программирования, компоновщики для сборки программы из нескольких модулей и другие служебные модули. Антикитерский механизм из Древней Греции был калькулятором, использовавшим шестерни различных размеров и конфигурации, обусловливавших его работу, по отслеживанию метонова цикла, до сих пор использующегося в лунно-солнечных календарях.Аль-Джазари построил программируемый автомат-гуманоид в 1206 году. Одна система, задействованная в этих устройствах, использовала зажимы и кулачки, помещённые в деревянный ящик в определённых местах, которые последовательно задействовали рычаги, которые, в свою очередь, управляли ударными инструментами. Часто первым программируемым устройством принято считать жаккардовый ткацкий станок, построенный в 1804 году Жозефом Мари Жаккаром, который произвёл революцию в ткацкой промышленности, предоставив возможность программировать узоры на тканях при помощи перфокарт. Первое программируемое вычислительное устройство, Аналитическую машину, разработал Чарлз Бэббидж (но не смог её построить). 19 июля 1843 года графиня Ада Августа Лавлейс, дочь великого английского поэта Джорджа Байрона, как принято считать, написала первую в истории человечества программу для Аналитической машины. Эта программа решала уравнение Бернулли, выражающее закон сохранения энергии движущейся жидкости. В своей первой и единственной научной работе Ада Лавлейс рассмотрела большое число вопросов. Ряд высказанных ею общих положений (принцип экономии рабочих ячеек памяти, связь рекуррентных формул с циклическими процессами вычислений) сохранили свое принципиальное значение и для современного программирования. В материалах Бэббиджа и комментариях Лавлейс намечены такие понятия, как подпрограмма и библиотека подпрограмм, модификация команд и индексный регистр, которые стали употребляться только в 1950-х годах. Однако ни одна из программ, написанных Адой Лавлейс, никогда так и не была запущена Большая часть работы программистов связана с написанием исходного кода, тестированием и отладкой программ на одном из языков программирования. Исходные тексты и исполняемые файлы программ являются объектами авторского права и являются интеллектуальной собственностью их авторов и правообладателей. Различные языки программирования поддерживают различные стили программирования (парадигмы программирования). Отчасти искусство программирования состоит в том, чтобы выбрать язык программирования, наиболее полно подходящий для решения поставленной задачи. Разные языки требуют от программиста различного уровня внимания к деталям при реализации алгоритма, результатом чего часто бывает компромисс между простотой и производительностью (или междувременем программиста и временем пользователя). Единственный язык, напрямую выполняемый ЭВМ — это машинный язык (также называемый машинным кодом и языком машинных команд). Изначально все программы писались в машинном коде, но сейчас этого практически уже не делается. Вместо этого программисты пишут исходный код на том или ином языке программирования, затем, используя компилятор, транслируют его в один или несколько этапов в машинный код, готовый к исполнению на целевом процессоре, или в промежуточное представление, которое может быть исполнено специальным интерпретатором — виртуальной машиной. Но это справедливо только для языков высокого уровня. Если требуется полный низкоуровневый контроль над системой на уровне машинных команд и отдельных ячеек памяти, программы пишут на языке ассемблера, мнемонические инструкции которого преобразуются один к одному в соответствующие инструкции машинного языка целевого процессора ЭВМ (по этой причине трансляторы с языков ассемблера получаются алгоритмически простейшими трансляторами). В некоторых языках вместо машинного кода генерируется интерпретируемый двоичный код «виртуальной машины», также называемый байт-кодом (byte-code). Такой подход применяется в Forth, некоторых реализациях Lisp, Java, Perl, Python, языках для .NET Framework. Первое знакомство с ПаскалемСтруктура программы на Паскале. По определению стандартного Паскаля программа состоит из заголовка программы и тела программы (блока), за которым следует точка — признак конца программы. В свою очередь, блок содержит разделы описаний и раздел операторов. ![]()
Раздел операторов имеется в любой программе и является основным. Предшествующие разделы носят характер описаний и не все обязательно присутствуют в каждой программе. В Турбо Паскале, в отличие от стандарта, возможно следующее: • отсутствие заголовка программы; • разделы Const, Type, Var, Label могут следовать друг за другом в любом порядке и встречаться в разделе описаний сколько угодно раз. Примеры программ. Уже было сказано, что Паскаль разрабатывался Н. Виртом как учебный язык. Основной принцип, заложенный в нем, — это поддержка структурной методики программирования. Этот же принцип лежит в основе псевдокода, который мы здесь называем Алгоритмическим языком (АЯ). По сути дела, расхождение между АЯ и Паскалем заключается в следующем: АЯ — русскоязычный, Паскаль — англоязычный; синтаксис Паскаля определен строго и однозначно в отличие от сравнительно свободного синтаксиса АЯ. Запись программы на Паскале похожа на английский перевод алгоритма, записанного на Алгоритмическом языке. Сравните алгоритм деления простых дробей, записанный на АЯ, с соответствующей программой на Паскале. ![]() Здесь использовано следующее равенство: ![]() Даже не заглядывая в учебник по Паскалю, в данной программе можно все понять. Для этого достаточно знать английский язык. Заголовок программы начинается со слова Program (программа), за которым следует произвольное имя, придуманное программистом (division — деление). Раздел описания переменных начинается со слова Var (variables — переменные), за которым следует список переменных. Тип указывается после двоеточия словом Integer — целый. Начало и конец раздела операторов программы отмечаются словами Begin (начало) и End (конец). В конце программы обязательно ставится точка. Ввод исходных данных с клавиатуры производится с помощью процедуры ReadLn (read line — читать строку). На клавиатуре набирают четыре числа, отделяемые друг от друга пробелами, которые отражаются строкой на экране дисплея. После набора чисел нажимают на клавишу ввода. Операторы присваивания в Паскале записываются так же, как в АЯ. Знак умножения — * (звездочка). Вывод результатов на экран дисплея производится с помощью процедуры WriteLn (write line — писать в строку). В рассмотренном примере два целых числа т и п выведутся в строчку, курсор на экране перейдет в начало следующей свободной строки и работа программы завершится. Необходимо строгое соблюдение правил правописания (синтаксиса) программы. В частности, в Паскале однозначно определено назначение знаков пунктуации. Точка с запятой (;) ставится в конце заголовка программы, в конце раздела описания переменных, после каждого оператора. Перед словом End точку с запятой можно не ставить. Запятая (,) является разделителем элементов во всевозможных списках: списке переменных в разделе описания, списке вводимых и выводимых величин. Строгий синтаксис в языке программирования необходим прежде всего для транслятора. Транслятор — это программа, которая исполняется формально. Если, допустим, разделителем в списке переменных должна быть запятая, то любой другой знак будет восприниматься как ошибка. Если точка с запятой является разделителем операторов, то транслятор в качестве оператора воспринимает всю часть текста программы от одной точки с запятой до другой. Если вы забыли поставить этот знак между какими-то двумя операторами, то транслятор будет принимать их за один, что неизбежно приведет к ошибке. Основное назначение синтаксических правил — придать однозначный смысл языковым конструкциям. Если какая-то конструкция может трактоваться двусмысленно, значит, в ней обязательно содержится ошибка. Лучше не полагаться на интуицию, а выучить правила языка. В дальнейшем мы строго опишем синтаксические правила Паскаля, а пока для получения первоначального представления о языке обратимся еще к нескольким примерам программирования несложных алгоритмов. «Оттранслируем» алгоритм вычисления факториала натурального числа (N!) на Паскале. ![]() Из этого примера, во-первых, видно, как записывается на Паскале оператор цикла с предусловием (цикл-пока): While <условие выполнения> Do <тело цикла> (While — пока, Do — делать). Если тело цикла содержит последовательность операторов, то говорят, что оно образует составной оператор, в начале и в конце которого надо писать Begin и End Служебные слова Begin и End часто называют операторными скобками, которые объединяют несколько операторов в один составной. Если же тело цикла — один оператор (не составной), то операторных скобок не требуется. Тогда транслятор считает, что тело цикла заканчивается на ближайшем знаке «;». Во-вторых, из примера видно, что в Паскале нет специальных слов для обозначения начала цикла (нц) и конца цикла (кц). На все случаи есть универсальные слова Begin и End. Рассмотрим еще один пример программы — решение квадратного уравнения. ![]() В этой программе по сравнению с предыдущими появилось много новых элементов. Имя вещественного типа в Паскале — real. Цикл с постусловием (цикл-до) программируется оператором Repeat <тело цикла> Until <условие окончания> (здесь Repeat — повторять, Until — до). Тело цикла может быть как одиночным, так и составным оператором, однако употребления Begin и End не требуется, поскольку сами слова Repeat и Until выполняют роль операторных скобок. Знак не равно в Паскале пишется так: <>, знак больше или равно: >=. Правила записи арифметических выражений мы подробно рассмотрим немного позже. В формулах вычисления корней используется стандартная функция квадратного корня ( ), которая в Паскале записывается так: sqrt (x). Порядок выполнения операций в выражении определяется скобками и старшинством операций. Старшинство операций такое же, как и в алгебре. Операции одинакового старшинства выполняются в порядке их записи (слева направо). Ветвление в Паскале программируется с помощью условного оператора, который имеет следующую форму: If <условие> Then <оператор 1> Else «oператор 2> (здесь If — если, Then — то, Else — иначе). Операторы 1 и 2 могут быть как простыми, так и составными. Составной оператор следует заключать в операторные скобки Begin и End. Так же, как и в Алгоритмическом языке, возможно использование неполной формы условного оператора: if <условие> then <оператор> Характерной чертой данной программы является использование в тексте комментариев. Комментарий — это любая последовательность символов, заключенных в фигурные скобки {...}. Можно употреблять также следующие ограничители комментариев (*...*). Комментарий не определяет никаких действий программы и является лишь пояснительным текстом. Он может присутствовать в любом месте программы, где можно поставить пробел Программист пишет комментарии не для компьютера, а для себя. Комментарий придает тексту программы большую ясность. Хорошо откомментированные программы называют самодокументированными. Во многих подобных программах объем комментариев превышает объем вычислительных операторов. Удачное использование комментариев — признак хорошего стиля программирования. Чтобы выполнить программу на ЭВМ, ее нужно ввести в память, оттранслировать и исполнить. Для того чтобы проделать всю эту работу, на компьютере должны быть специальные средства программного обеспечения. На ПК они составляют систему Турбо Паскаль. Упражнения «Оттранслируйте» с Алгоритмического языка на Паскаль следующие алгоритмы: а) алгоритм Евклида; б) алгоритм выбора наибольшего значения из трех; в) алгоритм определения существования треугольника с данными длинами сторон; г) алгоритм умножения двух целых чисел с использованием только операций сложения и вычитания; д) алгоритм вычисления частного и остатка от целочисленного деления. Элементы языка Турбо ПаскальАлфавит. Алфавит языка состоит из множества символов, включающих в себя буквы, цифры и специальные символы. Латинские буквы: от A до Z (прописные) и от а до z. (строчные). Цифры: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Шестнадцатеричные цифры: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, А, В, С, D, E, F. Специальные символы: + — * / = < > [ ] . , ( ) : ; { } ^ @ $ #. Следующие комбинации специальных символов являются едиными символами (их нельзя разделять пробелами): : = знак присваивания; < = меньше или равно; > = больше или равно; (* *) ограничители комментариев < > не равно; (используются наряду с {}); (..) эквивалент [ ]. Пробелы — символ пробела (ASCI1-32) и все управляющие символы кода ASCII (от 0 до 31). К спецсимволам относятся служебные слова, смысл которых определен однозначно. Служебные слова не могут быть использованы для других целей. С точки зрения языка это единые символы. Вот список служебных слов Турбо Паскаля: ![]() Последние версии языка содержат еще ряд служебных слов, относящихся к работе с объектами и встроенным ассемблером. Идентификаторы. Идентификатором называется символическое имя определенного программного объекта. Такими объектами являются имена констант, переменных, типов данных, процедур и функций, программ. С помощью синтаксической диаграммы идентификатор можно определить, как показано на рис. 8. ![]() Расшифровать это можно так: идентификатор — это любая последовательность букв и цифр, начинающаяся с буквы. В Турбо Паскале к буквам приравнивается также знак подчеркивания. Строчные и прописные буквы в идентификаторах и служебных словах не различаются. Например: max, MAX, MaX и mAx — одно и то же имя. Длина идентификатора может быть произвольной, но значащими являются только первые 63 символа. Комментарии. Следующие конструкции представляют собой комментарии и поэтому игнорируются компилятором: (любой текст, не содержащий символ «}» } (* любой текст, не содержащий символы «*)»*) Буквы русского алфавита употребляются только в комментариях, в литерных и текстовых константах. Строка, начинающаяся с символов {$ или (*$, является директивой компилятора. За этими символами следует мнемоника команды компилятора. Типы данныхКонцепция типов данных является одной из центральных в любом языке программирования. С типом величины связаны три ее свойства: форма внутреннего представления, множество принимаемых значений и множество допустимых операций. Турбо Паскаль характеризуется большим разнообразием типов данных, отраженном на рис. 9. ![]() В стандартном Паскале отсутствует строковый тип. Кроме того, в Турбо Паскале целые и вещественные — это группы типов. В старших версиях Турбо Паскаля существует процедурный тип и тип объект. Каждый тип имеет свой идентификатор. В табл. 3.1 представлена информация о простых типах данных, определенных в Турбо Паскале. Для вещественных типов в скобках указано количество сохраняемых значащих цифр мантиссы в десятичном представлении числа. Таблица 3.1 ![]() В стандарте Паскаля из вещественных типов определен только тип Real; из целых типов — Integer. Типы Single, Double, Extended употребляются в Паскаль-программах только в том случае, если ПК снабжен сопроцессором «плавающей арифметики» (для процессоров IBM PC, начиная с Intel-80486 и старше, это условие всегда выполняется). Тип данных называется порядковым, если он состоит из счетного количества значений, которые можно пронумеровать. Отсюда следует, что на этом множестве значений существуют понятия «следующий» и «предыдущий». Описание переменных. Для всех переменных величин, используемых в программе, должны быть указаны их типы. Это делается в разделе переменных программы. Структура раздела переменных показана на рис. 10. ![]() Пример раздела переменных программы: Var m,n,k: Integer; х,у,z: Real; Symbol: Char; Константы. Тип константы определяется по контексту, т.е. по форме ее записи в программе. Целые десятичные константы записываются в обычной форме целого числа со знаком или без знака, например 25, -24712, 376. Целые шестнадцатеричные константы записываются с префиксом $. Они должны находиться в диапазоне от $00000000 до $FFFFFFFF. Вещественные константы с фиксированной точкой записываются в обычной форме десятичного числа с дробной частью. Разделитель целой и дробной части — точка, например: 56.346, 0.000055, -345678.0. Вещественные константы с плавающей точкой имеют форму: <мантисса>Е<порядок> Здесь мантисса — целое или вещественное число с фиксированной точкой, порядок — целое число со знаком или без, например 7Е-2 (7∙10-2), 12.25Е6 (12,25∙106), 1Е-25 (10-25). Символьная константа — любой символ алфавита, заключенный в апострофы, например, 'W, '!', '9'. Логическая константа — одно из двух слов: true, false. Строковая константа — строка символов, заключенная в апострофы, например Turbo Pascal', 'Ответ:', '35-45-79'. Максимальная длина — 255 символов. Константе может быть поставлено в соответствие определенное имя. Назначение имени константе производится в разделе констант программы. Структура раздела констант показана на рис. 11. ![]() Пример: ![]() В дополнение к сказанному заметим, что в Турбо Паскале допустимо употребление типизированных констант. Типизированная константа аналогична переменной, которой задается начальное значение. Причем происходит это на этапе компиляции. Описание типизированной константы приведено на рис. 12. ![]() Пример: ![]() В Турбо Паскале имеется ряд имен, зарезервированных за определенными значениями констант. Ими можно пользоваться без предварительного определения в программе (табл. 3.2). Таблица 3.2 ![]() Типы пользователя. Один из принципиальных моментов состоит в том, что пользователю разрешается определять свои типы данных. Типы пользователя всегда базируются на стандартных типах данных Паскаля. Для описания типов пользователя в Паскале существует раздел типов, структура которого представлена на рис. 13. ![]() Перечисляемый тип (рис. 14) задается непосредственно перечислением всех значений, которые может принимать переменная данного типа. ![]() Определенное имя типа затем используется для описания переменных. Например: ![]()
![]() Здесь Gaz и Metal — имена перечисляемых типов, которые ставятся в соответствие переменным Gl, G2, G3 и Metl, Met2. Переменной Day назначается перечисляемый тип, которому не присвоено имя. Значения, входящие в перечисляемый тип, являются константами. Действия над ними подчиняются правилам, применимым к константам. Каждое значение в перечисляемом типе занимает в памяти 2 байта. Поэтому число элементов не должно превышать 65535. Перечисляемый тип — упорядоченное множество. Его элементы пронумерованы начиная от 0 в порядке следования в описании. В программе, в которой присутствует данное выше описание, возможен такой фрагмент: ![]() Интервальный тип (рис. 15) задается как упорядоченное ограниченное подмножество некоторого порядкового типа. ![]() Порядковый номер первой константы не должен превышать номера второй константы в соответствующем базовом типе. При исполнении программы автоматически контролируется принадлежность значений переменной интервального типа установленному диапазону. При выходе из диапазона исполнение программы прерывается. Пример: ![]() Арифметические операции, функции, выражения.Арифметический оператор присваивания
К арифметическим типам данных относятся группы вещественных и целых типов. К ним применимы арифметические операции и операции отношений. Операции над данными бывают унарными (применимые к одному операнду) и бинарными (применимые к двум операндам). Унарная арифметическая операция одна. Это операция изменения знака. Ее формат: ![]() Бинарные арифметические операции стандартного Паскаля описаны в табл. 3.3. В ней I обозначает целые типы, R — вещественные типы. Таблица 3.3 ![]() К арифметическим величинам могут быть применены стандартные функции Паскаля. Структура обращения к функции представлена на рис. 16. ![]()
Функция выступает как операнд в выражении. Например, в следующем операторе присваивания
![]() операндами являются три функции: sin, ln, cos. Их запись такая же, как в математике. Аргументы называются фактическими параметрами и являются в общем случае выражениями арифметического типа. Аргументы записываются в круглых скобках. Результат вычисления функции — величина соответствующего типа. Табл. 3.4 содержит описания математических стандартных функций Турбо Паскаля. Таблица 3.4 ![]() Арифметическое выражение задает порядок выполнения действий над числовыми величинами. Арифметические выражения содержат арифметические операции, функции, операнды, круглые скобки. Одна константа или одна переменная — простейшая форма арифметического выражения. Например, запишем по правилам Паскаля следующее математическое выражение: ![]() На Паскале это выглядит так: ![]() Для того чтобы правильно записывать арифметические выражения, нужно соблюдать следующие правила: 1. Все символы пишутся в строчку на одном уровне. Проставляются все знаки операций (нельзя пропускать знак умножения). 2. Не допускаются два следующих подряд знака операций (нельзя A+-B; можно А+(-B)). 3. Операции с более высоким приоритетом выполняются раньше операций с меньшим приоритетом. Порядок убывания приоритетов: • вычисление функции; • унарная операция смены знака (-); • *, /, div, mod; • +, -. 4. Несколько записанных подряд операций одинакового приоритета выполняются последовательно слева направо. 5. Часть выражения, заключенная в скобки, вычисляется в первую очередь. (Например, (A+B) * (C—D) — умножение производится после сложения и вычитания.) ![]() Не следует записывать выражений, не имеющих математического смысла. Например, деление на нуль, логарифм отрицательного числа и т. п. Пример. Цифрами сверху указан порядок выполнения операций:
![]()
Данное арифметическое выражение соответствует следующей математической формуле: ![]() В Паскале нет операции или стандартной функции возведения числа в произвольную степень. Для вычисления xy рекомендуется поступать следующим образом: • если у — целое значение, то степень вычисляется через умножение; например, х3 → х ∙ х ∙ х; большие степени следует вычислять умножением в цикле; • если у — вещественное значение, то используется следующая математическая формула: хy = eyln(x). На Паскале это будет выглядеть так: ![]() Очевидно, что при вещественном у не допускается нулевое или отрицательное значение х. Для целого у такого ограничения нет. Например, ![]() На Паскале это будет так: ![]() Выражение имеет целый тип, если в результате его вычисления получается величина целого типа. Выражение имеет вещественный тип, если результатом его вычисления является вещественная величина. Арифметический оператор присваивания имеет структуру, представленную на рис. 17. ![]() Например: ![]() Порядок выполнения оператора присваивания нами уже рассматривался. Следует обратить особое внимание на следующее правило: типы переменной и выражения должны быть одинаковыми. Исключение составляет случай, когда выражение имеет целый тип, а переменная — вещественный. Упражнения 1. Для следующих формул записать соответствующие арифметические выражения на Паскале: ![]() ![]() 2. Записать математические формулы, соответствующие следующим выражениям на Паскале: ![]() 3. Почему в Паскале аргумент функции всегда записывают в скобках (например, пишут ln(5), а не ln5)? 4. Для следующих формул записать соответствующие арифметические выражения на Паскале: ![]() 5. Вычислить значения выражений: ![]() 6. Определить тип выражения: ![]() 7. Если у — вещественная переменная, а п — целая, то какие из следующих операторов присваивания правильные, а какие нет: ![]() 8. Поменять местами значения целых переменных х и у, не используя дополнительные переменные. Найдя такой алгоритм, определить, в чем его недостаток по сравнению с методом обмена через третью переменную. Можно ли его применять для вещественных чисел? 9. Присвоить целой переменной h значение цифры, стоящей в разряде сотен в записи положительного целого числа k (например, если k = 28796, то h = 7). 10. Целой переменной S присвоить значение суммы цифр трехзначного целого числа k. 11. Какую задачу решает следующая программа? ![]() Можно ли того же самого результата достичь более простым способом? Ввод с клавиатуры и вывод на экранВвод данных — это передача информации от внешних устройств в оперативную память. Вводятся, как правило, исходные данные решаемой задачи. Вывод — обратный процесс, когда данные передаются из оперативной памяти на внешние носители (принтер, дисплей, магнитные устройства и т.д.). Результаты решения всякой задачи должны быть выведены на один из этих носителей. Основными устройствами ввода-вывода у персонального компьютера являются клавиатура и дисплей (экран монитора). Именно через эти устройства главным образом осуществляется диалог между человеком и ПК. Процедура ввода с клавиатуры имеет следующий формат: Read(<cписок ввода>) где <список ввода> — это последовательность имен переменных, разделенных запятыми. Слово read переводится как читать. (Точнее говоря, Read — это оператор обращения к стандартной процедуре ввода.) Например, ![]() При выполнении этого оператора происходит прерывание работы компьютера, после чего пользователь должен набрать на клавиатуре значения переменных а, b, с, d, отделяя их друг от друга пробелами. При этом вводимые значения высвечиваются на экране. В конце нажимают клавишу Enter. Значения должны вводиться в строгом соответствии с синтаксисом Паскаля. Пример: ![]() Набираем на клавиатуре: ![]() Если в программе имеется несколько операторов Read, то данные для них вводятся потоком, т. е. после считывания значений переменных для одного оператора Read данные для следующего оператора читаются из той же строки на экране, что и для предыдущего до окончания строки, затем происходит переход на следующую строку. Пример: ![]() Набираем на клавиатуре: ![]() Другой вариант оператора ввода с клавиатуры имеет вид: ![]() Здесь слово ReadLn означает read line — читать строку. Этот оператор отличается от Read только тем, что после считывания последнего в списке значения для одного оператора ReadLn данные для следующего оператора будут считываться с начала новой строки. Если в предыдущем примере заменить операторы Read на ReadLn: ![]() то ввод значений будет происходить из двух строк: ![]() Оператор вывода на экран (обращение к стандартной процедуре вывода) имеет следующий формат: ![]() Здесь элементами списка вывода могут быть выражения различных типов (в частности, константы и переменные). Пример: ![]() При выводе на экран нескольких чисел в строку они не отделяются друг от друга пробелами Программист сам должен позаботиться о таком разделении. Пусть, например, I = 1; J = 2, К = 3. Тогда, написав в программе
![]()
получим на экране строку: 1 2 3. После вывода последнего символа курсор остается в той же строке. Следующий вывод на экран будет начинаться с этой позиции курсора. Второй вариант процедуры вывода на экран:
![]()
Слово WriteLn — write line — означает писать строку. Его действие отличается от оператора Write тем, что после вывода последнего в списке значения происходит перевод курсора к началу следующей строки. Оператор WriteLn, записанный без параметров, вызывает перевод строки. Форматы вывода. В списке вывода могут присутствовать указатели форматов вывода (форматы). Формат определяет представление выводимого значения на экране. Он отделяется от соответствующего ему элемента двоеточием. Если указатель формата отсутствует, то машина выводит значение по определенному правилу, предусмотренному по умолчанию. Ниже кратко, в справочной форме, приводятся правила и примеры бесформатного и форматированного вывода величин различных типов. Для представления списка вывода здесь будут использованы следующие обозначения: I, Р, Q — целочисленные выражения; R — выражение вещественного типа; В — выражение булевского типа; Ch — символьная величина; S — строковое выражение; # — цифра; * — знак «+» или «—»; _ — пробел.
Форматы процедуры Write
I — выводится десятичное представление величины I, начиная с позиции расположения курсора: ![]() I:Р— выводится десятичное представление величины I в крайние правые позиции поля шириной Р: ![]() R — в поле шириной 18 символов выводится десятичное представление величины R в формате с плавающей точкой. Если R ≥ 0,0, используется формат _#.##########Е*##. Если R < 0,0, то формат имеет вид _-#.##########Е*##: ![]() R:Р — в крайние правые позиции поля шириной Р символов выводится десятичное представление значения R в нормализованном формате с плавающей точкой. Минимальная длина поля вывода для положительных чисел составляет 7 символов, для отрицательных — 8 символов. После точки выводится по крайней мере одна цифра: ![]()
R:P:Q — в крайние правые позиции поля шириной Р символов выводится десятичное представление значения R в формате с фиксированной точкой, причем после десятичной точки выводится Q цифр (0 ≤ Q ≤ 24), представляющих дробную часть числа. Если Q = 0, то ни дробная часть, ни десятичная точка не выводятся. Если Q > 24, то при выводе используется формат с плавающей точкой:
![]() Управление символьным выводом на экранИспользование для вывода на экран только процедур Write и WriteLn дает программисту очень слабые возможности для управления расположением на экране выводимого текста. Печать текста может производиться только сверху вниз, слева направо. Невозможны возврат к предыдущим строкам, стирание напечатанного текста, изменение цвета символов и т.д. Дополнительные возможности управления выводом на экран дают процедуры и функции модуля CRT. Для установления связи пользовательской программы с модулем перед разделами описаний должна быть поставлена строка Uses CRT Для работы с модулем CRT необходимо познакомиться со следующими понятиями: режимы экрана, координаты на экране, текстовое окно, цвет фона и цвет символа. Режимы экрана. Вывод на экран может происходить в текстовом или графическом виде (на графических дисплеях). Мы здесь будем говорить только о текстовом выводе. Дисплеи бывают монохроматические (черно-белые) и цветные. Монохроматические дисплеи могут работать только в черно-белом режиме; цветные — как в черно-белом, так и в цветном. Кроме того, текстовые режимы различаются по количеству символьных строк и столбцов, умещающихся на экране. В модуле CRT каждый режим имеет определенный номер, за которым закреплено символическое имя (описанная константа). Для установки режима экрана используется процедура TextMode(<номер режима>) При обращении к процедуре номер режима может задаваться как числом, так и именем соответствующей константы. Например, два оператора TextMode(1); TextMode(CO40); эквивалентны. Как правило, исходный режим экрана, устанавливаемый по умолчанию, — СO80 (на цветных дисплеях). Координаты позиции. Каждая символьная позиция на текстовом экране определена двумя координатами (X, Y). Координата Х — позиция в строке. Для крайней левой позиции в строке Х = 1.. Координата Y — номер строки, в которой находится символ. Строки нумеруются сверху вниз. Например, в режиме 80 х 25 символ в верхнем левом углу имеет координаты (1; 1); символ в нижнем правом углу — (80; 25); символ в середине экрана — (40; 13). Для установления курсора на экране в позицию с координатами (X, Y) в модуле CRT существует процедура: GoToXY(X,Y) Здесь координаты курсора задаются выражениями типа Byte. Вот пример программы, которая очищает экран и выставляет в центре экрана символ *: Uses CRT; Begin CIrScr; GoToXY(40,13); Write('*') End. Используемая здесь процедура ClrScr производит очистку экрана. Текстовое окно. Прямоугольное пространство на экране, в которое производится вывод символов, называется текстовым окном. Положение окна определяется координатами верхнего левого угла и нижнего правого угла прямоугольника. Если окно занимает весь экран, то в режиме 80 х 25 его координаты (1; 1) — (80; 25). Таким является исходное окно. Изменить положение и размер текстового окна можно с помощью процедуры Window(Xl,Yl,X2,Y2) Здесь аргументы — величины типа Byte; (X1, Yl) — координаты верхнего левого угла, (Х2, Y2) — координаты правого нижнего угла окна. После определения окна попытки вывода символов за его пределы оказываются безрезультатными. Повторное обращение к процедуре window с новыми параметрами отменяет предыдущее назначение. Управление цветом. На современных цветных дисплеях типа EGA, VGA, SVGA в текстовом режиме экрана можно использовать 16 цветов. В модуле CRT объявлены константы, имена которых представляют собой английские названия цветов, а соответствующие им значения — порядковые номера этих цветов. Процедура назначения цвета фона: TextBackGround(Color) Здесь аргумент — величина типа Byte, задающая номер цвета. Процедура назначения цвета символа: TextColor(Color) Если цвет фона назначается до очистки текстового окна, то после очистки окно заливается этим цветом. Если фон устанавливается после очистки экрана, то чистое окно будет иметь черный цвет (по умолчанию), а назначенный цвет фона будет устанавливаться в тех позициях, в которые выводятся символы. Вот пример программы, в которой по очереди откроются четыре окна, и каждое из них будет залито своим фоновым цветом: Uses CRT; Begin Window(1,1,40,12); TextBackGround(White); CIrScr; Window(41,1,80,12); TextBackGround(Red); CIrScr; Window(l,13,40,25); TextBackGround(LightRed); CIrScr; Window(41,13,80,25); TextBackGround(Green); CirScr; End. По следующей программе на белом фоне в середине экрана будут выведены номера первых пятнадцати цветов. Каждый номер будет того цвета, который он обозначает. Uses CRT; Var I: Byte; Begin TextBackGround(White) ; CIrScr; GoToXY(l,12); For I:=0 To 14 Do Begin TextColor(I); Write(1:5) ; End End. Кратко опишем еще несколько процедур управления текстовым экраном из модуля CRT. Все эти процедуры не имеют параметров. Процедура ClrEOL. Стирает часть строки от текущей позиции курсора до конца этой строки в окне. При этом положение курсора не меняется. Процедура DelLine. Уничтожает всю строку с курсором. Нижние строки сдвигаются на одну вверх. Процедура InsLine. Вставляет пустую строку перед строкой, в которой стоит курсор. Процедуры LowVideо, NormVideo, HighVideо. Устанавливают режимы пониженной, нормальной и повышенной яркости символов соответственно. Весьма полезной является функция KeyPressed из модуля CRT. При исполнении этой функции происходит опрос клавиатуры и определяется, не нажата ли какая-нибудь клавиша. В результате функция выдает логическое значение True, если нажата любая клавиша, и значение False в противном случае. Часто эту функцию используют для организации задержки окна результатов на экране (после выполнения программы Турбо Паскаль вызывает на экран окно редактора). Перед концом программы записывается следующий оператор: Repeat Until KeyPressed; Это пустой цикл, который «крутится на месте» до нажатия какой-либо клавиши. В это время на экране окно результатов. После нажатия на клавишу значение KeyPressed станет равно True, цикл завершится, будет выполнен переход на метку End и на экран вернется окно редактора. Этот прием можно использовать для задержки выполнения программы в любом ее месте. В приведенную выше программу получения на экране четырех разноцветных окон внесем следующее дополнение: после установки четырехцветного экрана выполнение программы останавливается и изображение сохраняется; затем после нажатия на любую клавишу экранвозвращается в исходный режим (80 х 25, черный фон, белые символы). Для этого перед концом программы нужно добавить следующее: Repeat Until KeyPressed; Window(1,1,80,25); TextBackGround(Black); CIrScr; О других процедурах и функциях модуля CRT читайте в книгах по Турбо Паскалю. Упражнения 1. Что будет напечатано в результате работы программы Program Roots; Var B,C,D: Real; Begin Read(B,C); D:=Sqrt(Sqr(B)-4*C); WriteLn('xl=',(-B+D)/2, 'x2=',(-B-D)/2) End. если в качестве исходных данных заданы числа 10 и —20? 2. Что будет напечатано в результате работы программы Program Less; Var X:Real; T:Boolean; Begin Read(X); T:=X<Round(X); Read(X); T:=T And (X<Trunc(X)) ; WriteLn(T) End. если последовательно вводятся два значения: 34, 79? 3. Что будет напечатано в результате работы программы Program ABC; Var A,B: Integer; Begin Read(A,B,A); WriteLn(A,B:2,A:5) End. если последовательно вводятся три числа: 36, —6, 2345? 4. Составьте программу вычисления суммы двух целых чисел, которая будет вести диалог с пользователем в следующем виде (на месте многоточий — вводимые и выводимые числа): ВВЕДИТЕ ДВА СЛАГАЕМЫХ а=............ b=............ РЕЗУЛЬТАТ ВЫЧИСЛЕНИЙ: а+b=............. Логические величины, операции, выражения. Логический оператор присваиванияПрямое отношение к программированию имеет дисциплина, которая называется математической логикой. Основу математической логики составляет алгебра логики, или исчисление высказываний. Под высказыванием понимается любое утверждение, в отношении которого можно однозначно сказать, истинно оно или ложно. Например, «Луна — спутник Земли» — истинно; «5 > 3» — истинно; «Москва — столица Китая» — ложно; «1 = 0» — ложно. Истина или ложь являются логическими величинами. Логические значения приведенных выше высказываний однозначно определены; другими словами, их значения являются логическими константами. Логическое значение неравенства х < 0, где х — переменная, является переменной величиной. В зависимости от значения х оно может быть либо истиной, либо ложью. В связи с этим возникает понятие логической переменной. Основы формального аппарата математической логики создал в середине XIX в. английский математик Джордж Буль. В его честь исчисление высказываний называют булевой алгеброй, а логические величины — булевскими. Одиночные высказывания могут быть объединены в составные логические формулы с помощью логических операций. Имеются три основные логические операции: отрицание, конъюнкция (логическое умножение) и дизъюнкция (логическое сложение). Операция отрицания обозначается в математической логике значком ¬ и читается как частица не. Это одноместная операция. Например, ¬ (x = у) читается «не (х равно y)». В результате получится истина, если х не равно у, и ложь, если х равно у. Отрицание изменяет значение логической величины на противоположное. Операция конъюнкции обозначается значком & и читается как частица и. Это двухместная операция. Например, (х > 0) & (х < 1) читается «х больше 0 и х меньше 1». Данная логическая формула примет значение истина, если х ![]() В Паскале логические значения обозначаются служебными словами false (ложь) и true (истина), а идентификатор логического типа — boolean. Кроме величин (констант и переменных) типа boolean логические значения false, true принимают результаты операций отношения. Операции отношения (рис. 18) осуществляют сравнение двух операндов и определяют, истинно или ложно соответствующее отношение между ними. ![]() Примеры записи отношений: х<у; a+b>=c/d; abs(m-n)<=l. Примеры вычисления значений отношений: ![]() Логические операции выполняются над операндами булева типа. Имеются четыре логические операции: Not — отрицание; And — логическое умножение (конъюнкция); Or — логическое сложение (дизъюнкция). Кроме этих трех обязательных операций в Турбо Паскале имеется еще операция — исключающее ИЛИ. Ее знак — служебное слово Хоr. Это двухместная операция, которая в результате дает значение истина, если оба операнда имеют разные логические значения. Операции перечислены в порядке убывания приоритетов. Результаты логических операций для различных значений операндов приведены в табл. 3.5. Таблица 3.5 ![]() Операции отношения имеют самый низкий приоритет. Поэтому если операндами логической операции являются отношения, то их следует заключать в круглые скобки. Например, математическому неравенству 1 ≤ х ≤ 50 соответствует следующее логическое выражение: (1<=X) And (X<=50) Логическое выражение есть логическая формула, записанная на языке программирования. Логическое выражение состоит из логических операндов, связанных логическими операциями и круглыми скобками. Результатом вычисления логического выражения является булева величина (false или true). Логическими операндами могут быть логические константы, переменные, функции, операции отношения. Один отдельный логический операнд является простейшей формой логического выражения. Примеры логических выражений (здесь d, b, с — логические переменные; х, у — вещественные переменные; k — целая переменная): ![]() Если d=true; b=false; c=true; x=3.0; y=0.5; k=5, то результаты вычисления будут следующими: ![]() В примере использована логическая функция odd(k). Это функция от целого аргумента k, которая принимает значение true, если значение k нечетное, и false, если k четное. Логический оператор присваивания имеет структуру, представленную на рис. 19. ![]() Примеры логических операторов присваивания: 1) d:=true; 2) b:=(x>y) and (k<>0); 3) c:=d or b and not (odd(k) and d). Функции, связывающие различные типы данныхВ табл. 3.6 приводится список стандартных функций, обеспечивающих связь между различными типами данных. Таблица 3.6 ![]() Функции ord, pred и succ применимы только к порядковым типам. Из простых типов это все, кроме вещественного. Функция ord, применяемая к целому числу, дает его собственное значение. Например, ord(-35)=-35; ord(128)=128 Если аргумент целый, то, например, оператор y:=pred(x) эквивалентен у:=х-1, а у:=succ(x) эквивалентен у:=х+1. Для символьного типа аргумента эти функции дают соответственно предыдущий и следующий символ в таблице внутренней кодировки. Поскольку латинский алфавит всегда упорядочен по кодам, т.е. ord('a')<ord('b')<…<-Ord('z'), то, например, pred('b')='a', a succ('b')='c' То же относится и к цифровым литерам: pred('5')='4'; succ('5')='6' Функция chr (x) является обратной к функции ord(x), если х — символьная величина. Это можно выразить формулой chr(ord(x))=х, где х — символьная величина. Например, для кода ASCII справедливо ord('a')=97; chr(97)='a' В некоторых случаях возникает задача преобразования символьного представления числа в числовой тип. Например, нужно получить из литеры '5' целое число 5. Это делается так: N:=ord('5')-ord('0'), где N — целая переменная. Здесь использован тот факт, что код литеры '5' на пять единиц больше кода '0'. Булевский тип также является порядковым. Порядок расположения двух его значений таков: false, true. Отсюда справедливы следующие отношения: ord(false)=0, succ(false)=true, ord(true)=1, pred(true)=false Вот интересный пример. Пусть х, у, z — вещественные переменные. Как вы думаете, какую задачу решает следующий оператор: z:=x*ord(x>=y)+y*ord(y>x) Ответ такой: z = mах(х, у). Как видите, эту задачу можно решить, не используя условного оператора if...then...else. Упражнения 1. Вычислить значения логических выражений: а) К mod 7=K div 5-1 при К=15; б) odd(trunc(10*P)) при Р=0.182; В) not odd(n)при n=0; г) t and (P mod 3=0) при t=true, P=10101; Д) (x*y<>0) and (y>x) при х=2, y=l; e) a or not b при a=false, b=true. 2. Если a=true и х=1, то какое значение получит логическая переменная d после выполнения оператора присваивания: a) d:=x<2; б) d:=not a or odd(x); в) d:=ord(a)ox 3. Написать оператор присваивания, в результате выполнения которого логическая переменная t получит значение true, если высказывание истинно, и значение false — в противном случае, для следующих высказываний: а) из чисел х, у, z только два равны между собой; б) х — положительное число; в) каждое из чисел х, у, z положительно; г) только одно из чисел х, у, z положительно; д) р делится нацело на q; e) цифра 5 входит в десятичную запись трехзначного целого числа k. Логические выражения в управляющих операторахАлгоритмическая структура ветвления программируется в Паскале с помощью условного оператора. Раньше мы его описывали в таком виде: If <условие> Then <оператор 1> Else <оператор 2>; Кроме того, возможно использование неполной формы условного оператора: If <условие> Then <оператор>; Теперь дадим строгое описание условного оператора в форме синтаксической диаграммы (рис. 20). ![]() То, что мы раньше называли условием, есть логическое выражение, которое вычисляется в первую очередь. Если его значение равно true, то будет выполняться <оператор 1> (после Then), если false, то <оператор 2> (после Else) для полной формы или сразу следующий оператор после условного для неполной формы (без Else). Пример 1. По длинам трех сторон треугольника а, b, с вычислить его площадь. Для решения задачи используется формула Герона ![]() где р = (а + b + с) / 2 — полупериметр треугольника. Исходные данные должны удовлетворять основному соотношению для сторон треугольника: длина каждой стороны должна быть меньше длин двух других сторон. Имея возможность в одном условном операторе записывать достаточно сложные логические выражения, мы можем сразу «отфильтровать» все варианты неверных исходных данных. Program Geron; Var A,B,C,P,S: Real; Begin WriteLn('Введите длины сторон треугольника:'); Write('а='); ReadLn(A) ; Write('b='); ReadLn(В); Write ('c='); ReadLn(C); If (A>0) And (B>0) And (00) And (A+B>C) And (B+С>A) And (A+C>B) Then Begin P:=(A+B+C)/2; S:=Sqrt(P*(P-A)*(P-B)*(P-C)); WriteLn('Площадь=',S) End Else WriteLn('Неверные исходные данные') End. Теперь рассмотрим синтаксическую диаграмму оператора цикл-пока, или цикл с предусловием (рис. 21). ![]() Сначала вычисляется <Логическое выражение>. Пока его значение равно true, выполняется <0ператор> — тело цикла. Здесь <Oператор> может быть как простым, так и составным. Пример 2. В следующем фрагменте программы на Паскале вычисляется сумма конечного числа членов гармонического ряда ![]() Суммирование прекращается, когда очередное слагаемое становится меньше ε или целая переменная i достигает значения MaxInt. S:=0; I:=l; While (l/I>=Eps) And (I<MaxInt) Do Begin S:=S+1/I; I:=1+1 End; Синтаксическая диаграмма оператора цикл-до, или цикл с постусловием, представлена на рис. 22. ![]() Исполнение цикла повторяется до того момента, когда <Логическое выражение> станет равным true. Предыдущая задача с использованием цикла с постусловием решается так: S:=0; I:=1; Repeat S:=S+1/I; I:=I+1 Until (1/I<Eps) Or (I>=MaxInt) Цикл по параметруРассмотрим следующую простую задачу: требуется вычислить сумму целых чисел от M до N путем прямого суммирования. Здесь М и N — целые числа. Задачу можно сформулировать так: ![]() Алгоритм и программа решения этой задачи с использованием структуры цикл-пока представлены на рис. 23. ![]() А теперь введем новый тип циклической структуры, который будет называться цикл по параметру, или цикл-для. Блок-схема и программа наПаскале для решения рассматриваемой задачи с использованием этой структуры приведены на рис. 24. ![]() Здесь целая переменная I последовательно принимает значения в диапазоне от М до N. При каждом значении I выполняется тело цикла. После последнего выполнения цикла при I = N происходит выход из цикла на продолжение алгоритма. Цикл выполняется хотя бы один раз, если М ≤ N, и не выполняется ни разу при М > N. В программе используется оператор цикла For, синтаксическая диаграмма которого представлена на рис. 25. ![]() Выполнение оператора For в первом варианте (То) происходит по следующей схеме: 1. Вычисляются значения < Выражения 1> и < Выражения 2>. Это делается только один раз при входе в цикл. 2. Параметру цикла присваивается значение < Выражения 1>. 3. Значение параметра цикла сравнивается со значением < Выражения 2 >. Если параметр цикла меньше или равен этому значению, то выполняется тело цикла, в противном случае выполнение цикла заканчивается. 4. Значение параметра цикла изменяется на следующее значение в его типе (для целых чисел — увеличивается на единицу); происходит возврат к пункту 3. Оператор цикла For объединяет в себе действия, которые при использовании цикла While выполняют различные операторы: присваивание параметру начального значения, сравнение с конечным значением, изменение на следующее. Как известно, результат суммирования целых чисел не зависит от порядка суммирования. Например, в рассматриваемой задаче числа можно складывать и в обратном порядке, т.е. от N до М (N ≥ М). Для этого можно использовать второй вариант оператора цикла For: Summa:=0 ; For I:=N DownTo M Do Summa:=Summa+I; Слово DownTo буквально можно перевести как «вниз до». В таком случае параметр цикла изменяется по убыванию, т.е. при каждом повторении цикла параметр изменяет свое значение на предыдущее (равносильно i:=pred(i)). Тогда ясно, что цикл не выполняется ни разу, если N < М. Работая с оператором For, учитывайте следующие правила: • параметр цикла не может иметь тип Real; • в теле цикла нельзя изменять переменную «параметр цикла»; • при выходе из цикла значение переменной-параметра является неопределенным. В следующем примере в качестве параметра цикла For используется символьная переменная. Пусть требуется получить на экране десятичные коды букв латинского алфавита. Как известно, латинские буквы в таблице кодировки упорядочены по алфавиту. Вот фрагмент такой программы: For С:='а' То 'z' Do Write (С,'-',Ord(C)); Здесь переменная С имеет тип Char. А теперь подумайте сами, как вывести кодировку латинского алфавита в обратном порядке (от 'z' до 'а'). Упражнения 1. Составить программу полного решения квадратного уравнения (алгоритм см. в разд. 1.3). 2. Используя операторы цикла While, Repeat и For, составить три варианта программы вычисления N!. 3. Составить программу, по которой будет вводиться последовательность символов до тех пор, пока не встретится маленькая или большая латинская буква z. Подсчитать, сколько раз среди вводимых символов встречалась буква W. 4. Вычислить сумму квадратов всех целых чисел, попадающих в интервал (ln х, еx), х > 1. 5. Вычислить количество точек с целочисленными координатами, попадающих в круг радиуса R (R > 0) с центром в начале координат. 6. Напечатать таблицу значений функции sin x и cos x на отрезке [0, 1] с шагом 0,1 в следующем виде: ![]() 7. Напечатать в возрастающем порядке все трехзначные числа, в десятичной записи которых нет одинаковых цифр. 8. Дано целое п > 2. Напечатать все простые числа из диапазона [2, п]. ПодпрограммыС понятием вспомогательного алгоритма вы уже знакомы (см. разд. 1.4). В языках программирования вспомогательные алгоритмы называются подпрограммами. В Паскале различаются две разновидности подпрограмм: процедуры и функции. Рассмотрим этот вопрос на примере следующей задачи: даны два натуральных числа a и b. Требуется определить наибольший общий делитель трех величин: а + b, |а – b|, а • b. Запишем это так: НОД (a + b, |а – b|, а • b). Идея решения состоит в следующем математическом факте: если х, у, z — три натуральных числа, то НОД(х, у, z) = НОД(НОД(х, у), z). Иначе говоря, нужно найти НОД двух величин, а затем НОД полученного значения и третьего числа (попробуйте это доказать). Очевидно, что вспомогательным алгоритмом для решения поставленной задачи является алгоритм получения наибольшего общего делителя двух чисел. Эта задача решается с помощью известного алгоритма Евклида (см. раздел 1.3). Запишем его в форме процедуры на алгоритмическом языке. Процедура Евклид(цел M,N,K); нач пока M<>N нц если M>N то M:=M-N иначе N:=N-M кв кц; K:=M кон Здесь M и N являются формальными параметрами процедуры. M и N параметры-аргументы, K — параметр-результат. Основной алгоритм, решающий исходную задачу, будет следующим: алг задача; цел а,b,с; нач ввод(а,b); Евклид(а+b,|a-b|,с); Евклид(с,а*b,с); вывод(с) кон. Процедуры в Паскале. Основное отличие процедур в Паскале от процедур в Алгоритмическом языке (АЯ) состоит в том, что процедуры в Паскале описываются в разделе описания подпрограмм, а в АЯ процедура является внешней по отношению к вызывающей программе. Теперь посмотрим, как решение поставленной задачи программируется на Турбо Паскале. Program NOD1; Var А,В,С: Integer; Procedure Evklid(M,N: Integer; Var К: Integer); Begin While M<>N Do If M>N Then M:=M-N Else N:=N-M; K:=M End; Begin Write('a='); ReadLn(A) ; Write('b='); ReadLn(B); Evklid(A+B,Abs(A-B),C); Evklid(C,A*B,C); WriteLn('НОД=',C) End. В данном примере обмен аргументами и результатами между основной программой и процедурой производится через параметры (формальные и фактические). Существует и другой механизм обмена — через глобальные переменные. Но об этом чуть позже. А сейчас рассмотрим синтаксическую диаграмму описания процедуры (рис. 27). ![]() Из диаграммы видно, что процедура может иметь параметры, а может быть и без них Чаще всего аргументы представляются как параметры-значения (хотя могут быть и параметрами-переменными). А для передачи результатов используются параметры-переменные. Процедура в качестве результата может передавать в вызывающую программу множество значений (в частном случае — одно), а может и ни одного. Теперь рассмотрим правила обращения к процедуре. Обращение к процедуре производится в форме оператора процедуры (рис. 28). ![]() Если описана процедура с формальными параметрами, то и обращение к ней производится оператором процедуры с фактическими параметрами. Правила соответствия между формальными и фактическими параметрами: соответствие по количеству, соответствие по последовательности и соответствие по типам. Первый вариант взаимодействия формальных и фактических параметров называется передачей по значению: вычисляется значение фактического параметра (выражения) и это значение присваивается соответствующему формальному параметру. Второй вариант взаимодействия называется передачей по имени: при выполнении процедуры имя формальной переменной заменяется на имя соответствующей фактической переменной (в откомпилированной программе имени переменной соответствует адрес ячейки памяти). В рассмотренном нами примере формальные параметры М и N являются параметрами-значениями. Это аргументы процедуры. При обращении к ней первый раз им соответствуют значения выражений а + b и abs (а - b); второй раз — с и а • b. Параметр K является параметром-переменной. В ней получается результат работы процедуры. В обоих обращениях к процедуре соответствующим фактическим параметром является переменная с. Через эту переменную основная программа получает результат. Теперь рассмотрим другой вариант программы, решающей ту же задачу. В ней используется процедура без параметров. Program NOD2; Var A,B,K,M,N: Integer; Procedure Evklid; Begin While M<>N Do If M>N Then M:=M-N Else N:=N-M; K:=M End; Begin Write('a='); ReadLn(A); Write('b='); ReadLn(B); M:=A+B; N:=Abs(A-B); Evklid; M:=K; N:=A*B; Evklid; WriteLn('HOД равен',K) End. Чтобы разобраться в этом примере, требуется объяснить новое для нас понятие: область действия описания. Областью действия описания любого программного объекта (переменной, типа, константы и т.д.) является тот блок, в котором расположено это описание Если данный блок вложен в другой (подпрограмма), то присутствующие в нем описания являются локальными. Они действуют только в пределах внутреннего блока. Описания же, стоящие во внешнем блоке, называются глобальными по отношению к внутреннему блоку. Если глобально описанный объект используется во внутреннем блоке, то на него распространяется внешнее (глобальное) описание. В программе NOD1 переменные М, N, К — локальные внутри процедуры; переменные а, b, с — глобальные. Однако внутри процедуры переменные а, b, с не используются. Связь между внешним блоком и процедурой осуществляется через параметры. В программе NOD2 все переменные являются глобальными. В процедуре Evklid нет ни одной локальной переменной (нет и параметров). Поэтому переменные М и N, используемые в процедуре, получают свои значения через оператор присваивания в основном блоке программы. Результат получается в глобальной переменной К, значение которой выводится на экран. Использование механизма передачи через параметры делает процедуру более универсальной, независимой от основной программы. Однако в некоторых случаях оказывается удобнее использовать передачу через глобальные переменные. Чаще такое бывает с процедурами, работающими с большими объемами информации. В этой ситуации глобальное взаимодействие экономит память ЭВМ. Функции. Теперь выясним, что такое подпрограмма-функция. Обычно функция используется в том случае, если результатом подпрограммы должна быть скалярная (простая) величина. Тип результата называется типом функции. В Турбо Паскале допускаются функции строкового типа. Синтаксическая диаграмма описания функции представлена на рис. 29. ![]() Как и у процедуры, у функции в списке формальных параметров могут присутствовать параметры-переменные и параметры-значения. Все это аргументы функции. Параметры вообще могут отсутствовать (если аргументы передаются глобально). Программа решения рассмотренной выше задачи с использованием функции будет выглядеть следующим образом: Program NOD3; Var А,В,Rez:Integer; Function Evklid(M,N:Integer):Integer; Begin While M<>N Do If M>N Then M:=M-N Else N:=N-M; Evklid:=M End; Begin Write('a='); ReadLn(A); Write('b='); ReadLn(B); Rez:=Evklid(Evklid(A+B,Abs(A-B)),A*B); WriteLn('NOD равен',Rez) End. Из примера видно, что тело функции отличается от тела процедуры только тем, что в функции результат присваивается переменной с тем же именем, что и функция. Обращение к функции является операндом в выражении. Оно записывается в следующей форме: <Имя функции> (<Список фактических параметров>) Правила соответствия между формальными и фактическими параметрами все те же. Сравнивая приведенные выше программы, можно сделать вывод, что программа NOD3 имеет определенные преимущества перед другими. Функция позволяет получить результат путем выполнения одного оператора присваивания. Здесь иллюстрируется возможность того, что фактическим аргументом при обращении к функции может быть эта же функция. По правилам стандарта Паскаля возврат в вызывающую программу из подпрограммы происходит, когда выполнение подпрограммы доходит до ее конца (последний End). Однако в Турбо Паскале есть средство, позволяющее выйти из подпрограммы в любом ее месте. Это оператор-процедура Exit. Например, функцию определения наибольшего из двух данных вещественных чисел можно описать так: Function Max(X,Y: Real): Real; Begin Max:=X; If X>Y Then Exit Else Max:=Y End; Еще раз об области действия описаний. В Паскале неукоснительно действует следующее правило: любой программный объект (константа, переменная, тип и т.п.) должен быть описан перед использованием в программе. Иначе говоря, описание объекта должно предшествовать его первому появлению в других фрагментах программы. Это правило относится и к подпрограммам. На рис. 30 схематически показана структура взаимного расположения описаний подпрограмм в некоторой условной программе. Попробуем, используя эту схему, разобраться в вопросе об области действия описаний подпрограмм. ![]() Любая подпрограмма может использоваться лишь в пределах области действия ее описания. Например, область действия подпрограмм А и В — основная программа. Поэтому из основной программы можно обратиться к подпрограммам А и В. В свою очередь, в подпрограмме В могут быть обращения к подпрограмме А; а из А нельзя обратиться к В, поскольку описание А предшествует описанию В. Подпрограммы А1 и А2 локализованы в подпрограмме A и могут использоваться только в ней; из А2 можно обратиться к A1, но не наоборот. Из подпрограммы B1 можно обратиться к А, поскольку ее описание является глобальным по отношению к B1, но нельзя обратиться к А1, поскольку область действия описания А1 не распространяется на блок подпрограммы В. Из подпрограммы В22 можнообратиться только к B21, B1, А. Объясните сами почему. Все понятно? Если нет, то прочитайте еще раз этот раздел. Очень важно в нем разобраться. Если одно и то же имя описано во внешнем блоке (глобально) и во внутреннем блоке (локально), то последнее описание (локальное) перекрывает первое в пределах внутреннего блока. Рассмотрим следующий пример: Program Example1; Program Example2; Var X: Integer; Var X: Integer; Procedure P; Procedure P; Var X: Integer; Begin Begin WriteLn('x=',X) WriteLn('x=',X) End; End; Begin X:=1; Begin X:=l; P P End. End. Что выведется на экран в результате работы программы Example1 и Example2? Первая программа выдаст результат: х=... На месте многоточия будет какое-то произвольное значение, соответствующее неопределенной величине х. Вторая программа в результате даст х=1 В первом случае переменная с именем х описана как глобально, так и локально. Но процедура выводит значение локальной переменной, которой ничего не присвоено. В этом примере идентификатором х обозначены две совершенно разные величины, им соответствуют две разные ячейки памяти. Во втором примере переменная х одна на всю программу. Она описана глобально. Поэтому значение 1, присвоенное ей в основной программе, передается и в подпрограмму. Далее разговор пойдет о ситуации на первый взгляд совершенно парадоксальной. Оказывается, подпрограмма в своем описании может содержать обращение к самой себе. Такая подпрограмма называется рекурсивной. Рекурсивные подпрограммы. В математике рекурсивным называется определение любого понятия через самое себя. Классическим примером является определение факториала целого числа, большего или равного нулю: ![]() Здесь функция факториала определена через факториал. Нетрудно понять справедливость такого определения. Для п > 0 ![]() Вариант 0!=1 является тривиальным. Но это «опорное» значение, от которого начинается раскручивание всех последующих значений факториала: ![]() Рассмотрим подпрограмму-функцию, использующую в своем описании приведенную выше рекурсивную формулу. Function Factor(N: Pozint): Pozint; Begin If N=0 Then Factor:=1 Else Factor:=N*Factor(N-l) End; Предполагается, что тип PozInt объявлен глобально следующим образом: Type PozInt=0..MaxInt; Пусть в основной программе для вычисления в целой переменной х значения 3! используется оператор X:=Factor(3); При вычислении функции с аргументом 3 произойдет повторное обращение к функции Factor(2). Это обращение потребует вычисления Factor(1). И наконец, при вычислении Factor(0) будет получен числовой результат 1. Затем цепочка вычислений раскрутится в обратном порядке: Factor(1)=l*Factor(0)=1 Factor(2)=2*Factor(1)=2 Factor(3)=3*Factor(2)=6. Последовательность рекурсивных обращений к функции должна обязательно выходить на определенное значение. А весь маршрут последовательных вхождений машина запоминает в специальной области памяти, называемой стеком. Таким образом, выполнение рекурсивной функции происходит в два этапа: прямой ход — заполнение стека; обратный ход — цепочка вычислений по обратному маршруту, сохраненному в стеке. Использование рекурсивных функций — красивый прием с точки зрения программистской эстетики. Однако этот путь не всегда самый рациональный. Рассмотренную задачу с п! можно решить так: F:=l; For I:=l To N Do F:=F*I; Очевидно, что такой вариант программы будет работать быстрее, чем рекурсивный. И в том случае, когда важнейшим является сокращение времени выполнения программы, следует отдать предпочтение последнему варианту. В каждой конкретной реализации Паскаля имеется ограничение на количество рекурсивных обращений к подпрограмме (глубина рекурсии). Это связано с ограничением на размер стека. По этой причине можно попасть в ситуацию, когда рекурсивной подпрограммой вообще не удастся воспользоваться. Рекурсивно определена может быть не только функция, но и процедура. Примеры использования рекурсивно-определенных процедур рассматриваются в пятой главе. Упражнения 1. Составить программу вычисления площади кольца по значениям внутреннего и внешнего радиусов, используя подпрограмму вычисления площади круга (2 варианта: с процедурой и с функцией). 2. По координатам вершин треугольника вычислить его периметр, используя подпрограмму вычисления длины отрезка, соединяющего две точки. 3. Даны три целых числа. Определить, сумма цифр которого из них больше. Подсчет суммы цифр организовать через подпрограмму. 4. Определить площадь выпуклого четырехугольника по заданным координатам вершин. Использовать подпрограмму-функцию вычисления длины отрезка и подпрограмму-процедуру вычисления площади треугольника по формуле Герона. 5. Описать рекурсивную функцию pow(x, n) от вещественного х (х ≠ 0) и целого п, которая вычисляет величину хn по формуле ![]() 6. Даны натуральные числа п и т; найти НОД (n, т). Использовать программу, включающую в себя рекурсивную процедуру вычисления НОД, и основанную на соотношении НОД (n, т) = НОД (т, r), где r — остаток от деления п на т. Вычисление рекуррентных последовательностейРекуррентная последовательность. Из курса математики известно понятие рекуррентной последовательности. Это понятие вводится так: пусть известно k чисел a1, ..., аk. Эти числа являются первыми числами числовой последовательности. Следующие элементы данной последовательности вычисляются так: ![]() Здесь F— функция от k аргументов. Формула вида ![]() называется рекуррентной формулой. Величина k называется глубиной рекурсии. Другими словами, можно сказать, что рекуррентная последовательность — это бесконечный ряд чисел, каждое из которых, за исключением k начальных, выражается через предыдущие. Примерами рекуррентных последовательностей являются арифметическая (1) и геометрическая (2) прогрессии: ![]() Рекуррентная формула для указанной арифметической прогрессии: ![]() Рекуррентная формула для данной геометрической прогрессии: ![]() Глубина рекурсии в обоих случаях равна единице (такую зависимость еще называют одношаговой рекурсией). В целом рекуррентная последовательность описывается совокупностью начальных значений и рекуррентной формулы. Все это можно объединить в одну ветвящуюся формулу. Для арифметической прогрессии: ![]() Для геометрической прогрессии: ![]() Следующая числовая последовательность известна в математике под названием чисел Фибоначчи: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ... Начиная с третьего элемента каждое число равно сумме значений двух предыдущих, т. е. это рекуррентная последовательность с глубиной равной 2 (двухшаговая рекурсия). Опишем ее в ветвящейся форме: ![]() Введение представления о рекуррентных последовательностях позволяет по-новому взглянуть на некоторые уже известные нам задачи. Например, факториал целого числа п! можно рассматривать как значение n-го элемента следующего ряда чисел: ![]() Рекуррентное описание такой последовательности выглядит следующим образом: ![]() Программирование вычислений рекуррентных последовательностей. С рекуррентными последовательностями связаны задачи такого рода: 1) вычислить заданный (n-й) элемент последовательности; 2) математически обработать определенную часть последовательности (например, вычислить сумму или произведение первых n членов); 3) подсчитать количество элементов на заданном отрезке последовательности, удовлетворяющих определенным свойствам; 4) определить номер первого элемента, удовлетворяющего определенному условию; 5) вычислить и сохранить в памяти заданное количество элементов последовательности. Данный перечень задач не претендует на полноту, но наиболее часто встречающиеся типы он охватывает. В четырех первых задачах не требуется одновременно хранить в памяти множество элементов числового ряда. В таком случае его элементы могут получаться последовательно в одной переменной, сменяя друг друга. Пример 1. Вычислить п-й элемент арифметической прогрессии (1). Var M,I: 0..Maxint; A: Real; Begin Write('N='); ReadLn(N); A:=l; For I: =2 To N Do A:=A+2; WriteLn('A(',N:l,')=',A:6:0) End. Рекуррентная формула ai = ai-1 + 2 перешла в оператор А := А + 2. Пример 2. Просуммировать первые п элементов геометрической прогрессии (2) (не пользуясь формулой для суммы первых n членов прогрессии). Var N,1: 0..Maxint; A,S: Real; Begin Write('N='); ReadLn(N); A:=l; S:=A; For I: =2 To N Do Begin A:=2*A; S:=S+A End; WriteLn('Сумма равна',S:6:0) End. При вычислении рекуррентной последовательности с глубиной 2 уже нельзя обойтись одной переменной. Это видно из следующего примера. Пример 3. Вывести на печать первые п (п ≥ 3) чисел Фибоначчи. Подсчитать, сколько среди них четных чисел. Var N,I,K,F,F1,F2: 0..Maxint; Begin Fl:=l; F2:=l; K:=0; WriteLn('F(l)=',Fl,'F(2)=',F2); For I:=3 To N Do Begin F:=F1+F2; WriteLn('F(',I:l,')=',F); If Not Odd(F) Then K:=K+1; F1:=F2; F2:=F End; WriteLn('Количество четных чисел в последовательности равно',К) End. Понадобились три переменные для последовательного вычисления двухшаговой рекурсии, поскольку для нахождения очередного элемента необходимо помнить значения двух предыдущих. Пример 4. Для заданного вещественного х и малой величины ε (например, ε = 0,000001) вычислить сумму ряда ![]() включив в нее только слагаемые, превышающие ε. Известно, что сумма такого бесконечного ряда имеет конечное значение, равное еx, где е = 2,71828... — основание натурального логарифма. Поскольку элементы этого ряда представляют собой убывающую последовательность чисел, стремящуюся к нулю, то суммирование нужно производить до первого слагаемого, по абсолютной величине не превышающего ε. Если слагаемые в этом выражении обозначить следующим образом: Пример 5. Для заданного натурального N и вещественного х (х > 0) вычислить значение выражения: ![]() В этом случае рекуррентность не столь очевидна. Попробуем найти ее методом индукции. Будем считать, что искомое выражение есть N-й элемент последовательности следующего вида: ![]() Отсюда видна связь: ![]() Теперь поставленная задача решается очень просто: Var A,X: Real; I,N: Integer; Begin Write('X='); ReadLn(X); Write('N='); ReadLn(N); A:= Sqrt(X); For I:=2 To N Do A:=Sqrt(X+A); WriteLn('Ответ:',А) End. К решению всех перечисленных выше задач можно подойти иначе. Вспомним о рекурсивно определенных подпрограммах. Посмотрите на описание арифметической прогрессии в форме рекуррентной последовательности. Из него непосредственно вытекает способ определения функции для вычисления заданного элемента прогрессии. Сделаем это для общего случая, определив арифметическую прогрессию с первым членом а0 и разностью d: ![]() Соответствующая подпрограмма-функция выглядит так: Function Progres(АО,D: Real;I: Integer): Real; Begin If I=1 Then Progres:=AO Else Progres:=Progres(A0,D,I-1)+D End; Следующая программа выводит на экран первые 20 чисел Фибоначчи, значения которых вычисляет рекурсивная функция Fibon. Var К: Byte; Function Fibon(N: Integer): Integer; Begin If (N=1) Or (N=2) Then Fibon:=1 Else Fibon:=Fibon(N-1)+Fibon(N-2) End; Begin For K:=l To 20 Do WriteLn(Fibon(K)) End. Основные понятия и средства компьютерной графики в Турбо ПаскалеДо сих пор мы использовали экран компьютера только для вывода символьной информации — чисел, текстов. Однако Турбо Паскаль позволяет выводить на экран рисунки, чертежи, графики функций, диаграммы и т.п., все то, что принято называть компьютерной графикой. В стандарте Паскаля графический вывод не предусмотрен. Однако на разных типах компьютеров, в разных реализациях Паскаля существуют различные программные средства графического вывода — специальные наборы данных, функций, процедур. Несмотря на такое разнообразие, имеются общие понятия и средства, свойственные любому варианту реализации графики в любом языке программирования. В данном разделе лекций мы затронем только такие базовые средства. Начиная с четвертой версии Турбо Паскаля для IBM PC появилась мощная графическая библиотека, организованная в модуль Graph. В приложении 2 в справочной форме дано описание основных компонент этого модуля. В рассмотренных ниже примерах программ используется модуль Graph. Для его подключения в начале программы необходимо написать строку: Uses Graph; Графические режимы экрана. Для вывода графических изображений необходимо перевести экран в один из графических режимов. В графическом режиме можно из программы управлять состоянием каждого пиксела (точечного элемента) экрана. Графические режимы отличаются: • размером графической сетки (M x N, где М — число точек по горизонтали, N — число точек по вертикали); • цветностью (число воспроизводимых на экране цветов). Допустимые режимы зависят от типа монитора и соответствующего графического драйвера, используемого на компьютере. Для установки графического режима экрана существуют соответствующие процедуры. В модуле Graph процедура установки графического режима экрана имеет следующий заголовок: Procedure InitGraph(Var Driver,Mode: Integer; Path: String); Здесь целая переменная Driver определяет тип графического драйвера; целая переменная Mode задает режим работы графического драйвера; Path — выражение типа String, содержащее маршрут поиска файла графического драйвера. Список констант модуля Graph, определяющих типы драйверов и режимы, приведен в табл. П2.1 приложения 2. Вот пример программы, инициализирующей графический режим VGAHi для работы с драйвером VGA (монитор типа VGA). Uses Graph; Var Driver,Mode: Integer; Begin Driver: = VGA;{драйвер} Mode: = VGAHi;(режим работы} InitGraph(Driver,Mode,'C:\TP\BGI'); Здесь указывается, что файл egavga.bgi с драйвером для VGA-монитора находится в каталоге C:\TP\BGI. Режим VGAHi соответствует графической сетке 640 х 480 с палитрой из 16 цветов. Возможно также автоматическое определение типа драйвера и установка режима. Этот прием позволяет программе работать с разными типами мониторов, не внося изменений в текст: Driver:=Detect; InitGraph(Driver,Mode,'C:\TP\BGI'); При этом автоматически устанавливается режим с наибольшей разрешающей способностью и цветностью. После окончания работы в графическом режиме следует вернуться в текстовый режим экрана. В модуле Graph процедура возвращения в текстовый режим имеет заголовок: Procedure CloseGraph; Цвет фона и цвет рисунка. На цветном мониторе можно менять окраску экрана. Установленная окраска экрана называется цветом фона. Рисунок на этом фоне наносится с помощью разнообразных линий: прямых, окружностей, прямоугольников, ломаных и т.д. Цвета этих линий также могут меняться. В табл. П2.2 приложения 2 приведены имена констант, определяющих 16 цветов палитры для мониторов типа EGA, VGA. Заголовок процедуры установки цвета фона: Procedure SetBkColor(Color: Word); Здесь Color — выражение целого типа, определяющее номер цвета фона. Заголовок процедуры установки цвета линий: Procedure SetColor(Color: Word); Заметим, что если в качестве номера цвета линии указывается 0, то это всегда совпадает с цветом фона (невидимая линия). Если необходимо очистить графический экран (стереть рисунок), то для этого используется процедура очистки экрана. Заголовок процедуры очистки экрана: Procedure ClearDevice; В результате выполнения этой процедуры экран заполняется установленным цветом фона. Графические координаты. Положение каждого пикселя графической сетки однозначно определяется указанием его координат. Графические оси координат расположены на экране так, как показано на рис. 31.
Function GetMaxX; For X:=l То 25 Do
Ellipse(200,250,0,359,10,20);{нос}
Вместе с графиком функции строятся оси координат. Ось Х имеет координату Yg= 90, ось Y — координату Xg = 10.
Строковый тип данных
, >, <=, >=, <> производят сравнение двух строк, в результате чего получается логическая величина (true или false). Операция отношения имеет более низкий приоритет, чем операция сцепления. Сравнение строк производится слева направо до первого несовпадающего символа, и больше считается та строка, в которой первый несовпадающий символ имеет больший номер в таблице символьной кодировки.
От исходной символьной информации он должен перейти к работе с числовой информацией. Если предположить, что строка составлена только из четырех символов в соответствии с указанным форматом, то задача решается довольно просто. Вот программа такого интерпретатора:
Табличные данные и массивы
Тип элементов массива называется его базовым типом. Очевидно, что для рассмотренных массивов температур базовым типом является вещественный (Real).
Var H: Аггау[1981..1990]. Of Array[1..12] Of Real;
Например, если в таблице H требуется, чтобы данные за 1989 г. были такими же, как за 1981 г. (девятой строке присвоить значение первой строки), то это можно делать так:
Пусть из рассмотренного выше массива температур требуется отобрать самую высокую температуру и номер месяца, ей соответствующего. Идея алгоритма решения этой задачи: чтобы получить максимальную температуру в вещественной переменной TMах, сначала в нее заносится первое значение массива T[1]. Затем поочередно сравнивается значение TMах с остальными элементами массива температур, и каждое значение большее, чем TMах, присваивается этой переменной. Для получения номера самого теплого месяца в целой переменной NumMax в нее следует каждый раз засылать номер элемента массива температур одновременно с занесением в TMах его значения.
Упражнения:
3. Для вектора {хi}, i = 1,..., 20, подсчитать количество компонент, значения которых лежат в интервале [0,1].
Понятие множества. Множественный тип данных
Операции над множествами. В Паскале реализованы основные операции теории множеств. Это объединение, пересечение, разность множеств. Во всех таких операциях операнды и результаты есть множественные величины одинакового базового типа.
Пример 1. Дана символьная строка. Подсчитать в ней количество знаков препинания (. - , ; : ! * ?).
Var А,В: Set Of 2..N;
Файлы. Файловые переменные
Пример 1. В файловую переменную Fx занести 20 вещественных чисел, последовательно вводимых с клавиатуры.
INPUT — логическое имя стандартного устройства ввода, связанного с клавиатурой; при этом вводимые с клавиатуры символы отражаются на экране дисплея;
Можно договориться о каком-то условном значении, которое будет признаком конца ввода. Пусть, например, признаком конца ввода будет число 9999.
Текстовый файл можно создать или преобразовать с помощью текстового редактора. Его можно просмотреть на экране дисплея или распечатать на принтере.
Пример 6. Пусть файл с именем Note.txt содержит некоторый текст. Требуется подсчитать количество строк в этом тексте.
Упражнения
Комбинированный тип данных
Такая структура называется двухуровневым деревом. В Паскале эта информация может храниться в одной переменной типа Record (запись). Задать тип и описать соответствующую переменную можно следующим образом:
Такая организация данных позволит, например, делать выборки информации по году рождения или по городу, где живут студенты. В этом случае описание соответствующей записи будет выглядеть так:
Работа с файлами записей. Чаще всего записи используются как элементы файлов, составляющих компьютерные информационные системы. Рассмотрим примеры программ, работающих с файлами записей.
В стандарте языка Паскаль допустим только последовательный доступ к элементам файла. Одной из дополнительных возможностей, реализованных в Турбо Паскале, является прямой доступ к записям файла.
© Семенов Андрей Александрович, с. Стеклянное 2009-2015 г. |
Программирование |