Реферат Курсовая Конспект
Общая схема решения задачи на персональном компьютере - Лекция, раздел Философия, Введение Учебное Пособие Написано На Основе Кур...
|
Введение
Учебное пособие написано на основе курса лекций, читаемых студентам 1-2 курсов математического факультета. Может быть полезно начинающим программистам, желающим самостоятельно изучить основы программирования на языке Object Pascal или слушающим соответствующий лекционный курс. Предполагается, что читатель хотя бы в минимальной степени знаком с операционными системами DOS и Windows и понимает, например, что такое имя файла, каталог, папка, диск, путь и т.п. Информация о средах программирования Turbo Pascal и Borland Pascal, ориентированных на работу с DOS, а также о среде программирования Delphi, предназначенной для разработки приложений, работающих под управлением операционной системы Windows, в пособии не приводится. Отмечены лишь некоторые важные моменты. Учебное пособие содержит примеры, записанные как фрагмент программы или законченная программа. Все примеры оттестированы. Однако авторы хотели бы предостеречь от некритического использования этих программ читателем - большинство из них лишь иллюстрирует возможности языка и не претендует на оптимальность. В пособие включена подборка вариантов задач по основным темам.
1. Общая схема решения задачи на персональном компьютере
В общем виде процесс решения задачи на ПК можно представить в виде последовательности следующих действий:
1) анализ задачи;
2) разработка алгоритма решения задачи;
3) разработка пользовательского интерфейса;
4) написание кода;
5) отладка программы;
6) тестирование программы;
7) составление документации.
Все эти этапы (иногда в неявной форме) обязательно выполняются любым программистом при решении любой задачи. Рассмотрим их подробнее.
На этапе анализа задачи необходимо четко определить постановку задачи, убедиться, что вы ясно ее понимаете; определиться с набором входных и выходных данных.
Под алгоритмом понимают понятное и точное предписание исполнителю выполнить последовательность действий, направленных на достижение поставленной цели. Обязательной составной частью алгоритма является определение зависимости между входной и выходной информацией. При решении некоторых наиболее тривиальных задач может показаться, что этап разработки алгоритма отсутствует, однако это означает лишь, что вы пользуетесь уже известным вам алгоритмом. Для разработки алгоритмов существует два наиболее популярных инструмента – это блок-схема и псевдокод. Блок-схема представляет собой диаграмму, на которой изображена последовательность выполняемых компьютером определенных действий. Различные геометрические фигуры представляют на блок-схеме различные типы процессов. Псевдокод – это текст программы, содержащий как операторы языка программирования, так и фразы на удобном для пользователя языке (английском, русском и т.д.). Ниже при помощи блок-схем будут рассмотрены основные алгоритмические структуры.
Этап разработки пользовательского интерфейса предполагает проработку такого вопроса, как определение вами той информации, которую пользователь будет видеть на экране. То есть, как и в каком формате пользователь будет вводить данные, какие дополнительные к основным результирующим данным он может получить в итоге и т.д.
На этапе написания кода вы записываете алгоритм на языке программирования. Один и тот же алгоритм можно запрограммировать множеством различных способов, но вы должны стремиться написать оптимальную программу. Хорошо написанная программа, как правило, содержит меньше ошибок и гораздо быстрее отлаживается.
Этап отладки включает в себя трансляцию программы и проверку ее на простейших тестах. Трансляция программы - это процесс перевода ее с языка программирования на машинный язык, его осуществляет специальная программа - транслятор. В зависимости от порядка перевода и выполнения команд все трансляторы делят на два типа: компиляторы и интерпретаторы. Компилятор - это транслятор, преобразующий исходный код языка в машинный код и создающий таким образом выполнимый файл. Интерпретатор, в свою очередь, преобразует исходный код в машинный шаг за шагом, т.е. каждая команда преобразуется интерпретатором и сразу выполняется, затем интерпретатор преобразует следующую команду. Язык Pascal является компилируемым. При трансляции вы постепенно исправляете допущенные при написании программы синтаксические ошибки, следите за сообщениями транслятора - он указывает, какая обнаружена ошибка и где именно. После того, как вы исправите все синтаксические ошибки, и транслятор сообщит об успешном завершении трансляции, будет создан файл с именем, таким же, как у вашего исходного файла, и с расширением exe(от ЕХЕcutive - выполняемый); этот файл содержит программу (в отличие от исходного файла, содержащего лишь текст программы), которая может быть выполнена. Необходимо отчетливо понимать, что задачей транслятора ни в коем случае не является поиск ошибок в ваших программах, он сообщает о них лишь в том случае, когда не может правильно интерпретировать ваш текст. Успешно осуществив трансляцию, запустите свою программу. Не следует думать, что эта программа не содержит ошибок! Все логические ошибки, допущенные вами, остались в программе, и на этапе отладки вы должны найти их и исправить. Не существует никаких общих рецептов для отладки - класс программиста главным образом, как раз и проявляется в том, как он отлаживает программы. Но один полезный совет можно дать: аккуратно и подробно выводите при отладке все вычисляемые вашей программой величины.
После того, как вы решите, что ваша программа работает правильно (обычно это не соответствует действительности), начинайте тестирование - выполняйте программу с различными наборами входных данных, причем они обязательно должны содержать все особые случаи. Когда вы убедитесь, что ваша программа иногда работает правильно, а иногда - нет, возвращайтесь к алгоритму, пересматривайте его и заново повторяйте все этапы. Успешно завершив тестирование, вы можете надеяться, что ваша программа верна.
Следует четко разграничивать два понятия - верная программа и хорошая программа. Всякая хорошая программа верна, но далеко не всякая верная программа хороша - она может использовать неэффективный (или неэффективно запрограммированный) алгоритм, занимать много лишней памяти, быть неряшливо оформленной и т.д. Старайтесь писать не только верные, но и хорошие программы!
Под составлением документации понимается разработка всех материалов, описывающих назначение и принципы работы программы. Документация может быть внутренней и внешней. Внутренняя документация состоит из комментариев, включенных в код программы. С их помощью человек, не знакомый с программой, может понять, как она работает. Внешняя документация содержит техническое задание, блок-схемы, псевдокоды, базовые допущения и описание входных и выходных данных. Для коммерческих программ внешней документацией часто служит руководство пользователя. Главное назначение документации — позволить человеку, не являющемуся разработчиком программы, использовать ее и при необходимости модифицировать ее код.
Схематично полный цикл разработки программы можно представить следующим образом:
Рис.1. Полный цикл разработки программы.
Циклы
Циклы используются в случае, если некоторую группу операторов требуется выполнить многократно.
Пример 5. Подсчитать количество нечетных цифр в записи натурального числа .
Идея решения. Из заданного числа выбирать из младшего разряда цифру за цифрой до тех пор, пока оно не исчерпается, т.е. станет равным нулю. Каждую нечётную цифру учитывать.
блок-схема 1 блок-схема 2 |
Пояснения по блок-схеме 1: 1. Ввести число 2. {подготавливаем счётчик нечётных цифр} 3. Если , переход к пункту 7 4. Если , то 5. 6. Переход к пункту 3 7. Вывод 8. Конец | Пояснения по блок-схеме 2: 1. Ввести число 2. {подготавливаем счётчик нечётных цифр} 3. Если , то 4. 5. Если , переход к пункту 3 6. Вывод 7. Конец |
Задача решена двумя способами. Слева решение оформлено с использованием цикла с предусловием, справа — с постусловием.
Пример 6. Найти произведение первых натуральных чисел, кратных трём.
При составлении алгоритма учтем, что первое натуральное число, кратное 3, есть тройка, а все последующие больше предыдущего на 3.
1. Ввод 2. {накапливаем произведение} 3. {переменная для хранения чисел, кратных 3} 4. 5. Если , переход к пункту 10 6. 7. 8. 9. Перейти к пункту 5 10. Вывод 11. Конец |
Пример 7. Дана последовательность, общий член которой определяется формулой . Вычислить при сумму тех ее членов, которые больше заданного числа .
При решении задачи находится очередной член последовательно и, если он больше , добавляется к сумме.
1. Ввести 2. 3. 4. 5. Сравнить с . Если , переход к пункту 10 6. 7. 8. 9. Переход к пункту 5 10. Вывод 11. Конец |
В примере 5 и в примере 7 количество повторений заранее неизвестно. В первом оно зависит от количества цифр в записи натурального числа, во втором — от числа . В примере 6 количество шагов известно из условия задачи, поэтому проще и предпочтительней использовать цикл с параметром.
Блок-схемы идеально подходят для изучения азов программирования, так как позволяют наглядно и однозначно проследить последовательность выполнения этапов алгоритма. Поэтому на начальном этапе авторы рекомендуют практиковать применение блок-схем. Хотя в настоящее время блок-схемы алгоритмов используются не столь широко, как в начале компьютерной эры. Их популярность резко упала по ряду причин.
• Разработка блок-схемы занимает много времени.
• Блок-схемы имеют большие размеры. Блок-схема даже простой программы может достичь размера в несколько страниц.
• В блок-схеме не отражаются специфические программные конструкции, реализующие, например, цикл или структуру принятия решения.
Наиболее существенной причиной падения популярности блок-схем стало развитие методов структурного программирования. Большие программы делают структурированными, т.е. разбитыми на отдельные модули и подпрограммы. При умелой разбивке структура каждого модуля должна быть достаточно простой, при этом необходимость использования блок-схемы отпадает. Однако иногда разбить программу на простые модули все же не удается, в таких случаях приходится использовать блок-схему программы.
Как видно из названия, псевдокодпредставляет собой "ненастоящий" код. Он состоит из смеси операторов языка высокого уровня и фраз на английском (или русском) языке. Каждый программист пользуется собственными псевдокодами, поэтому никаких стандартов на составление псевдокодов не существует.
Псевдокоды получили широкое распространение как средство облегчения разработки программ. По сравнению с блок-схемами они обладают существенными преимуществами. Их написание не требует много времени. Тексты псевдокодов компактны. С их помощью программист может сконцентрироваться на создании алгоритма, не беспокоясь об увязке всех линий блок-схемы.
Поскольку псевдокод похож на код высокоуровневого языка, его легче преобразовать в настоящий код программы, чем блок-схему. В псевдокоде отражены специфические программные конструкции, которые используются в программе для организации циклов или структур принятия решений.
3. Консольные приложения в Delphi. Введение в язык Object Pascal. Общая структура программы. Идентификаторы, комментарии, пробелы. Раздел описаний и раздел операторов
Для реализации программ, написанных на языке программирования Object Pascal, можно использовать различные системы программирования. Turbo Pascal и Borland Pascal ориентированы на работу с дисковыми операционными системами DOS (такими как MS DOS компании Microsoft или PC DOS компании IBM). Среда программирования Delphi предназначена для разработки программ (или приложений), работающих под управлением операционной системы Windows. Мы рассмотрим возможность создания приложений для DOS в среде Delphi. Это позволит подготовиться к использованию графического интерфейса пользователя (GUI – Graphical User Interface).Такие программы называются консольными приложениями.
Создадим простое консольное приложение. Для этого выполним ряд действий.
1. Выберем команду FileNewOther (ФайлНовыйДругое), выделим пиктограмму Console Application (Консольное приложение) и щелкнем на кнопке ОК. При этом на экране появится окно редактора кода.
2. В окне редактора кода введем следующий текст (некоторые строки вам набирать не придется, они уже будут присутствовать):
program ConsoleExample;
{$APPTYPE CONSOLE}
uses SysUtils;
begin
Writeln ('Hello, World from Delphi!!!');
Writeln ('This is the console application.');
Writeln;
Writeln ('Press <ENTER> to quit.');
Readln;
end.
3. Сохраним программу, выбрав последовательно команды FileSave Project As… Затем нажмем клавишу <F9> - программа выполнится. При этом на экране появляется такое окно DOS:
4. Особо нужно отметить сложности, возникающие при работе с кириллицей в консольных приложениях. Выполним следующую программу:
program ConsoleExample;
{$APPTYPE CONSOLE}
uses SysUtils;
begin
Writeln (‘Привет, Мир!!!');
Writeln ('Это консольное приложение.');
Readln;
end.
на экране увидим следующее
Появление такой «абракадабры» связано с тем, что в компиляторе Delphi используется кодовая страница Windows-1251, а запущенное приложение использует кодовую страницу DOS. В результате этого несоответствия русские буквы отображаются некорректно. Воспользуемся следующим способом для устранения проблемы - используем функцию, которая будет перекодировать кириллицу Windows в DOS перед отображением на экран. Важно отметить, что при наборе фрагментов 'А'..’п' и 'р'..'я' обязательно (!) включать русскую раскладку клавиатуры.
program test;
{$APPTYPE CONSOLE}
function Rus(mes: string):string;
var i: integer;
begin
for i:=1 to length(mes) do
case mes[i] of
'А'..’п' : mes[i] := Chr(Ord(mes[i]) - 64);
'р'..'я' : mes[i] := Chr(Ord(mes[i]) - 16);
end;
rus := mes;
end;
begin
Writeln (Rus('Привет, Мир!!!'));
Writeln (Rus('Это консольное приложение.'));
Readln;
end.
Результат работы программы выглядит гораздо привлекательнее:
Разъяснением содержимого последней программы мы займемся позже, после изучения ряда тем. В последующих программах оговаривать вывод кириллицы не будем, вы можете пользоваться предложенным примером.
Теперь займемся более детальным рассмотрением такого примера:
begin
writeln('Hello !!!');
Readln;
end.
Если вам удастся откомпилировать и запустить эту программу, она выведет на экран сообщение: " Hello !!!". Получения того же сообщения на экране можно добиться, записав программу так:
const Message=' Hello !!!';
begin
writeln(Message); Readln;
end.
и так :
var Message: String[10];
begin Message:=' Hello !!!'; writeln(Message); Readln;
end.
и еще множеством различных способов, но в каждой программе обязательно будет слово begin,и в конце программы всегда будет стоять end.- признак конца программы. Перед BEGINможет что-то быть (как правило, это так), или может не быть ничего. То, что находится перед BEGIN,называется разделом описаний, то, что находится между BEGINи END., называется разделом операторов. Слова BEGIN, END, а также WRITELN, READLNявляются ключевыми словами языка Object Pascal, а слово Message- это идентификатор пользователя, т.е. имя, данное нами некоторому объекту - константе, переменной, или чему-то еще. Все ключевые слова и идентификаторы пользователя есть последовательности букв и цифр, начинающиеся с буквы. Буквами языка являются все латинские буквы и символ подчеркивания. Компилятор не различает большие и малые латинские буквы, поэтому вы можете записывать идентификаторы как захотите: Begin, BEGIN, begin, BeGiNи т.д. – компилятор будет воспринимать их одинаково. Вы можете выбирать любые идентификаторы пользователя, лишь бы они не совпадали с ключевыми словами; так, в нашем примере вместо Messageвы можете написать Qили __t123, или Y56_ertи т.д. Однако все эти идентификаторы не несут в себе никакого смысла, затрудняют чтение и отладку программы и делают ее неряшливой; идентификатор Message имеет то достоинство что из него уже ясно его назначение - содержать некоторое сообщение. Старайтесь всегда использовать в программе осмысленные идентификаторы! Язык Object Pascal допускает идентификаторы длиной до 63 символов (точнее, компилятор различает первые 63 символа имени), поэтому не экономьте на именах переменных и функций, пусть лучше имена будут длинными, но понятными. Кроме ключевых слов и идентификаторов всякая программа содержит также пробелы и (в идеале) комментарии. Комментарии могут быть записаны в фигурных скобках и могут стоять в любом месте программы, пробелы являются разделителями, там, где допустим один пробел, можно поставить любое количество пробелов. Комментарии и пробелы следует использовать для аккуратного оформления текста программы. Хорошая программа обязательно должна быть документирована, т.е. содержать комментарии поясняющие, как она работает.
4. Арифметические типы данных. Числовые константы и переменные. Оператор присваивания. Выражения
В языке Object Pascal определены следующие арифметические типы данных: целочисленные типы - Byte, ShortInt, Word, Integerи LongInt; вещественные типы - Real, Single, Doubleи Extended; и не совсем вещественный тип Comp. Характеристики этих типов приведены в таблице 1 (запись 1.5e-45 означает 1.5 умноженное на 10 в степени -45, это общепринятое в языках программирования обозначение для вещественных чисел - константа с плавающей точкой).
Арифметические типы данныхТаблица 1
Название типа | Диапазон допустимых значений | Количество верных цифр | Размер в байтах |
Byte | 0...255 | - | |
ShortInt | -128...127 | - | |
Word | 0..65535 | - | |
Integer | -32768...32767 | - | |
LongInt | -2147483648...2147483647 | - | |
Single | ±1.5e-45... ±3.4e+38 | 7-8 | |
Real | ±2.9e-39... ±1.7e+38 | 11-12 | |
Double | ±5.0e-324... ±1.7e+308 | 15-16 | |
Extended | ±3.4e-4932... ±1.1e+4932 | 19-20 | |
Comp | -9.2e18...9.2e18 |
Типы Byteи Wordиспользуются для целых величин без знака, типы ShortInt, Integerи LongInt- для целых со знаком, типы Single, Real, Doubleи Extended- для вещественных величин. Тип Compможет содержать только целые числа от -2 63 +1 до +263-1, но эти числа хранятся в вещественном формате, поэтому тип Compсчитается вещественным. С данными типа Comp можно обращаться так же, как с данными других вещественных типов, но дробная часть числа при этом автоматически отбрасывается.
Целые числовые константы записываются в языке Object Pascal в десятичном виде или в 16-ричном виде, 16-ричная константа начинается с символа $и содержит 16-ричные цифры: 0-9,A-F. Например, число 255 можно записать как $FF. Числовые константы по умолчанию имеют тип Integerили LongInt. Вещественные константы записываются либо с фиксированной точкой, например, -1.234, либо с плавающей точкой, например, -1.234E-5или 555е12.
В программе, как правило, приходится использовать переменные арифметических типов. Каждая такая переменная (и переменная любого другого типа) в языке Object Pascal должна быть обязательно описана, т.е. должен быть явно указан ее тип. Описание переменных в общем случае имеет вид:
VARимя_1,... ,имя_n :тип ;
имя_a1,... ,имя_am :тип ;...
Здесь имя - имена разных переменных (идентификаторы), тип - типы переменных, VAR- ключевое слово, означающее, что после него следуют описания переменных. Переменные одного типа можно описать совместно, разделив их имена запятыми, а можно описывать и каждую переменную отдельно. Точка с запятой означает окончание описания переменных данного типа. Слово VARможет повторяться в программе сколько угодно раз. Выбор типа для той или иной переменной определяется назначением этой переменной. Пусть, например, переменная iслужит счетчиком (индексом) элементов некоторой последовательности, причем известно, что количество элементов не может превосходить 100. Мы можем описать переменную iлюбым целочисленным типом, но правильный выбор - Byteили ShortInt, любой другой тип будет избыточным. Всегда следует выбирать типы переменных осознанно; если вы не понимаете, какой тип должна иметь ваша переменная, вероятнее всего, эта переменная в программе не нужна. Но при этом важно быть уверенным, что значение переменной не выйдет за рамки диапазона данного типа переменных. Для вещественных переменных чаще всего используется тип Singleили Extended.
Пусть в программе нам необходимы переменные b1,b2,b3,b4типа Byte, переменные i,j,kтипа Integerи переменные r1,r2типа Single. Их можно описать, например, двумя эквивалентными способами:
var b1,b2,b3,b4 : Byte;
i,j,k : Integer;
r1,r2 : Single;
или так :
var b : Byte;
i,j,k Integer;
var r1: Single;
var b2,b3,b4: Byte;
r2: Single;
Всякая переменная обладает четырьмя атрибутами: именем, типом, адресом и значением. Имя переменной есть идентификатор, т.е. последовательность символов; тип переменной определяет ее свойства, диапазон допустимых значений и размер памяти, необходимый для размещения этой переменной; адрес переменной указывает на место в памяти, где размещается ее значение; переменная всегда имеет некоторое значение, даже если вы ничего не сделали, чтобы определить это значение. В последнем случае говорят, что переменная не определена; это значит, что ее значение не известно нам заранее (ни в коем случае не следует думать, что неопределенные переменные имеют нулевые значения - это не так).
Каким же образом определить значение переменной? Для этого используется оператор присваивания:
имя := выражение;
Здесь мы встречаемся с двумя новыми понятиями - оператор и выражение. Оператор - это минимальная осмысленная конструкция в языке Object Pascal, вся программа - это последовательность операторов. Оператор всегда заканчивается символом ";", кроме одного единственного оператора END.Допускаются пустые операторы ";", не выполняющие никаких действий. Выражение - это конструкция, состоящая из одного или нескольких операндов и, возможно, знаков операций, и имеющая некоторое значение. Операндами могут быть константы, переменные и другие выражения, т.е. можно строить сколь угодно сложные выражения. Мы не знаем пока никаких знаков операций, но предположим, что знак +означает операцию сложения (это так и есть). Запишем несколько выражений:
1(константа есть частный случай выражения);
b1(переменная есть частный случай выражения);
25+1E3 b1+4.25+r2
Теперь мы можем присвоить переменной ее значение:
i:=-11; j:=22+i; k:=i+j+177;
Наряду с переменными в Паскале есть и другие именованные объекты - это константы (отличайте их от числовых констант, которые не имеют имени, а лишь значение). Константы бывают двух видов - нетипизированные и типизированные. Нетипизированные константы описываются, так же, как и переменные в разделе описаний, в виде:
const имя=значение; имя=значение; ...
Здесь имя - идентификатор, значение - вообще говоря, некоторое выражение, которое может включать и именованные константы, описанные выше, но только не переменные. Запишем несколько примеров:
const c=-155;
d=c+100;
const f=d+1;
const g=c+f;
Нетипизированные константы, описанные в разделе описаний, вы можете затем использовать в разделе операторов в выражениях, но изменить их значения невозможно. Не совсем удачное название "нетипизированные" означает не отсутствие у констант типа - любая константа имеет совершенно определенный тип, который определяется ее значением, - а лишь то обстоятельство, что при описании таких констант тип не указывается явно. Второй класс именованных констант - типизированные константы, описание которых имеет вид:
const имя:тип=значение; имя:тип=значение; ...
С этим классом констант мы работать не будем, поэтому подробное описание опускаем.
5. Ввод-вывод данных в Паскале
Для ввода-вывода данных в Паскале используются стандартные процедуры ввода-вывода, которые иногда не совсем верно называют операторами ввода-вывода. Понятие процедур и функции будет рассмотрено позднее, пока же мы просто познакомимся с особенностями их организации.
Простейшая процедура ввода в Паскале - процедура READ, она записывается в виде:
read(имя_1,имя_2,...);
где имя - имена переменных или типизированных констант. Вводимые значения задаются в виде допустимых в Паскале констант и разделяются любым количеством пробелов. Для окончания ввода следует нажать клавишу Enter. Процедуру ввода можно записать и как READLN, при вводе числовых переменных они эквивалентны. Кроме того, READLNбез списка в скобках можно использовать для организации задержки в работе программы - программа будет переходить в режим ожидания нажатия любой клавиши.
Простейшая процедура вывода записывается в виде:
write(выражение_1, выражение_2, ...);
или
writeln(выражение_1, выражение_2, ...);
Вывести можно любое выражение, если необходимо вывести текст, он заключается в апострофы. Процедура WRITELNотличается от процедуры WRITEтем, что после вывода происходит переход на новую строку. Можно использовать процедуру WRITELNбез списка вывода для пропуска строки. Запишем пример программы, осуществляющей ввод и вывод:
var i : integer;
w : word;
r : single;
begin
writeln; { ------------- ввод ------------- }
write('Введите целое число ');
read(i);
writeln;
write('Введите натуральное число ');
read(w);
writeln;
write('Введите вещественное число ');
read(r);
writeln; { ------------- вывод ------------- }
writeln('Вы ввели : ',i,' ',w,' ',r,' их сумма=',i+w+r); writeln('Нажмите Enter для выхода');
readln;
readln;
end.
Впервые записав осмысленную программу, остановимся и обсудим ее внешний вид. Даже на таком тривиальном примере мы можем понять некоторые основные правила оформления программы.
1. Организация диалога с пользователем. Прежде чем записать оператор READ,вы обязаны записать хотя бы один WRITE, который выведет на экран приглашение "Введите ...", причем из этого приглашения пользователь должен понять, какие именно данные ему следует ввести. Так, в нашем примере операторы write('Введите i '); read(i); были бы неуместны, так как пользователю неизвестно, что такое i, и он мог бы ввести, например, вещественное число, что привело бы к аварийному завершению программы.
2. Оформление текста программы. Хорошо оформленная программа легко читается и быстрее отлаживается, следует стремиться к "прозрачности" текста, но не к некоторой, вполне субъективной, "красоте". Так, скажем, операторы, выполняющиеся последовательно, следует и записывать строго друг под другом, но не "елочкой" или какой-либо другой фигурой. Средства, используемые для оформления текста, крайне просты и доступны всякому - это пробелы, пустые строки и комментарии.
3. При выводе чисел можно их форматировать, т.е. управлять формой их представления. Для этого в списке вывода после выводимого выражения можно указывать модификаторы: “:L:d“ - для вещественных значений и “:L” для вещественных и целых. L и d - целочисленные выражения, первое из них определяет, сколько всего позиций отводится для выводимого числа на экране, а второе - сколько выводится цифр после десятичной точки. Если при выводе вещественного числа задан модификатор “:L:d“, то оно выводится с фиксированной точкой, если же задан модификатор “:L” или он отсутствует - то с плавающей точкой. Пусть значение переменной Xравно 123.45678, тогда оператор
write(x); выведет " 1.2345678000E+02"
write(x:8:2); выведет " 123.46"
write(x:10:5); выведет " 1.235E+02"
write(x:10); выведет " 1.235E+02"
write(x:8); выведет " 1.2E+02"
write(x:1); выведет " 1.2E+02"
По умолчанию вещественные числа всегда разделяются при выводе пробелами, но если вы выводите подряд несколько целых чисел, не форматируя их и не выводя между ними пробелов, они будут выводиться подряд и сольются в одно число.
6. Арифметические операции. Стандартные математические функции
Для арифметических данных, т.е. для числовых констант, переменных и числовых функций определены шесть арифметических операций:
+сложение
- вычитание
*умножение
/вещественное деление
divцелая часть от деления
modостаток от деления
Первые четыре операции определены для любых операндов - как целых, так и вещественных, причем результат операции "/" всегда вещественное число, даже если оба операнда целые. Операции DIVи MODопределены только для целых операндов. Кроме того, выделяют унарную операцию "-", которая применяется не к двум, а к одному операнду, например: -x.
Вообще говоря, язык Object Pascal запрещает использовать в одном выражении разнотипные операнды, однако для арифметических данных сделано исключение. Перед выполнением арифметической операции один или оба операнда автоматически приводятся к одному типу, а затем уже подставляются в выражение. Значение любого выражения всегда имеет определенный тип - такой же, как у операндов после приведения их к одному типу. Правила преобразования целочисленных типов приведены в таблице 2.
Правила преобразования типов | Таблица 2 | ||||
Операнды | Byte | ShortInt | Word | Integer | LongInt |
Byte ShortInt Word Integer LongInt | Integer Integer Word Integer LongInt | Integer Integer LongInt Integer LongInt | Word LongInt Word LongInt LongInt | Integer Integer LongInt Integer LongInt | LongInt LongInt LongInt LongInt LongInt |
Если один операнд выражения имеет целочисленный тип, а второй - вещественный, то первый автоматически приводится к вещественному типу и значение выражения будет вещественным. Целые значения можно присваивать вещественной переменной, но вещественные значения присвоить целой переменной нельзя! Присваивая значение целочисленной переменной и константе, вы должны следить, чтобы это значение не выходило за пределы диапазона допустимых значений переменной. В языке Object Pascal есть возможность явно преобразовать целочисленное значение к любому из целочисленных типов, для этого используются стандартные функции с именами Byte, ShortInt, Word, Integerи LongInt. Например, преобразуем переменную типа Wordк типу Integer:
var x : word;
begin
x:=300;writeln(x,' ',integer(x));
x:=65535;writeln(x,' ',integer(x));
end.
Программа выведет:
300 300
65535 -1
В первом случае преобразование происходит корректно, а во втором - с изменением значения.
Арифметическое выражение может содержать любое количество операндов и, соответственно, любое количество операций, которые выполняются в последовательности, определенной их приоритетом; приоритет операций *, /, DIV, MODвыше, чем операций +и -. Операции одного приоритета выполняются слева направо. Чтобы изменить порядок выполнения операций, вы можете использовать в выражении круглые скобки. Вычислим, например, частное от деления Xна сумму A,B и C: X/(A+B+C);
Набор встроенных математических функций в языке Object Pascal невелик, он включает :
1. Abs(x) - абсолютная величина числа.
2. Int(x) - целая часть вещественного числа.
3. Frac(x) - дробная часть вещественного числа.
4. Trunc(x) - целая часть вещественного числа, преобразованная к типу LongInt.
5. Round(x) - округленное до целого вещественное число, преобразованное к типу LongInt.
6. Sqr(x) - квадрат числа.
7. Sqrt(x) - квадратный корень.
8. Exp(x) - экспонента.
9. Ln(x) - натуральный логарифм.
10. Pi- число пи.
11. Sin(x) - синус.
12. Cos(x) - косинус.
13. Arctan(x) - арктангенс.
Все остальные математические функции можно получить, пользуясь этим основным набором; например: десятичный логарифм - Ln(x)/Ln(10), тангенс -Sin(x)/Cos(x) и т.д. Аргументы функций могут быть любыми арифметическими выражениями и задаются в круглых скобках после имени функции, аргументы функций Sinи Cosвыражаются в радианах. Вычислим квадрат синуса 70 градусов: Sqr(Sin(Pi/180*70))
Кроме перечисленных выше математических функций Object Pascal предоставляет еще несколько полезных числовых функций и процедур разного назначения:
14. High(целый тип) - возвращает наибольшее возможное значение данного типа.
15. Low(целый тип) - возвращает наименьшее возможное значение данного типа.
16. SizeOf(тип)
SizeOf(переменная) - возвращает размер в байтах заданного типа или заданной переменной. Функция SizeOfприменима к любому типу, в том числе и к структурированным типам - массивам, записям и некоторым другим, речь о которых пойдет ниже.
17. Random(Range:Word) - возвращает целое случайное число в диапазоне от 0 до Range-1.
18. Random- возвращает вещественное случайное число в из отрезка [0, 1].
19. Randomize- процедура, инициализирующая генератор случайных чисел, используя текущее системное время
Выведем несколько случайных чисел в диапазоне от 0 до 99:
begin
randomize;
writeln(random(100));
writeln(random(100));
writeln(random(100));
end.
При первом запуске программы она вывела числа 13, 38, 48, при втором запуске - 63, 99, 6, при третьем запуске - 23, 87, 92. Это действие процедуры Randomize - поскольку при каждом запуске системное время, которое отсчитывает операционная система, было различным, мы каждый раз получали различные последовательности случайных чисел. Теперь исключим из программы оператор Randomize;и запустим ее несколько раз - каждый раз мы будем получать тройку чисел 0, 3, 86.
Обратите внимание, что процедура используется в операторе вызова, а функция используется в выражении. Запись Random(100);неверна, поскольку Random- это функция, но также неверна и запись WRITELN(Randomize);. Можно считать, что различие между процедурой и функцией состоит в том, что процедура выполняет некоторую последовательность действий, а функция вычисляет некоторое значение. Заметим, что READи WRITE- это тоже процедуры.
Для работы с внутренним двоичным представлением двухбайтовых целых чисел (типа Wordили Integer) существуют функции:
20. Lo(x) - возвращает младший байт аргумента.
21. Hi(x) - возвращает старший байт аргумента.
22. Swap(x) - меняет местами младший и старший байты.
Сделаем отступление о двоичной системе счисления. Все данные в памяти компьютера хранятся закодированными в двоичной системе. Любая переменная занимает целое число байтов, а каждый байт есть последовательность из 8 двоичных цифр - битов. Например, значение переменной типа Byte, равное 11, хранится как последовательность битов 0000 1011, а если переменная имеет тип Word, то ее значение кодируется как 0000 0000 0000 1101. 1024байта (или 2 в 10-й степени) имеют свое название - 1Кбайт, иногда эту величину также называют килобайт; 1024 Кбайт называют мегабайт. Пусть переменная tтипа Wordимеет значение 40000, или 1001 1100 0100 0000в двоичной системе, тогда функция Lo(t)возвратит 64( = 0100 0000), функция Hi(t)возвратит 156(= 1001 1100) и функция Swap(t)возвратит 16540( = 0100 0000 1001 1100).
Для целочисленных переменных определены процедуры:
23. Inc(x) Inc(x,d)
24. Dec(x) Dec(x,d).
Здесь x - имя переменной, d - любое целочисленное выражение. Процедура Incувеличивает значение переменной на d, а процедура Dec- уменьшает на d; второй аргумент этих процедур можно не задавать, тогда он будет принят равным 1. Например, вместо операторов a:=a+3; b:=b-1; c:=c+a+b; мы могли бы написать Inc(a,3); Dec(b); Inc(c,a+b); , и такой способ записи был бы предпочтительней.
7. Пример выполнения задания
Задача. Вычислить при х = 2.1; у = 0.59; z = -4.8 значения a и b, используя формулы:
; .
Вывести результаты, сопровождая их вывод именами выводимых переменных. Задание выполнить в виде консольного приложения. Повторить задание 1, используя функции из модуля math
Блок-схема алгоритма имеет вид:
Создадим простое консольное приложение. Для этого запустим Delphi и выполним ряд действий. Выберем команду FileNewOther (Файл Новый Другое), выделим пиктограмму Console Application (Консольное приложение) и щелкнем на кнопке ОК. При этом на экране появляется окно редактора кода, в котором введем следующий текст:
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils;
var a,b,c,x,y,z: single;
proba:integer;
function Rus(mes: string):string;
var i: integer;
begin
for i:=1 to length(mes) do
case mes[i] of
'А'..'п' : mes[i] := Chr(Ord(mes[i]) - 64);
'р'..'я' : mes[i] := Chr(Ord(mes[i]) - 16);
end;
rus := mes;
end; { Rus }
begin { program }
writeln(Rus('Введите x, y, z'));
readln (x,y,z);
c:=sin(x*x)/cos(x*x);
a:=y*c*sqr(c)+sqrt(z*z/(y*y+x*x));
b:=ln(y+x*x)+sqr(sin(z/y));
writeln('a=',a:8:3,' b=',b:8:3);
readln;
end. { program}
Сохраним программу, выбрав последовательно команды FileSave Project As… Нажав клавишу <F9>, выполните программу. При этом на экране появляется такое окно работающего приложения.
Перейдем к следующему заданию. В листинг добавляем ссылку на модуль math, что позволяет использовать прямо функцию tan(аргумент) и функцию возведения в степень роwеr(основание, степень).
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils, math;
var a,b,c,x,y,z: single;
proba:integer;
function Rus(mes: string):string;
var i: integer;
begin
for i:=1 to length(mes) do
case mes[i] of
'А'..'п' : mes[i] := Chr(Ord(mes[i]) - 64);
'р'..'я' : mes[i] := Chr(Ord(mes[i]) - 16);
end;
rus := mes;
end; { Rus }
begin { program }
writeln(Rus('Введите x, y, z'));
readln (x,y,z);
c:=tan(x*x);
a:=y*power(c,3)+sqrt(z*z/(y*y+x*x));
b:=ln(y+x*x)+sqr(sin(z/y));
writeln('a=',a:8:3,' b=',b:8:3);
readln;
end. { program}
8. Символьный тип данных
Для хранения символьной информации в Паскале предусмотрен специальный тип данных Char. Допустимы переменные, нетипизированные и типизированные константы такого типа. Данные типа Charзанимают 1 байт памяти. Неименованные символьные константы записываются в программе либо в виде 'символ', либо в виде #номер. Все имеющиеся символы пронумерованы от 0до 255, символы с 0-го по 31-й - невидимые, как правило, они не отображаются на экране, 32-й символ - это пробел.
Некоторые из невидимых символов могут оказаться полезны: символ #8– клавиша BackSpace; символ #10- "конец строки", при выводе он перемещает текущую позицию вывода на одну строку вниз; символ #13-"возврат каретки" - перемещает текущую позицию вывода в начало текущей строки. Клавиша Enterгенерирует два символа - #10и #13.
Символьные данные можно вводить и выводить процедурами READи WRITEпри вводе и выводе символьные значения изображаются без апострофов. Для символьных величин определены функции:
25. Ord(c) - возвращает номер символа.
26. Pred(c) - возвращает символ с номером, меньшим на 1.
27. Succ(c) - возвращает символ с номером, большим на 1.
Эти функции определены не только для символов, но для любого порядкового типа данных. Порядковым типом называется такой тип, все допустимые значения которого можно пронумеровать от 0 до некоторого N (в математике к этому понятию близко понятие счетного множества). Из известных нам типов порядковыми являются все целочисленные типы: Byte, ShortInt, Word, Integer, LongInt. И не являются порядковыми все вещественные типы. Значение функции Ordот числового аргумента равно самому этому аргументу, Pred(x) дает значение x-1, а Succ(x) - значение x+1. Функция
28. Chr(n) - в некотором смысле обратная функции Ord: для заданного числового аргумента n она возвращает символ с соответствующим номером. Для символьных переменных (так же, как и для любых переменных порядкового типа) определены процедуры Incи Dec. Еще одна специфически символьная функция:
29. UpCase(c) - преобразует значение аргумента, если это маленькая латинская буква, в соответствующую заглавную букву. К сожалению, функция не работает для русских букв.
Напишем простую программу, обрабатывающую символьные величины.
var c : char; n : byte;
const space =' ';
begin write('введите какой-нибудь символ '); read(c);
writeln('вы ввели символ',space,c,space,'его номер=',ord(c)); writeln('соседние с ним символы :',space,pred(c),space,
'и',space,succ(c));
writeln('upcase(',c,')=',upcase(c));
writeln;
write('теперь введите число от 33 до 255 '); read(n); writeln('символ с номером ',n,' - это ',space,chr(n),space); writeln;
readln
end.
9. Логический тип данных. Операции сравнения. Логические операции. Битовые операции
Логические, или булевские, данные предназначены для хранения логических значений "истина" или "ложь". Логические переменные и константы имеют тип Booleanи занимают в памяти 1 байт. Существует всего две логические константы - TRUEи FALSE, истина и ложь. Тип Boolean- это порядковый тип, поэтому для него определены функции Ord, Pred, Succи процедуры Incи Dec, причем Ord(FALSE)=0, Ord(TRUE)=1. Прежде чем перейти к логическим операциям, рассмотрим операции сравнения, которых в Паскале существует шесть:
=равно; | <>не равно; |
<меньше; | <=меньше или равно; |
>больше; | >=больше или равно. |
Операции сравнения определены для любых однотипных операндов (числовых, символьных, логических); для числовых данных, так же, как и в случае арифметических операций, сделано исключение - вы можете сравнивать два числовых выражения любых типов, но сравнивать число и символ, число и логическую величину, символ и логическую величину нельзя! Результат операции сравнения есть TRUEили FALSE, в зависимости от того, выполнено или не выполнено условие. Числа сравниваются между собой естественным образом, символы - в соответствии с их номерами, а для логических величин справедливо неравенство FALSE<TRUE. Логических, или булевских, операций в Паскале четыре:
NOT- логическое отрицание;
AND- логическое "и";
OR- логическое "или";
XOR- логическое исключающее "или".
Правила выполнения этих операций таковы :
NOT- унарная (т.е. применимая к одному операнду) операция:
NOT FALSE= TRUE, NOT TRUE= FALSE.
Правила выполнения бинарных операций AND, ORи XORприведены в таблице 3.
Правила выполнения бинарных операцийТаблица 3
Операнд | Результат операции | |||
a | b | a AND b | a OR b | a XOR b |
false false true true | false true false true | false false false true | false true true true | false true true false |
Приоритет операции NOT(как и всякой унарной операции) наивысший, следующий приоритет у операции AND, и самый низкий приоритет - у операций ORи XOR. Выражения могут содержать не только разные логические операции, но и операции сравнения и арифметические, поэтому отметим, что приоритет логических и арифметических операций выше, чем операций сравнения. Существует функция, определенная для целочисленных аргументов и имеющая логическое значение, - это функция
30. Odd(x). Она возвращает TRUE, если значение x нечетное, и FALSE, если оно четное.
Логические значения можно выводить процедурой WRITE, но вводить логические переменные процедурой READнельзя. Теперь попробуем записать программу, использующую логические данные.
var a,b,c,d : integer;
begin writeln('введите 4 целых числа, a,b,c и d, среди ',
'которых должно быть 2 и только 2 одинаковых!'); write('a='); read(a); writeln;
write('b='); read(b); writeln;
write('c='); read(c); writeln;
write('d='); read(d); writeln;
writeln('вашу понятливость можно оценить как ',
(a=b)and(a<>c)and(a<>d)and(c<>d)or
(a=c)and(a<>b)and(a<>d)and(b<>d)or
(a=d)and(a<>b)and(a<>c)and(b<>c)or
(b=c)and(b<>a)and(b<>d)and(a<>d)or
(b=d)and(b<>a)and(b<>c)and(a<>c)or
(c=d)and(c<>a)and(c<>b)and(a<>b));
readln;
end.
Программа выведет TRUE, если введенные данные удовлетворили условию, и FALSE- в противном случае.
10. Условный оператор. Блок. Оператор выбора
Условный оператор в Паскале записывается в виде:
IFлогическое выражение
THENоператор/блок
[ELSEоператор/блок]
логическое выражение - это любое выражение, значение которого имеет тип Boolean, блок - это последовательность операторов, заключенная в логические скобки: BEGINоператоры END;. В условном операторе перед ELSEникогда не ставится ";" ! Перед ENDв большинстве случаев можно не ставить ";". Если значение логического выражения TRUE, то выполняется оператор или блок, стоящий после THEN, в противном случае - оператор или блок, стоящий после ELSE. Конструкция ELSEнеобязательна, условный оператор можно использовать и в усеченном виде, тогда при значении логического выражения FALSEне выполняется никаких действий. Операторы, входящие в условный оператор, сами могут быть условными, т.е. допускается любая вложенность условных операторов. Запишем теперь предыдущую задачу о четырех числах, используя оператор IF:
var a,b,c,d : integer;
begin writeln('Введите 4 целых числа, a,b,c и d, среди ',
'которых должно быть 2 и только 2 одинаковых!');
write('a='); read(a); writeln; write('b='); read(b); writeln;
write('c='); read(c); writeln; write('d='); read(d); writeln;
if (a=b)and(a<>c)and(a<>d)and(c<>d)
or(a=c)and(a<>b)and(a<>d)and(b<>d)or
(a=d)and(a<>b)and(a<>c)and(b<>c)or
(b=c)and(b<>a)and(b<>d)and(a<>d)or
(b=d)and(b<>a)and(b<>c)and(a<>c)or
(c=d)and(c<>a)and(c<>b)and(a<>b)
then
writeln('вы довольно понятливы')
else
writeln('вы ошиблись !!!');
readln;
end.
Можно решить эту задачу и другим способом :
var a,b,c,d : integer;
const num : byte = 0;
begin writeln('введите 4 целых числа, a,b,c и d, среди ',
'которых должно быть 2 и только 2 одинаковых!');
write('a='); read(a); writeln; write('b='); read(b); writeln;
write('c='); read(c); writeln; write('d='); read(d); writeln;
if a=b then inc(num);
if a=c then inc(num);
if a=d then inc(num);
if b=c then inc(num);
if b=d then inc(num);
if c=d then inc(num);
if num=1
then writeln('вы довольно понятливы')
else writeln('вы ошиблись !!!');
readln;
end.
Теперь попробуем записать условный оператор, реализующий более сложную логическую структуру. Пусть даны три числа d, mи y, содержащие число, месяц и год для некоторой даты; необходимо выяснить, правильна ли эта дата.
var d,m : byte;
y : word;
valid : boolean;
begin write('введите дату '); read(d,m,y);
if (m=1)or(m=3)or(m=5)or(m=7)
or(m=8)or(m=10)or(m=12)
then
if (d>=1)and(d<=31)
then valid:=true
else valid:=false
else
if (m=4)or(m=6)or(m=9)or(m=11)
then
if (d>=1)and(d<=30)
then valid:=true
else valid:=false
else
if m=2
then
if (d>=1)and(d<=28)
then valid:=true
else
if d=29
then
if (y mod 4=0)and
(y mod 100>0) or
(y mod 400=0)
then valid:=true
else valid:=false
else valid:=false
else valid:=false;
if valid
then writeln('дата верна')
else writeln('дата неверна');
end.
Оператор выбора во многих случаях удобнее, чем условный оператор, он записывается в виде:
FORпеременная:=начальное значение TOконечное значение DO
оператор/блок
или
STRING
или
STRING [максимальная длина ]
Если максимальная длина не задана, то по умолчанию она берется равной 255. Максимальная длина при описании строковых данных задается целочисленным константным выражением и никогда не может превышать 255. Это ограничение обусловлено самой структурой типа STRING: фактически строка - это массив ARRAY [Byte] OF Char, причем в 0-м символе закодирована текущая длина строки. Строковые переменные могут иметь любую длину от 0 до максимальной. В программе строки можно использовать и как единый структурированный объект (чуть позже мы познакомимся с разнообразными возможностями обработки строк), и как массив символов, т.е. обращаться к элементам строк следует так же, как к элементам массивов. Для строк определены следующие операции:
- строке можно присвоить строку;
- строки можно вводить процедурой READLN;
- строки можно выводить процедурой WRITE[LN];
- для строк определена операция конкатенации +, при этом вторая строка дописывается справа к первой и длина результата становится равной сумме длин операндов (если она не превосходит 255).
Запишем программу, выполняющую простейшие операции со строками:
type ShortString = string[80];
var s1,s2 : ShortString;
s,s3 : string;
begin
writeln(Rus('Введите 1-ю строку ')); readln(s1);
writeln(Rus(' Введите 2- ю строку ')); readln(s2);
writeln(Rus('Вы ввели '),s1,' & ',s2);
writeln(Rus('s1+s2='),s1+s2);
s3:=s1+s1+s1;
writeln(Rus('Строка s1,повторенная 3 раза '),s3); readln
end.
Обратите внимание, что при вводе строк всегда используется READLN, но не READ. Процедура READв отличие от READLNсчитывает лишь символы до символа конца строки (клавиша Enter), который остается в буфере клавиатуры. Таким образом, пользуясь процедурой READможно ввести только одну строку; все строки, вводимые вслед за первой, станут пустыми. Запишем теперь программу, которая вводит некоторую строку, заменяет в ней все цифры на пробелы и дописывает в конец строки символы "???":
var s : string;
l,i : byte;
begin write('введите строку '); readln(s);
l:=ord(s[0]);
for i:=1 to l do if s[i] in ['0'..'9'] then s[i]:=' ';
for i:=l+1 to l+3 do s[i]:='?';
writeln(Rus( 'вот что получилось : '),s); readln
end.
Наша программа заменила цифры, но никаких трех знаков вопроса не добавила. Дело в том, что, обращаясь к элементам строки, невозможно изменить текущую длину строки. Второй цикл нашей программы сработал правильно, записав символы "?" в соответствующие элементы строки, но длина строки осталась прежней, и процедура WRITELNвывела только символы с 1-го по L-й. Чтобы решить задачу корректно, мы могли бы добавить в программу один оператор INC(s[0],3); но, конечно, лучше всего просто записать: s:=s+'???';
Для обработки строк в Паскале существует несколько стандартных функций и процедур :
1. FUNCTION Length(S: String): Integer; - возвращает длину строки.
2. FUNCTION Concat(S1[,S2,...,Sn]: String): String; - возвращает строку, полученную сцеплением аргументов S1[,S2,...,Sn], может использоваться вместо операции "+".
3. FUNCTION Pos(Substr: String; S: String): Byte; - возвращает номер первого слева символа строки S, начиная с которого строка Substr входит в S, если Substr не входит в S, то значение функции равно 0.
4. FUNCTION Copy(S: String; Index: Integer; Count: Integer): String; - возвращает подстроку строки S, которая начинается с символа с номером Index и имеет длину Count.
5. PROCEDURE Delete(VARS: String; Index: Integer; Count:Integer); - удаляет из строки S подстроку, начинающуюся с символа с номером Index и имеющую длину Count.
6. PROCEDURE Insert(Substr: String; VARS: String; Index: Integer); -вставляет в строку S подстроку Substr начиная с символа с номером Index.
Еще две стандартные процедуры предназначены для перевода строки в число и числа в строку:
7. PROCEDURE Val(S: STRING;VARV; VARCode: Integer); - преобразует строку S в число V (если это возможно); V - любая переменная арифметического типа, переменная Code возвращает 0, если преобразование прошло успешно, или номер первого неправильного символа строки.
8. PROCEDURE Str(X [:Width [:Decimals ]];VARS:STRING); - преобразует произвольное арифметическое выражение X в строку S, параметры Width и Decimals позволяют форматировать строку и имеют такой же смысл, как и в процедуре WRITE[LN] .
Теперь, зная процедуру Val, вы можете организовать надежный ввод числовых данных в любой своей программе. Предположим, что программа должна вводить вещественное значение F. Мы можем записать это так:
var f : single; ...
begin write('введите f '); read(f); …
Если пользователь правильно введет число, то все будет в порядке, но если он ошибочно или преднамеренно нажмет не ту клавишу (например, запятую вместо точки и т.п.), то произойдет аварийное прерывание программы. Программы, таким образом, реагирующие на неверный ввод, нельзя назвать хорошими. Хорошая программа обязана обрабатывать нажатие практически любых клавиш в любых комбинациях. Мы можем предложить следующий вариант:
var f : single;
s : string;
code : integer; ...
begin repeat
write('введите f '); readln(s);
val(s,f,code);
if code=0 then break;
writeln('ошибка ввода!');
until false;
Решим часто встречающуюся задачу о распаковке текста: дана строка, содержащая текст на английском языке; нужно выделить слова, содержащиеся в этом тексте. Хотя эта задача и элементарна, ее решение не столь тривиально и требует предварительной разработки алгоритма. Сначала уясним, что такое текст. Текстом будем называть последовательность слов, разделенных любым количеством "разделителей". Слова - это последовательности букв языка (в нашем случае - английских букв), "разделители" - любые символы, не являющиеся буквами. Итак, наш текст в общем случае имеет вид : *X*X...*X*,где X- слово, *- "разделитель". Можно предложить следующий алгоритм распаковки:
1) удалим завершающие пробелы, после чего текст примет регулярный вид *X*X...*X*;
2) удалим лидирующие пробелы;
3) выделим первое слово и удалим его из текста.
После выполнения пунктов 2 и 3 мы получили одно слово и текст стал короче на одно слово, сохранив при этом свою структуру. Очевидно, что пункты 2 и 3 следует выполнять до тех пор, пока текст не пуст. Запишем программу, реализующую этот алгоритм.
var s : string;
i : byte;
const letters : set of char = ['a'..'z','A'..'Z'];
begin writeln(Rus('введите текст ')); readln(s);
{ удалим завершающие пробелы, здесь есть 1 ошибка! }
while not(s[length(s)] in letters) do
delete(s,length(s),1);
writeln(Rus('слова текста :'));
{ организуем цикл по словам }
while s<>'' do
begin
{ удалим лидирующие пробелы }
while not(s[1] in letters) do delete(s,1,1);
{ найдем границу первого слова, здесь есть 1 ошибка! } i:=1;
while s[i] in letters do inc(i); { i - номер первого пробела } dec(i);
writeln(copy(s,1,i)); { выведем слово }
delete(s,1,i); { удалим слово из текста }
end;
readln
end.
На первый взгляд наша программа работает правильно (мы ввели текст латиницей и получили все слова из него), но тестирование программы обязательно должно включать все предельные, или особенные, случаи. Введем, например, строку, не содержащую никаких слов, и программа сработает неправильно: она либо зациклится, либо пользователь не получит никакого сообщения - все завершится просто сворачиванием окна вывода. Это результат ошибки в первом цикле: если в тексте нет букв, все символы из него будут удалены, длина строки станет равной нулю, и в дальнейшем станет проверяться символ с номером 0, который равен #0и, естественно, не является буквой. Еще одна ошибка подобного рода может произойти при выделении последнего слова: мы увеличиваем индекс i, пока i-й символ - буква, и, в конце концов, дойдем до конца строки. Но переменная sвсегда содержит 255 символов, символы с номерами Length(s)+1, Length(s)+2и т.д. существуют, и нет никаких гарантий, что они не являются английскими буквами. В этом случае мы можем получить последнее слово с "хвостом". Исправим нашу программу:
var s : string; i : Byte;
const Letters : set of Char = ['a'..'z','A'..'Z'];
begin
writeln(Rus('Введите текст латиницей')); readln(s);
while not(s[Length(s)] in Letters)and(s<>'') do
Delete(s,Length(s),1);
if s=''
then
begin
writeln(Rus('текст не введен'));
Halt;
end;
writeln(Rus('Слова текста :'));
while s<>'' do {цикл выделения отдельных слов}
begin
while not(s[1] in Letters) do
Delete(s,1,1);
i:=1;
while (s[i] in Letters) and (i<=Length(s)) do
inc(i);
Dec(i);
writeln(Copy(s,1,i));
Delete(s,1,i);
end;
readln;
end.
Теперь запишем то же самое, используя функции и процедуры :
var s : string;
i : byte;
const letters : set of char = ['a'..'z','A'..'Z'];
{процедура удаления завершающих пробелов}
procedure del_tail(var s:string);
begin
while not(s[length(s)] in letters)and(s<>'') do
delete(s,length(s),1);
end; {del_tail}
{процедура удаления лидирующих пробелов}
procedure del_head(var s:string);
begin
while not(s[1] in letters) do
delete(s,1,1);
end; {del_head}
{функция выделения отдельного слова}
function makeword(s:string; var bound:byte):string;
begin bound:=1;
while (s[bound] in letters)and(bound<=length(s)) do
inc(bound);
dec(bound);
makeword:=copy(s,1,i);
end; {makeword}
begin writeln(Rus('введите текст ')); readln(s);
del_tail(s);
if s='' then
begin writeln(Rus('текст не введен'));
halt;
end;
writeln(Rus('слова текста :'));
while s<>'' do { организуем цикл по словам }
begin
del_head(s);
writeln(makeword(s,i));
delete(s,1,i);{ удаление слова из текста }
end; readln
end.
18. Погрешности при вычислениях
В отличие от целочисленных выражений, которые всегда вычисляются точно, вещественные выражения дают приближенный результат, и вещественные переменные содержат приближенные значения. Например, выполним программу
var x : single;
begin x:=1/3;
writeln(x*3-1 :15:10); readln
end.
Мы получим не 0 (точное значение выводимого выражения), а, например, 0.0000000298, а может быть, какое-нибудь другое маленькое число. Это обусловлено тем, что переменные типа Singleхранят конечное число десятичных цифр (11-12 цифр), кроме того, эти цифры хранятся в двоичном коде, поэтому мы и не получили 1E-12или 1E-13. Таким образом, x/a*aдалеко не всегда равно x. И наоборот, a+xможет быть равно a, даже если xне равно нулю. Найдем такое положительное число, которое удовлетворяет уравнению x+1=1:
const x:single;
begin x:=1;
while x+1<>1 do
x:=x/2;
writeln(x); readln
end.
Мы получим, например, 5.42E-20(результат зависит от типа компьютера).
Решим реальную задачу, в которой используются приближенные вычисления: вычислить сумму ряда . Несмотря на то, что необходимо просуммировать бесконечное число слагаемых, эта задача легко решается за конечное время, так как общий член ряда быстро убывает и, начиная с некоторого n,прибавление очередного слагаемого уже не будет изменять сумму. Сначала напишем плохую программу:
function factorial(n:word):single;
var i:word; f:single;
begin f:=1;
for i:=1 to n do f:=f*i;
factorial:=f;
end; { factorial }
function power(x:single; n:word):single;
var i:word; f:single;
begin if n=0
then power:=1
else begin f:=x;
for i:=2 to n do f:=f*x;
power:=f;
end;
end;{ power}
var x,s1,s2 : single;
i : word;
begin writeln('введите x '); readln(x);
s2:=0; i:=0;
repeat
s1:=s2;
s2:=s1+power(x,i)/factorial(i);
inc(i);
until s1=s2;
writeln('сумма ряда = ',s1); readln
end.
Запустим эту программу, задав x=1; мы получим верный результат 2.71828... (его легко проверить, поскольку сумма нашего ряда равна exp(x)). А теперь попытаемся поочередно запускать программу для x=10, 11, 12, 13… И для какого-то х результат получен не будет. В данном случае это переполнение, оно происходит всякий раз, когда вещественная величина превышает максимально допустимое значение 1.7E38. Следовательно, для некоторого iмы уже не можем вычислить i!.
Означает ли это, что решить задачу невозможно? Вовсе нет; конечно, мы не можем задать нашей программе очень большое значение x, но значение 10вполне приемлемо, дело здесь в качестве нашей программы. Действительно, посмотрим, как работает программа: для вычисляется x0 и 0!, затем для i=1 заново вычисляется x1 и 1! и т.д. до получения результата; но xi+1=xxi и (i+1)!=(i+1)i!, так что, зная предыдущие значения, достаточно выполнить всего одну операцию, чтобы получить последующие. Более того, нам вовсе не нужен факториал сам по себе, а только общий член ряда (в котором этот факториал находится в знаменателе). Нетрудно записать рекуррентную формулу для общего члена ряда: , , откуда .Кроме того, что таким образом мы избавимся от переполнения, пользуясь этой формулой, мы еще и увеличим скорость нашей программы.
var x,s1,s2,a : single;
i : word;
begin i:=0;
writeln(Rus('введите x )'); readln(x);
a:=1; s2:=0;
repeat s1:=s2;
s2:=s1+a;
inc(i);
a:=a*x/i;
until s1=s2;
writeln(Rus('сумма ряда = '),s1); readln
end.
Программа сработала для x=10и x=20и x=50, но для x=100снова произошло переполнение. Но здесь уже ничего сделать нельзя, exp(100)>1043 и никак не может быть представлена вещественным значением типа Single.
Решим еще одну задачу: найти корень уравнения f(x)=0методом бисекции или половинного деления. Метод бисекции заключается в следующем: пусть уравнение имеет единственный корень на отрезке [a,b] - это значит, что график функции один раз пересекает ось абсциссна этом отрезке. Определим знак функции в точке a и в точке x=(a+b)/2. Если эти знаки одинаковы, то корень лежит на отрезке [x,b], в противном случае - на отрезке [a,x]. Таким образом, за один шаг метода мы ровно вдвое уменьшили наш отрезок; будем повторять эти операции до тех пор, пока отрезок не станет очень маленьким, и в качестве корня возьмем середину этого маленького отрезка. Попробуем реализовать этот метод:
var a, b, epsilon, x, fa, fx: single;
function f(x:single):single;
begin f:=exp(x)-2;
end; {f}
begin epsilon:=1e-10; a:=0; b:=10;
fa:=f(a);
while b-a>epsilon do
begin x:=(a+b)/2;
fx:=f(x);
if fx=0
then begin writeln(x);
halt;
end;
if fa*fx<0
then b:=x
else a:=x;
end;
writeln(Rus('Корень уравнения Exp(x)=2 на отрезке от 0 до 10 равен '),x:10:8);
writeln(Rus('Значение функции в этой точке = '),f(x):10:8);
readln
end.
В результате выполнения программы получим корень х= 0.69314003. Теперь найдем пробелы в программе. Для этого вычислим корень уравнения ln(x)-50=0, a=1, b=1e30 - программа зациклится! Выведем внутри цикла значения aи b: эти числа почти одинаковы и не меняются, но поскольку их порядок 1021, b-aсущественно превосходит наш отрезок. Есть два способа, которыми мы можем исправить положение. Первый заключается в правильном подборе отрезка, но надо понимать, что придется подбирать этот отрезок для каждого нового уравнения, то есть фактически для каждого уравнения писать свою программу. Очевидно, что это бесперспективный путь. Выведем в нашей зацикленной программе не только aи b, но и x, может быть, это поможет нам придумать второй способ: значение x, оказывается, в точности равно b.
Мы могли бы прийти к выводу, что рано или поздно xстанет равным или aили b, рассуждая чисто теоретически. Действительно, на каждом шаге цикла мы уменьшаем отрезок в два раза; если бы мы работали на вещественной оси, то величины aи bстремились бы друг к другу бесконечно, но, поскольку множество вещественных чисел в компьютере дискретно (из-за конечного числа цифр), настанет момент, когда между aи bбольше не будет ни одного числа. После этого выражение (a+b)/2будет давать либо a, либо b. Воспользуемся этим обстоятельством и напишем следующую программу:
var a, b, epsilon, x, fa, fx: single;
function f(x:single):single;
begin f:= Ln(x)-50;
end; {f}
begin a: = 1; b: = 1e30;
fa:=f(a); x:=(a+b)/2;
while (x<>a)and(x<>b) do
begin fx:=f(x);
if fx=0
then begin writeln(x);
halt;
end;
if fa*fx<0
then b:=x
else a:=x;
x:=(a+b)/2;
end;
writeln(x); readln
end.
Программа дала верный результат 5.184705...E21.
Решим еще одну задачу: вычислить значения функции f(x)=ln(1+ln(1+exp(exp(x)))) на отрезке [0,1000]с шагом 5.
var x0, x1, h, x : single;
var i : byte;
function f(x:single):single;
begin f:=ln(1+ln(1+exp(exp(x))));
end; {f}
begin x0:= 0; x1:= 1000; h:= 5;
for i:=0 to round((x1-x0)/h) do
begin
x:=x0+i*h;
writeln('x=',x:4:0,' f(x)=',f(x));
end;
end.
При x=10произошло переполнение. Означает ли это, что задача неразрешима? Нет, мы просто написали плохую программу, скопировав математическую формулу в оператор Паскаля. Посмотрим, в каком месте происходит переполнение - очевидно, при вычислении exp(exp(x)), других возможностей просто не существует. Это значит, что полученное значение exp(exp(x))превосходит 1E38. Посмотрим на аргумент внутреннего логарифма: прибавление единицы к очень большому числу никак не изменит это число, следовательно, этой единицей можно пренебречь. Таким образом, для x≥5наша формула упрощается:
f(x)=ln(1+ln(1+exp(exp(x))))=ln(1+ln(exp(exp(x))))=ln(1+exp(x))
Исправим программу:
function f(x:single):single;
begin if x<5
then f:=ln(1+ln(1+exp(exp(x))))
else f:=ln(1+exp(x));
end; {f}
Сделаем некоторые выводы из вышесказанного. Компьютерные вычисления несколько отличаются от абстрактных математических вычислений. В математике вещественная ось непрерывна (между двумя любыми вещественными числами находится бесконечное множество чисел) - компьютерное множество вещественных чисел дискретно. Математика оперирует с бесконечно большими и бесконечно малыми величинами - компьютерные вещественные числа ограничены сверху и снизу. Математические вычисления точны - компьютерные вычисления приближенны. Вы должны учитывать это, когда программируете какую-либо вычислительную задачу.
19. Файлы. Работа с текстовыми файлами
Научимся работать с внешними файлами: читать из них информацию, записывать информацию в файл, корректировать файлы, создавать новые файлы, переименовывать и уничтожать существующие файлы. Различают три типа файлов: текстовые, типизированные и бинарные. Это различие влияет лишь на способы обращения к файлу, один и тот же файл на диске программа может рассматривать и как текстовый, и как типизированный, и как бинарный. Рассмотрим текстовые файлы.
Для работы с текстовым файлом в программе следует описать файловую переменную типа TEXT:
VARf : TEXTFILE;
которая называется дескриптором файла. В дескрипторе хранится указатель файла, который похож на курсор в текстовом редакторе. Как и курсор, указатель файла обозначает текущую позицию в открытом текстовом файле. В режиме чтения информации из файла указатель файла определяет следующий элемент данных, который будет считан из файла. В режиме записи указатель файла определяет позицию, в которую будет записан следующий элемент данных.
Описав дескриптор файла, необходимо связать или инициализировать файл, т.е. установить связь файловой переменной с файлом на диске процедурой
1. AssignFile(VAR f:TEXT; Name:String),
где Name - правильно построенное имя файла, существующего или вновь создаваемого. Если файл находится не в текущей папке - в той, где хранится ваша программа, в Name должно быть указано полное имя файла, включая имя диска и всех папок.
После этого для доступа к файлу выполняется открытие файла одной из трех процедур:
2. Reset(VAR f:TEXT)- открывает файл для чтения.
3. Rewrite(VAR f:TEXT)- открывает файл для записи.
4. Append(VAR f:TEXT)- открывает файл для записи в конец файла. Процедуры Resetи Appendвыполняются только для существующих файлов, процедура Rewrite- для любых файлов, но если файл существует, он будет уничтожен и создан заново. Чтение из файла и запись в файл выполняются процедурами READ[LN]и WRITE[LN], но перед списком ввода или вывода задается файловая переменная:
5. Read[Ln](VAR f:TEXT; список ввода).
6. Write[Ln](VAR f:TEXT;список вывода).
Списки ввода и вывода строятся точно так же, как и в случае ввода с клавиатуры и вывода на экран. Особенностью текстовых файлов является то, что они состоят из строк, каждая из которых заканчивается символом конца строки. Процедура WriteLnзаписывает в файл этот символ, а процедура Write- нет. Вы можете сами управлять длинами записываемых строк, в нужный момент вызывая процедуру WriteLn. При вводе следует помнить, что если символ конца строки не считан процедурой ReadLn, то следующая строка недоступна. Как правило, текстовый файл используется для хранения строк или символов, но можно держать там и числа.
Для текстовых файлов определены четыре логические функции:
7. Function EOLN(VAR f:TEXT):Boolean- возвращает TRUE, если при чтении достигнут конец строки.
8. Function EOF(VAR f:TEXT):Boolean- возвращает TRUE, если при чтении достигнут конец файла.
9. Function SeekEOLN(VAR f:TEXT):Boolean- возвращает TRUE, если в строке больше нет ничего, кроме пробелов.
10. Function SeekEOF(VAR f:TEXT):Boolean- возвращает TRUE, если в файле нет больше ничего, кроме пробелов.
Функция EOLNпригодится вам, если вы читаете из текстового файла символы; функция EOF- если вы читаете символы или строки, а функции SeekEOLNи SeekEOFнеобходимы при вводе чисел из текстового файла. Функции EOLNи SeekEOLNтакже могут быть полезны при обычном вводе с клавиатуры. Приведем пример: пусть необходимо ввести некоторый массив натуральных чисел и некоторый массив символов. Известно, что в обоих массивах не более 100 элементов. Запишем программу, которой не нужно заранее знать, сколько элементов будет введено, это удобнее, чем сначала запрашивать количество элементов в массиве.
const nmax=100;
var x : array[1..nmax] of word;
c : array[1..nmax] of char;
i, nx, nc : byte;
begin
nx:=0; nc:=0;
writeln(Rus('введите числа'));
{вводим все числа, заканчивая клавишей enter}
while not seekeoln do
begin inc(nx);
read(x[nx]);
end;
{считываем конец строки, иначе не введутся символы}
readln;
{вводим символы, заканчивая клавишей enter}
writeln(Rus('введите символы')); while not eoln do
begin inc(nc);
read(c[nc]);
end;
writeln(Rus('введено '),nx,Rus(' чисел :'));
for i:=1 to nx do
write(x[i]:8);
writeln;
writeln(Rus('введено '),nc,Rus(' символов :'));
for i:=1 to nc do
write(c[i]);
writeln; readln;readln;
end.
Вернемся к работе с файлами. Файл закрывается процедурой.
11. Procedure Close(VARf:TEXT),
после чего файловую переменную можно использовать для других целей. Любой файл можно удалить с диска процедурой.
12. Procedure Erase(VARf).
Удаляемый файл должен быть инициализирован, но не открыт, или открыт, но затем закрыт. Напишем программу, которая читает текстовый файл и выводит его на экран. Для ее работы нам понадобится создать при помощи любого текстового редактора файл, сохранить его под именем test.txt в той же папке, где будет храниться наша программа:
var f : textfile;
s : string;
const name='test.txt';
begin
assign(f,name);
reset(f);
while not eof(f) do
begin readln(f,s);
writeln(s);
end;
close(f); readln
end.
Теперь выполним то же самое, не используя строку:
var f : text;
c : char;
const name='test.txt';
begin
assign(f,name);
reset(f);
while not eof(f) do
begin
while not eoln(f) do
begin read(f,c);
write(c);
end;
readln(f);
writeln;
end;
end.
Если в этой программе опустить READLN(f), то она зациклится. Прочтем из текстового файла числа (в таком файле должны быть записаны только числовые константы и пробелы):
var f : text;
x : single;
const name='num.txt';
begin
assign(f,name);
reset(f);
while not seekeof(f) do
begin read(f,x);
write(x:10:5);
end; readln
end.
Числа в текстовом файле могут быть записаны как в одной, так и в нескольких строках и разделяться любым количеством пробелов.
ЗАДАНИЯ ДЛЯ ЛАБОРАТОРНЫХ РАБОТ
Лабораторная работа №1.
Вычисление простейших арифметических выражений
.
, .
, .
, , …,
по данным значениям , , .
.
Разрешается использовать не более четырех умножений и четырех сложений и вычитаний.
и .
Разрешается использовать не более восьми операций.
Лабораторная работа №2.
Разветвления
Примечание. Здесь и далее обозначает минимальное из чисел x и y, – максимальное из чисел x и y.
Лабораторная работа №3.
Простейшие циклы
.
.
.
; ,
Дано натуральное число . Получить .
Лабораторная работа №4.
Итерационные циклы. Вычисление суммы ряда
Для заданного положительного , описывается как константа, и заданного , вводится с клавиатуры, вычислить сумму ряда с точностью . Значение параметра , входящего в некоторые варианты, вводится с клавиатуры. Значение полученной суммы сравнить с соответствующим значением в левой части равенства. Так же на печать выдать количество суммируемых членов ряда. Предусмотреть ограничение количества слагаемых ряда для предотвращения «зацикливания». Приложением должен быть также предусмотрен ввод чисел только из указанного диапазона.
Лабораторная работа №5.
Целые числа
треугольник, в котором по краям стоят единицы, а каждое число внутри равно сумме двух стоящих над ним в ближайшей строке сверху. Дано натуральное . Получить первые строк треугольника Паскаля.
Лабораторная работа №6.
Вычисления с хранением последовательностей
Лабораторная работа №7.
Двумерные массивы.
1. Дана действительная матрица размера . Найти среднее арифметическое наибольшего и наименьшего значения ее элементов.
2. Дана действительная матрица размера . Найти сумму наибольших значений элементов ее строк.
3. В данной действительной квадратной матрице порядка найти сумму элементов строки, в которой расположен элемент с наименьшим значением. Предполагается, что такой элемент единственный.
4. В данной действительной матрице размера поменять местами строку, содержащую элемент с наибольшим значением, со строкой, содержащей элемент с наименьшим значением. Предполагается, что эти элементы единственны.
5. В данной квадратной целочисленной матрице порядка 17 указать индексы всех элементов с наибольшим значением.
6. Дана целочисленная квадратная матрица порядка 8. Найти наименьшее из значений элементов столбца, который обладает наибольшей суммой модулей элементов. Если таких столбцов несколько, то взять первый из них.
7. Дана действительная квадратная матрица порядка 10. В строках с отрицательным элементом на главной диагонали найти сумму всех элементов.
8. Дана действительная квадратная матрица порядка . Рассмотрим те элементы, которые расположены в строках, начинающихся с отрицательного элемента. Найти суммы тех из них, которые расположены соответственно ниже, выше и на главной диагонали.
9. Даны натуральное число , действительная квадратная матрица порядка . Поострить последовательность из нулей и единиц, в которой тогда и только тогда, когда элементы -строки матрицы образуют возрастающую последовательность.
10. Дана целочисленная квадратная матрица порядка 15. Выяснить, имеются ли в матрице ненулевые элементы, и если имеются, то указать индексы всех ненулевых элементов.
11. Дана действительная квадратная матрица порядка 9. Вычислить сумму тех из ее элементов, расположенных на главной диагонали и выше нее, которые превосходят по величине все элементы, расположенные ниже главной диагонали. Если на главной диагонали и выше нее нет элементов с указанным свойством, то ответом должно служить сообщение об этом.
12. Дана действительная квадратная матрица порядка . Найти сумму элементов главной и побочной диагоналей.
13. Дана действительная квадратная матрица порядка . Найти наименьшее из значений элементов побочной диагонали и двух соседних с ней линий.
14. Дана действительная квадратная матрица порядка . Выяснить, верно ли, что наибольшее из значений элементов главной диагонали больше, чем наименьшее из значений элементов побочной диагонали.
15. Даны целые числа , целочисленная квадратная матрица порядка . Заменить нулями в матрице те элементы с четной суммой индексов, для которых имеются равные среди .
16. Дана целочисленная матрица размера . Найти матрицу, получающуюся из данной перестановкой столбцов – первого с последним, второго с предпоследним и т.д.
17. Дана целочисленная матрица размера . Найти матрицу, получающуюся из данной перестановкой строк – первой с последней, второй с предпоследней и т.д.
18. Дана действительная квадратная матрица порядка . Преобразовать матрицу по правилу: строку с номером сделать столбцом с номером , а столбец с номером сделать строкой с номером .
19. Даны две действительные квадратные матрицы порядка .Получить новую матрицу – умножением элементов каждой строки первой матрицы на наибольшее из значений элементов соответствующей строки второй матрицы.
20. В данной действительной квадратной матрице порядка найти наибольший по модулю элемент. Получить квадратную матрицу порядка путем выбрасывания из исходной матрицы какой-либо строки и столбца, на пересечении которых расположен элемент с найденным значением.
Лабораторная работа №8.
Обработка последовательностей символов
Для всех упражнений данной лабораторной работы входной информацией является строка – последовательность английских слов, разделенных пробелами.
Лабораторная работа №9.
Использование подпрограмм
1. Даны действительные числа , . Получить
,
где
.
2. Даны действительные числа , . Получить
,
где
.
, , .
5. Даны действительные числа , . Получить
,
где
.
.
.
.
Использовать программу, включающую рекурсивную процедуру вычисления .
(это так называемая функция Аккермана).
Использовать программу, включающую рекурсивную процедуру.
СОДЕРЖАНИЕ
Предисловие ___________________________________________________3
1. Общая схема решения задачи на персональном компьютере 6
2. Введение в язык Object Pascal. Общая структура программы. Идентификаторы, комментарии, пробелы. Раздел описаний и раздел операторов_____________________7
3. Арифметические типы данных. Числовые константы и переменные.
Оператор присваивания. Выражения__________________________________________8
4. Операторы ввода-вывода_________________________________________________11
5. Арифметические операции. Стандартные математические функции 13
6. Символьный тип данных_______________________ _____________ 17
7. Логический тип данных. Операции сравнения. Логические операции.
Битовые операции___________________________________________________18
8. Условный оператор. Блок. Оператор выбора 21
9. Операторы цикла_______________________ _23
10. Метки. Оператор GOTO. Процедура Halt 26
11. Интервальные типы данных. Оператор TYPE. Массивы____________27
12. Ошибки при выполнении программы. Опции компилятор __ 32
13. Процедуры и функции. Сфера действия описаний 34
14. Множества_________________________________ 38
15. Тип STRING________________________________________________40
17. Кое-что о вещественных вычислениях 51
18. Записи___________________________ 54
19. Тип "перечисление" _____________________________________57
21. Модули. Создание и использование модулей 60
22. Файлы_________________________________ 61
24. Указатели и динамическая память 68
25. Динамические структуры : списки, деревья 71
31. Некоторые вычислительные алгоритмы______________________80
32. Объекты__________________________ ____ 87
– Конец работы –
Используемые теги: Общая, Схема, решения, задачи, персональном, компьютере0.102
Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Общая схема решения задачи на персональном компьютере
Если этот материал оказался полезным для Вас, Вы можете сохранить его на свою страничку в социальных сетях:
Твитнуть |
Новости и инфо для студентов