АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

ПРОГРАММА ВЫПОЛНЕНИЯ РАБОТЫ

Читайте также:
  1. F Продолжение выполнения задания
  2. F Продолжение выполнения задания
  3. F Продолжение выполнения задания
  4. F Продолжение выполнения задания
  5. I Психологические принципы, задачи и функции социальной работы
  6. I. Задания для самостоятельной работы
  7. I. Задания для самостоятельной работы
  8. I. Задания для самостоятельной работы
  9. I. КУРСОВЫЕ РАБОТЫ
  10. I. ОБЩИЕ ПОЛОЖЕНИЯ ПО ВЫПОЛНЕНИЮ КОНТРОЛЬНОЙ РАБОТЫ
  11. I. ОБЩИЕ УКАЗАНИЯ К ВЫПОЛНЕНИЮ КУРСОВОЙ РАБОТЫ
  12. I. РАБОЧАЯ ПРОГРАММА

Если в программе все операторы выполняются последовательно, один за другим, такая программа называется линейной. Рассмотрим в качестве примера программу, вычисляющую результат по заданной формуле.

2.1 ЗАДАЧА 1.1. РАСЧЕТ ПО ФОРМУЛЕ

Написать программу, которая переводит температуру в градусах по Фаренгейту в градусы Цельсия по формуле:

,

где Стемпература по Цельсию, a Fтемпература по Фаренгейту.

Перед написанием любой программы надо четко определить, что в нее требуется ввести и что мы должны получить в результате. В данном случае сомнений нет: в качестве исходных данных выступает одно вещественное число, представляющее собой температуру по Цельсию, в качестве результата – другое вещественное число. Алгоритмических сложностей решение этой задачи также не представляет, поэтому давайте попробуем написать эту программу «в лоб» и посмотрим, что получится. Сразу же оговоримся, что первый блин будет комом, но тем программирование и отличается в лучшую сторону от реальной жизни, что ошибки можно найти и исправить.

#include <iostream.h>

int main() { // 1

float fahr, cels;. // 2

cout << endl << " Введите температуру по Фаренгейту" << endl; // 3

cin >> fahr; // 4

cels = 5 / 9 * (fahr - 32); // 5

cout << " По Фаренгейту: " << fahr << ", в градусах Цельсия: "

<< cels << endl; // 6

return 0; // 7

}

Рассмотрим каждую строку программы отдельно.

В начале программы записана директива препроцессора[6], по которой к исходному тексту программы подключается заголовочный файл <iostream.h>. Это текстовый файл, который содержит описания элементов стандартной библиотеки, необходимых для выполнения ввода-вывода. Если говорить более конкретно, то в этом файле описан набор классов для управления вводом/выводом, стандартные объекты-потоки cin для ввода с клавиатуры и cout для вывода на экран, а также операции помещения впоток << (вывода на экран) и извлечения из потока >> (ввода с клавиатуры). Объекты мы будем рассматривать во второй части методических указаний, а пока давайте пользоваться стандартными объектами и операциями с ними как некими волшебными словами, не пытаясь полностью осознать их смысл, ведь и в реальной жизни большинством благ цивилизации мы пользуемся подобным же образом.

ВНИМАНИЕ: Директивы препроцессора записываются в отдельной строке, перед знаком # могут находиться только пробельные символы.

Программа на C++ состоит из функций. Функция – это именованная последовательность операторов. Функция состоит из заголовка и тела. Строка, помеченная комментарием 1, представляет собой заголовок главной (а в данном случае и единственной) функции программы. Она должна иметь имя main, указывающее, что именно с нее требуется начинать выполнение. Заголовок любой функции пишется по определенным правилам. За именем функции в скобках обычно следует список передаваемых ей параметров. В данном случае он пуст, но скобки необходимы для того, чтобы компилятор мог распознать, что это именно функция, а не другая конструкция языка. Перед именем записан тип значения (int – целое), возвращаемого функцией в точку ее вызова (в данном случае – во внешнюю среду). По стандарту главная функция должна возвращать целочисленное значение. Забегая вперед, скажем, что этим в нашей программе занимается оператор 7. Впрочем, многие компиляторы реагируют спокойно и в случае, если функция ничего не возвращает.

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

Для хранения исходных данных и результатов надо выделить достаточно места в оперативной памяти. Для этого служит оператор 2. В нашей программе требуется хранить два значения: температуру по Цельсию и температуру по Фаренгейту, поэтому в операторе определяются две переменные. Одна, для хранения температуры по Фаренгейту, названа fahr, другая (по Цельсию) – сels.

ВНИМАНИЕ: Имена переменным дает программист, исходя из их назначения. Имя может состоять толь­ко из латинских букв, цифр и знака подчеркивания и должно начинаться не с цифры. От того, насколько удачно подобраны имена в программе, зависит ее читаемость – одна из важ­нейших характеристик программы.

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

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

ПРИМЕЧАНИЕ: В общем случае тип переменных выбирается исходя из возможного диапазона значений и требуемой точности представления данных. Например, нет необходимости заводить переменную вещественного типа для хранения величины, которая может принимать только целые значения – хотя бы потому, что целочисленные операции выполняются гораздо быстрее.

Для того чтобы пользователь программы знал, в какой момент требуется ввести с клавиатуры данные, применяется так называемое пригла­шение к вводу (оператор 3). На экран выводится указанная в операторе строка символов, и курсор переводится на следующую строку. Строка символов, более строго называемая символьным литералом, –это последовательность любых представимых в компьютере символов, заключенная в кавычки.

Стандартный объект, с помощью которого выполняется вывод на экран, называется cout. Ему с помощью операции << передается то, что мы хотим вывести. Для вывода нескольких элементов используется цепочка таких операций. Для перехода на следующую строку записывается волшебное слово endl. Это – так называемый манипулятор; он управляет, то есть «манипулирует» стандартным объектом cout. Существуют и другие манипуляторы, с помощью которых можно задать вид выводимой информации. Мы будем рассматривать их по мере необходимости.

СОВЕТ: Не забывайте в дружелюбной манере, но без излишнего многословия, пригласить пользова­теля ввести исходные данные и указать порядок их ввода. В некоторых случаях может по­надобиться указать тип величин.

В операторе 4 выполняется ввод с клавиатуры одного числа в переменную fahr. Для этого используется стандартный объект cin и операция извлечения (чтения) >>. Как видите, семантика ввода очень проста и интуитивно понятна: значение со стандартного ввода передается в переменную, указанную справа. Если требуется ввести несколько величин, используется цепочка операций >>. В процессе ввода число преобразуется из последовательности символов, набранных на клавиатуре, во внутреннее представление вещественного числа и помещается в ячейку памяти, зарезервированную для переменной fahr.

В операторе 5 вычисляется выражение, записанное справа от операции присваивания (обозначаемой знаком =), и результат присваивается переменной cels, то есть заносится в отведенную этой переменной память. Выражение – это правило для вычисления некоторого значения, можно назвать его формулой. Порядок вычислений определяется приоритетом операций. Уровней приоритетов в языке C++ огорчительно много, поэтому в случае сомнений надо не лениться обращаться к справочной информации, а вот запоминать подобные вещи в дета­лях мы бы не рекомендовали – есть и более полезные применения головному мозгу.

Основные правила, тем не менее, просты и соответствуют принятым в математике: вычитание имеет более низкий приоритет, чем умножение, поэтому для того, чтобы оно было выполнено раньше, соответствующая часть выражения заключается в скобки. Деление и умножение имеют одинаковый приоритет и выполняются слева направо, то есть сначала целая константа 5 будет поделена на целую константу 9, а затем результат этой операции умножен на результат вычитания числа 32 из переменной fahr. Мы вернемся к обсуждению этого оператора позже, а пока рассмотрим два оставшихся.

Для вывода результата в операторе 6 применяется уже знакомый нам объект cout. Выводится цепочка, состоящая из четырех элементов. Это строка " По Фаренгейту: ", значение переменной fahr, строка ", в градусах Цельсия:" и значение переменной сels. Обратите внимание, что при выводе строк все символы, находящиеся внутри кавычек, включая и пробелы, выводятся без изменений. При выводе значений переменных выполняется преобразование из внутреннего представления числа в строку символов, представляющую это число. Под значение отводится ровно столько позиций, сколько необходимо для вывода всех его значащих цифр. Это значит, что если вывести две переменные подряд, их значения «склеятся», например:

cout << fahr << сels; // плохо

cout << fahr << ' ' << сels; // чуть лучше

СОВЕТ: Рекомендуется всегда предварять выводимые значения текстовыми пояснениями.

В одиночные кавычки в языке C++ заключается отдельный символ. В данном примере это пробел. Наконец, последний оператор (оператор 7) этой программы предназначен для возврата из нее и передачи значения во внешнюю среду. В главной функции разрешается его опускать, но в этом случае компилятор может выдать предупреждение (warning) и сформирует возвращаемое значение по умолчанию, равное нулю. Предупреждение можно проигнорировать, но, на наш взгляд, приятнее видеть в результате компиляции сообщение «0 errors, 0 warnings» (0 ошибок, 0 предупреждений) или «Success» (успешное завершение) – при большом количестве запусков программы это экономит время, не отвлекая внимания.

Наберите текст программы и скомпилируйте ее. Если вы видите сообщения об ошибках, сличите текст на экране с текстом в книге (последний – лучше).

ВНИМАНИЕ: При работе в интегрированной среде Borland C++ 3.1 (или любой другой оболочке, рассчитанной на работу в среде MS DOS) у вас не будет проблем с компиляцией и выполнением приводимых примеров. Напротив, работа в среде Microsoft Visual C++ 6.0 в режиме консольных приложений сопряжена с неудобствами, вызванными различными стандартами кодировки символов кириллицы в операционных системах MS DOS и Windows. Ниже мы рассмотрим этот вопрос подробнее.

2.2 ОСОБЕННОСТИ РАБОТЫ В ИНТЕГРИРОВАННОЙ СРЕДЕ VISUAL C++ 6.0

Мы предполагаем, что вы уже посмотрели (см. методические указания по интегрированной среде), как создаются прило­жения консольного типа, набрали текст приведенной выше программы, откомпи­лировали ее и запустили на выполнение. Вам приготовлен неприятный сюрприз: вместо приглашения «Введите температуру по Фаренгейту» вы увидите набор ка­ких-то странных символов. Этому, конечно, должно быть какое-то объяснение. Начнем издалека. В старой доброй операционной системе MS DOS для кодировки символов используется стандарт ASCII, являющийся международным только в первой половине кодов (от 0 до 127), вторая половина кодов (от 128 до 255) явля­ется национальной и различна для разных стран.

Например, в России для второй половины таблицы ASCII используется так называемая «альтернативная кодировка ГОСТа». В Windows же используется стандарт ANSI, в первой половине совпадающий с ASCII, а во второй половине отличающийся от его российского варианта. Разработчики интегрированной среды Visual C++ решили, что режим консольных приложений должен как бы имитировать работу в среде MS DOS, поэтому ввод-вывод выполняется в этом режиме в кодировке ASCII. В то же время в текстовом редакторе Visual C++, как и во всех Windows-приложениях, используется кодировка ANSI. Теперь происхождение этих странных символов должно стать вам понятным.

Покажем, как будет выглядеть наша первая программа при ее реализации в среде Visual C++ 6.0 (приводится одно из возможных решений):

#include <iostream.h>

#include <windows.h>

 

char* Rus(const char* text); // 0


int main(){ // 1

float fahr, cels; // 2

cout << endl << Rus(" Введите температуру по Фаренгейту") << endl; // 3

cin >> fahr; // 4
cels = 5 / 9 * (fahr - 32); // 5

cout << Rus(" По Фаренгейту: ") << fahr; // 6

cout << Rus(". в градусах Цельсия: ") << cels << endl; // 7
return 0;

}

//////////////////////////////////////////////////////////

char bufRus[256]; // 8

char* Rus(const char* text){ // 9

CharTo0em(text, bufRus); // 10

return bufRus; // 11

} // 12

//////////////////////////////////////////////////////////

Для решения проблемы мы написали свою небольшую функцию Rus(), которая, обращаясь к функции CharTo0em(), возвращает в качестве адреса преобразованной строки указатель на char (строки 9-12). В качестве временного хранилища преоб­разуемой строки функция использует глобальный 2 массив bufRus длиной 256 сим­волов (предполагается, что в качестве аргумента будут подставляться строки, не превышающие эту длину), описанный в операторе 8. Использовать функцию очень просто: любая строковая_константа заменяется выражением Rus(строковая_констан­та). Кроме того, мы добавили в нашу программу так называемый прототип функ­ции Rus (оператор 0). Он требуется компилятору для проверки правильности ее использования.

ПРИМЕЧАНИЕ: Строго говоря, для использования такой функции в операциях вывода с объектом cout было бы правильнее потребовать, чтобы функция Rus () возвращала значение типа ссылки на класс ostream, но для этого нужно владеть основами работы с классами, поэтому к этому вопросу мы вернемся во второй части практикума. То, что функция Rus () возвращает значение типа char*, приводит к следующему ограничению: ее нельзя использовать более одного раза в цепочке операций << для одного объекта cout.

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

2.3 ОТЛАДКА ПРОГРАММЫ

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

Как вы можете видеть, результат выполнения программы со стабильностью, достойной лучшего применения, оказывается равным нулю! Это происходит из-за способа вычисления выражения. Давайте вновь обратимся к оператору 4. Константы 5 и 9 имеют целый тип, поэтому результат их деления также целочисленный. Округления при этом не происходит, дробная часть всегда отбрасывается. Естественно, что результат дальнейших вычислений не может быть ничем, кроме нуля. Исправить эту ошибку просто – достаточно записать хотя бы одну из констант в виде вещественного числа, например:

cels = 5. / 9 * (fahr - 32); // 5

Вещественная константа «5.» по умолчанию имеет тип double, и при выполнении деления происходит автоматическое преобразование к этому же типу другой константы, а затем и результата вычитания.

Можно записать это выражение и по-другому, просто изменив порядок действий:

cels = 5 * (fahr - 32) /9; //5

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

Введите температуру по Фаренгейту

По Фаренгейту: 451, в градусах Цельсия: 232.778

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

СОВЕТ: Начинающие часто тратят время на поиск ошибки в алгоритме, не удостоверившись, что программа работает с правильными данными. Рекомендуется для контроля выводить ис­ходные данные сразу же после ввода, чтобы исключить ошибки.

Попробуйте при вводе температуры задать нецифровые символы и проинтерпре­тировать полученный результат.

Как видите, даже в таком простом примере можно допустить ошибки! В данном случае заметить их легко, но так происходит далеко не всегда, поэтому запомните важное правило: надо всегда заранее знать, что должна выдать программа. Добить­ся этого можно разными способами, например, вычислением результатов в уме, на бумаге или с помощью калькулятора, а в более сложных случаях – расчетами по аль­тернативной или упрощенной методике. Это убережет вас от многих часов, бесплод­но и безрадостно проведенных за компьютером. Не поленимся повторить еще раз:

ВНИМАНИЕ: Перед запуском программы необходимо иметь тестовые примеры, содержащие исходные данные и ожидаемые результаты. Количество этих примеров зависит от алгоритма.

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

Давайте теперь напишем ту же программу вторым способом, с использованием функций библиотеки C++, унаследованных из языка С. Этот способ также приме­няется достаточно часто, потому что в использовании этих функций есть свои пре­имущества. Когда вы их оцените, то сможете выбирать для каждой программы наи­более подходящий способ ввода-вывода.

#include <stdio.h>

int main(){ // 1

float fahr, cels; // 2

printf("\n Введите температуру по Фаренгейту\n"); // 3

scanf ("%f", &fahr); // 4

cels = 5 * (fahr - 32) /9; // 5

printf(" По Фаренгейту: %6.2f, вградусах Цельсия: %6.2f\n", fahr, cels); // 6

return 0: // 7

}

Как видите, к программе подключается другой заголовочный файл – <stdio.h>. Он содержит описание функций, констант и других элементов, относящихся ко вводу-выводу «в стиле С».

Рассмотрим отличия этой программы от предыдущей.

Функция printf в операторе 3 выполняет вывод переданного ей в качестве пара­метра строкового литерала, то есть последовательности любых символов в кавыч­ках, на стандартное устройство вывода (дисплей). Символы \n называются управляющей последовательностью. Есть разные управляющие последовательности, все они начинаются с обратной косой черты. Эта последовательность задает переход на следующую строку.

Для ввода исходных данных в операторе 4 используется функция scanf. В ней тре­буется указать формат вводимых значений, а также адреса переменных, которым они будут присвоены. Параметры любой функции перечисляются через запятую. В первом параметре функции scanf в виде строкового литерала задается спецификация формата вводимой величины, соответствующая типу переменной. Спецификация %fсоответствует типу float[7]. В качестве второго параметра функ­ции передается адрес переменной, по которому будет помещено вводимое значе­ние. Операция взятия адреса обозначается &.

Для вывода результата в операторе 6применяется уже знакомая нам функция printf. Теперь в ней три параметра. Первый, имеющий вид строкового литерала, задает вид и формат выводимой информации. Второй и третий параметры пред­ставляют собой имена переменных. Все символы литерала, кроме спецификаций формата %fи управляющей последовательности \n, выводятся на дисплей без из­менений. При выводе форматные спецификации будут заменены конкретными значениями переменных fahr и cels.

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

1 Приведем еще две наиболее употребительные спецификации: –для величин целого типа в деся­тичной системе счисления, 81 f – для величин типа double. Более полный список спецификаций см. в Учебнике на с. 387.

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

Надо сказать, что при использовании классов также можно задавать любую форму представления информации, но мы пока не будем вдаваться в подобные детали. Мы не рекомендуем начинающим изучать на этом семинаре теоретический мате­риал по классам ввода/вывода, поскольку для их полного понимания требуется освоить большой объем материала. Всему свое время!

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

СОВЕТ: Используйте функции ввода/вывода в тех программах, где требуется тщательное формати­рование результатов, а классы – в остальных случаях.

Рассмотрим в более общем виде очень важный для дальнейшей работы вопрос – описание переменных.

2.4 ОПИСАНИЕ ПЕРЕМЕННЫХ

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

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

Переменная, описанная внутри блока (в частности, внутри функции main), является локальной, память под нее выделяется в сегменте стека в момент выполнения оператора описания. Для локальных переменных автоматическое обнуление не производится. Областью действия локальной переменной является блок, в котором она описана, начиная с точки описания. Время ее жизни также ограничено этим блоком. Сколько раз выполняется блок, столько раз «рождается» и «умирает» локальная переменная.

Есть один вид локальных переменных, которые, подобно глобальным, размещаются в сегменте данных, существуют на всем протяжении выполнения программы и инициализируются однократно. Это статические переменные. С другой стороны, они, как локальные переменные, видны только в своем блоке. Для описания статических переменных используется ключевое слово static. Ниже приведен пример описания трех переменных и таблица 6, в которой суммируются сведения о видах переменных:

int a; // глобальная переменная

int main() {

static int b = 1: // локальная статическая переменная

int с: // локальная переменная

}

Таблица 6-Сведения о видах переменных

  Глобальная Локальная статическая Локальная
Имя a b с
Размещение сегмент данных сегмент данных сегмент стека
Время жизни вся программа вся программа блок
Область видимости файл блок блок
Инициализация да да нет

Память под все эти переменные выделяет компилятор. Кроме перечисленных, существуют динамические переменные, память под которые резервируется во время выполнения программы с помощью операции new в динамической области памяти, или хипе (heap). Доступ к таким переменным осуществляется не по имени, а через указатели. Мы рассмотрим их на третьем семинаре.

Во всех рассмотренных выше программах переменные являются локальными. Вариант с глобальными переменными выглядит так:

#include <iostream.h>

float fahr, сels; // глобальные переменные

int main() {

cout << endl << " Введите температуру по Фаренгейту" << endl;
cin >> fahr;

cels = 5 * (fahr - 32) / 9;

cout << " По Фаренгейту: " << fahr << ", в градусах Цельсия: " << cels << endl;

return 0;

}

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

2.5 ЗАДАЧА 1.2. ВРЕМЕННОЙ ИНТЕРВАЛ

Заданы моменты начала и конца некоторого промежутка времени в часах, минутах и секундах (в пределах одних суток). Найти продолжительность этого промежутки; в тех же единицах.

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

Вы уже знаете, что тип переменной выбирается, исходя из диапазона и требуемой точности представления данных, а имя дается в соответствии с ее содержимым. Нам потребуется хранить исходные данные, не превышающие величины 60 для минут и секунд и величины 24 для часов, поэтому можно ограничиться коротким целым типом (short int, сокращенно short). Назовем переменные для хранения начала интервала hourl, mini и seel, для хранения конца интервала – hour2, min2 и sec2, а результирующие величины – hour, min и sec.

Для решения этой задачи необходимо преобразовать оба момента времени в секунды, вычесть первый из второго, а затем преобразовать результат обратно в часы, минуты и секунды. Следовательно, нам потребуется промежуточная переменная, в которой будет храниться интервал в секундах. Она может иметь весьма большие значения, ведь в сутках 86400 секунд. В величинах типа short могут храниться значения, не превышающие 32767 для величин со знаком (signed short) и 65535 для величин без знака (unsigned short), поэтому тип short здесь использовать нельзя. Вот почему для этой переменной следует выбрать длинный целый тип (long int, сокращенно long). «Обычный» целый тип int в зависимости от архитектуры компьютера может совпадать либо с коротким, либо с длинным целым типом.

Ниже приведен текст программы:

#include <iostream.h>

int main() {

short hour1, min1, sec1, hour2, min2, sec2, hour, min, sec;

cout << endl << " Введите время начала интервала (час мин сек)" << endl;

cin >> hour1 >> min1 >> sec1;

cout << endl << " Введите время конца интервала (час мин сек)" << endl;

cin >> hour2 >> min2 >> sec2;

long sum_sec = (hour2 – hour1) * 3600 + (min2 – min1) * 60 + sec2 – sec1;

hour = sum_sec / 3600;

min = (sum_sec - hour * 3600) / 60;

sec = sum_sec - hour * 3600 - min * 60;

cout << " Продолжительность промежутка от " <<

hour1 << ':' << min1 << ':' << sec1 «" до " <<

hour2 << ':' << min2 << ':' << sec2 << endl << " равна " <<

hour << ':' << min << ':' << sec << endl;

return 0;

}

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

ВНИМАНИЕ: Данные при вводе разделяются пробелами, символами перевода строки или табуляции (но не запятыми!).

Протестируйте программу на различных наборах исходных данных.

Для обладателей старых компиляторов приведем текст программы с использованием функций ввода-вывода в стиле С:

#include <stdio.h>

int main() {

short hour1, min1, sec1. hour2. min2, sec2. hour, min, sec;

printf(" Введите время начала интервала (час мин сек)\n");

scanf ("%i%i%i", &hour1, &min1, &sec1);

printf(" Введите время конца интервала (час мин сек)\n");

scanf("%i%i%i". &hour2, &min2, &sec2);

long sum_sec = (hour2 – hour1) * 3600 + (min2 – min1) * 60 + sec2 – sec1;

hour = sum_sec / 3600;

min = (sum_sec - hour * 3600) / 60;

sec = sum_sec - hour * 3600 - min * 60;

printf(" Длительность промежутка от %2i:%2i:%2i до %2i:%2i:l2i\n", hour1,

min1, sec1, hour2, min2. sec2);

printf(" равна %2i:%2i:%2i\n", hour, min, sec);

return 0;

}

Давайте повторим наиболее важные моменты этой лабораторной работы.

1. Выбирайте тип переменных с учетом диапазона и требуемой точности представления данных.

2. Давайте переменным имена, отражающие их назначение.

3. Ввод с клавиатуры предваряйте приглашением. Для контроля сразу же после ввода выводите исходные данные на дисплей (по крайней мере, в процессе отладки).

4. До запуска программы подготовьте тестовые примеры, содержащие исходные данные и ожидаемые результаты. Отдельно проверьте реакцию программы на неверные исходные данные.

5. При записи выражений обращайте внимание на приоритет операций.

6. В функциях printf и scanf для каждой переменной указывайте спецификацию формата, соответствующую ее типу. Не забывайте, что в scanf передается адрес переменной, а не ее значение.

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

8. Не смешивайте в одной программе ввод/вывод с помощью классов (в стиле C++) и с помощью функций библиотеки (в стиле С).

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

10. Данные при вводе разделяйте пробелами, символами перевода строки или табуляции.

Основные моменты правильного написания программ приведены в приложении 3.

3. СОДЕРЖАНИЕ ОТЧЕТА

1. Титульный лист установленного образца.

2. Формулировка цели лабораторной работы.

3. Постановка задачи лабораторной работы.

4. Приведение блок-схемы задачи.

5. Листинг программы.

6. Результат счета или выполнения программы.

7. Обязательным является наличие электронного варианта программы.

4. КОНТРОЛЬНЫЕ ВОПРОСЫ

1. Что такое структурное программирование?

2. Основные элементы языка С++.

3. В чем заключается роль компилятора?

4. Что такое исходная программа?

5. Что называется препроцессором?

6. Назовите основные типы данных.

7. Какие типы данных относятся к целочисленным, а какие к типам с плавающей точкой?

8. Назовите основные функции ввода/вывода.

9. Назовите тип данных, множество значений которого пусто. Для чего он используется?

10. Что такое переменная?

11. Что называется инициализацией?

12. Поясните понятие локальной и глобальной переменной.

13. В какой форме может выполняться описание переменной?

14. В соответствии с количеством операндов, которые используются в операциях, они делятся на… (какие?).

15. Объясните понятие, приоритет выполнения операции.

5. ЗАДАНИЯ

Напишите программу для расчета по двум формулам. Список математических функций библиотеки C++ приведен в приложении 4. Для их использования необходимо подключить к программе заголовочный файл <math.h>.


БИБЛИОГРАФИЧЕСКИЙ СПИСОК

1. Иванова Г.С. Технология программирования: учебник для вузов/ Г. С. Иванова; доп. М-вом образования РФ. -2-е изд., стереотип. -М.: Изд-во МГТУ им. Н. Э. Баумана, 2003. -320 с. -(Информатика в техническом университете).

2. Климова Л.М, Основы практического программирования на языке СИ++: учеб. пособие/ Л. М, Климова; рек. кафедрой прикладной математики МГТУ ГА. -М.: Приор, 1999. -464 с.

3. Колдаев В.Д. Основы алгоритмизации и программирования: Учебное пособие / Под ред. Проф. Л.Г. Гагариной. – М.: ИД «ФОРУМ»: ИНФРА-М, 2006. – 416 с. (Профессиональное образование).

4. Комаров Н.А. Программирование на персональном компьютере: Практическое руководство с примерами по языкам программирования высокого уровня – специальное изд. – М.: Альянс-пресс, 2003. – 688 с. (Серия книг «ПК с нуля»).

5. Павловская Т.А. С/С++. Программирование на языке высокого уровня: учебник для вузов/ Т. А. Павловская; доп. М-вом образования РФ. -СПб.: Питер, 2005. -461 с. -(Учебник для вузов).

6. Павловская Т. А., Щупак Ю.А. Структурное программирование: Практикум. -СПб.: Питер, 2002. -240 с.

7. Семакин И.Г., Шестаков А.П. Основы программирования: Учебник. – М.: Мастерство; НМЦ СПО; Высшая школа, 2001. – 432с.

8. Фридман А.Л. Язык программирования Си++: Курс лекций для студ. вузов/ А.Л. Фридман; Рек. УМО в обл. прикл. информатики. -М.: ИНТУИТ. У "Интернет-университет Информационных Технологий", 2003. -288 с. -(Основы информационных технологий).


Приложение 1. Спецификации формата для функций семейства printf

Спецификация Пояснение
c Аргумент рассматривается как отдельный символ
d, i Аргумент преобразуется к десятичному виду
e, E Аргумент, рассматриваемый как переменная типа float или double, преобразуется в десятичную форму в виде [-]m.nnnnnne [+ -]xx, где длина строки из n определяется указанной точностью. Точность по умолчанию равна 6
f Аргумент, рассматриваемый как переменная типа float или double, преобразуется в десятичную форму в виде [-]m.nnnnnn, где длина строки из n определяется указанной точностью. Точность по умолчанию равна 6
g, G Используется формат %e или %f, который короче; незначащие нули не печатаются
o Аргумент преобразуется в беззнаковую восьмеричную форму (без лидирующего нуля)
p Вывод указателя в шестнадцатеричном формате (эта спецификация не входит в стандарт, но она существует практически во всех реализациях)
s Аргумент является строкой: символы строки печатаются
u Аргумент преобразуется в беззнаковую десятичную форму
x, X Аргумент преобразуется в беззнаковую шестнадцатеричную форму (без лидирующих 0х)
% Выводится символ %

 

Модификаторы формата

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

%-minC или %minC;

%-min.precisionC или %min.precisionC.

Здесь С – спецификация формата из приведенной выше таблицы, min – число, задающее минимальную ширину поля. Смысл модификатора precision, также за­даваемого десятичным числом, зависит от спецификации формата, с которой он используется:

- при выводе строки (спецификация %s) precision указывает максимальное чис­ло символов для вывода;

- при выводе вещественного числа (спецификации %fили %е) precision указывает количество цифр после десятичной точки;

- при выводе целого числа (спецификации %dили %i), precision указывает минимальное количество выводимых цифр. Если число представляется меньшим числом цифр, чем указано в precision, выводятся ведущие (начальные) нули.

- при выводе вещественного числа (спецификации %d или %G) precision указывает максимальное количество значащих цифр, которые будут выводится.

Символ минус (-) указывает на то, что значение выравнивается по левому краю и, если нужно, дополняется пробелами справа. При отсутствии минуса значение выравнивается по правому краю и дополняется пробелами слева.

Перед спецификацией могут использоваться префиксы l и h, например, %l f, %hu.

Префикс h с типами d, i, о, х и X указывает на то, что тип аргумента short int, а с типом u – short unsigned int.

Префикс l с типами d, i, о, х и X указывает на то, что тип аргумента long int, с ти­пом и - long unsigned int, а с типами e, E, f, g и G – что тип аргумента double, а не float.

Пример:

#include <stdio.h>

int main(){

int int1 = 45, int2 = 13;

float f = 3.621;

double dbl = 2.23;

char ch = 'z’, *str = "ramambahari";

printf("int1 - %d| int2 - %3d| int2 - %-4d|\n", int1, int2, int2);

printf("int1 = %X| int2 - %3x| int2 = %4o|\n", int1, int2, int2);

printf("f - %f| f - %4.2f| f - %6.1f|\n", f, f, f);

printf("f - %g| f - %e| f = %+E|\n", f, f, f);

printf("dbl - %5.21f| dbl - %e| dbl = %4.1G|\n", dbl, dbl, dbl);

printf("ch - %c| ch - %3c|\n", ch, ch);

printf("str = %14s|\nstr - %-14s|\nstr = %s|\n", str, str, str);

return 0;

}

Результат работы программы:

int1 = 45| int2 = 13| int2 = 13 |

int1 = 2D| int2 = d| int2 = 15 |

f = 3.621000| f = 3.62 | f = 3.6 |

f = 3.621 | f = 3.621000e+000 | f = +3.621000E+000|

dbl = 2.23 | dbl = 2.230000e+000 | dbl = 2 |

ch = z| ch = z |

str = ramambahari|

str = ramambahari |

str = ramambahari|


Приложение 2. Арифметические преобразования типов

Преобразования типов выполняются, если операнды, входящие в выражения, имеют различные типы. Ниже приведена последовательность преобразований.

Ø Любые операнды типа char, unsigned char или short преобразуются к типу int по правилам:

• char расширяется нулем или знаком в зависимости от умолчания для char;

• unsigned char расширяется нулем;

• signed char расширяется знаком;

• short, unsigned short и enum при преобразовании не изменяются.

• Затем любые два операнда становятся либо int, либо float, double или long double.

Ø Если один из операндов имеет тип long double, то другой преобразуется к типу long double.

Ø Если один из операндов имеет тип double, то другой преобразуется к типу double.

Ø Если один из операндов имеет тип float, то другой преобразуется к типу float.

Ø Иначе, если один из операндов имеет тип unsigned long, то другой преобразуется к типу unsigned long.

Ø Иначе, если один из операндов имеет тип long, то другой преобразуется к типу long.

Ø Иначе, если один из операндов имеет тип unsigned, то другой преобразуется к типу unsigned.

Ø Иначе оба операнда должны иметь тип int.

Тип результата тот же, что и тип участвующих в выражении операндов.

 


Приложение 3. Правила оформления текстов программ

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

· ясную для понимания, т. е. читабельную. Ясность означает, что любой, кто знаком с языком программирования и прикладной областью, поймет алгоритм, читая текст программы, комментарии и спецификацию;

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

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

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

При написании программ обычно используется принцип «лишь бы работало», т. е. совершенно игнорируются элементарные правила оформления текстов программ. Исходный текст программы – это такой же текст, как стихотворение, эссе, рассказ, web-страничка. Посмотрим на фрагмент сильно искаженного текста (рис. 3).

 

Рис. 3. Фрагмент искаженного текста

Для грамотного написания программы необходимо форматировать исходные тексты. Вспомним, что стандартный размер экрана – 80 х 25 символов (знакомест). Именно такие размеры наиболее комфортны для восприятия.

Правило 1, про количество операторов на одной строке

Количество операторов на строке должно быть равно одному.

Неправильно:

а = b; do while (0); printf("MIEE");

Правильно:

a = b;

do while (0);

printf(MIEE");

Правило 2, про горизонтальные отступы

Все операторы, входящие в составной оператор (напоминаем, составной оператор – это все, что между begin и end в языке программирования Turbo Pascal и между { } в языке программирования С), должны быть сдвинуты вправо (клавиша Tab). Кроме того, размер отступа должен быть восемь символов.

Неправильно:

if (a < b) {

j = m;

i = 1;

for (k = 0; k < N; k++) {

c[k] += (m-1);

u[k-j] = 2*j;

if(1>a) {

break;

};

};

printf("ooo");

};

Правильно:

if (a < b) {

j = m;

i = 1;

for (k = 0; k < N; k++) {

c[k] += (m-1);

u[k-j] = 2*j;

if(1>a) {

break;

};

};

printf("ooo");

};

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

Правило 3, про операторные скобки

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

Неправильно:

for (;;) {

printf("Кафедра ИСТ");

};

for j:=0 to N do begin

WriteLn(‘ Кафедра ИСТ ');

end;

Правильно:

for (;;) {

printf("Кафедра ИСТ");

};

for j:=0 to N do begin

WriteLn(‘ Кафедра ИСТ ');

end;

Допускается такой вариант:

for (;;)

{

printf("истина");

};

for j:=0 to N do

begin

WriteLn('истина');

end;

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

Неправильно:

int my_favorite_function(void) {

return 1;

}

function MyFavoriteFunction:boolean; begin

MyFavoriteFunction:= TRUE;

end;

Правильно:

int my_favorite_function(void)

{

return 1;

}

function MyFavoriteFunction:boolean;

begin

MyFavoriteFunction:= TRUE;

end;

Начинающие программисты обычно набирают текст последовательно, и поэтому:

а) он у них получается кривой и

б) они постоянно забывают закрыть блок или закрывают его не там, где надо.

Чтобы избежать этого, текст программы нужно набирать не последовательно. К этому располагает сама грамматика и синтаксис почти любого языка программирования. Всегда есть ПАРНЫЕ символы – скобки, составные операторы. Если написали begin, то почему бы сразу не написать end? Если набрали открывающую скобку, то почему бы сразу не набрать закрывающую, а потом не вернуться назад?

Например:

for (i = 0; i < N; i++) {

/* тело цикла */

}

Правило 4, про горизонтальные пробелы

В конце строки пробелов быть не должно. Пробелы полезны вокруг знака какой-нибудь операции.

for (k = NUM; k; k--) {

int tmp;

tmp = some_func(k, arg2, arg3);

printf("%d\n", tmp);

}

Правило 5, про вертикальные пробелы (пустые строки)

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

Неправильно:

int func_1(void)

{ return 1;

}

 

int func_1(void)

{ return 2;

}

 

int main(void) {

LIST *1 = get_head();

double a, b;

printf("Hello.\n");

for (1;1->next;1=1->next)

printf("%s\n", 1->name);

};

printf("Bye.\n");

}

Правильно:

int func_1(void)

{

return 1;

}

 

int func_1(void)

{

return 2;

}

 

int main(void)

{

LIST *1 = get_head();

double a, b;

printf("Hello.\n");

for (1; 1->next; 1 = 1->next)

printf("%s\n", 1->name);

printf("Bye.\n");

}

Правило 6, про объявления переменных

Тип у переменной следует писать для каждой из них. На одной строчке – одна переменная.

Неправильно:

int a,b,c;

float *q,w,u,z,tmp,ttt,qqq,aaa,bbb;

……..

a,b,c,d,ttt,test,tt0: integer;

q,w,u,z,ppp,ddd,dddO,ddd23: real;

Правильно:

int a;

int b;

int c;

float *q;

……..

a: integer;

b: integer;

c: integer;

q: real;

Правило 7, про говорящие идентификаторы

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

Правило 8, про инициализацию массивов

Массивы с заранее предопределенными значениями (если их не требуется по заданию вводить с клавиатуры или из файла) не инициализировать операторами присваивания, а делать это с использованием инициализаторов и типизированных констант в языках C++ и Turbo Pascal, соответственно.

Неправильно:

double matrix[3][3];

….

matrix[0][0] = 1.5;

matrix[0][1] = 2.5;

……

Matrix: array[1..3, 1..3] of extended;

……

Matrix[1,1]:= 1.5;

Matrix[1,2]:= 2.5;

Правильно:

double matrix[3][3] = {

{1.5, 2.5,... },

{…},

{...},

};

const

Matrix: array[1..3, 1..3] of extended =

(

 

(1.5, 2.5,...),

(…),

(...)

);

Правило 9, про функции и процедуры

Программа без подпрограмм – почти всегда заведомо плохая программа.

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

Функции должны быть короткими – 2 экрана (50 строк) максимум. Единственное оправдание длинной функции – это наличие в ней оператора множественного выбора с большим числом альтернатив.

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

Правило 10, про ошибки

Если функция может потенциально завершиться неудачно, то эту ситуацию следует проверять.

Неправильно:

char * buf;

buf = (char*)malloc(/*много-много байт*/);

buf[0] = some_value;

Правильно:

char * buf;

buf = (char*)malloc(/*много-много байт*/);

if (!buf) {

реггог("нет памяти");

exit(1);

};

buf[0] = some_value;

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

Неправильно:

char * buf;

buf = (char*)malloc(/*много-много байт*/);

if (buf) {

/* здесь страница кода */

} else {

реггог("нет памяти");

};

Этот else может быть далеко от if, что уменьшает ясность программы.

Правильно:

char * buf;

buf = (char*)malloc(/*много-много байт*/);

if (!buf) {

реггог("нет памяти");

/* выходим */

exit(BAD_EXIT_CODE)

/* или return BAD_RET__VAL; */

};

/* в этом месте все хорошо, продолжаем */

Правило 11, про данные

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

Специально для структуризации данных существуют типы данных, структуры (или записи в терминах языка программирования Pascal) и классы (в ООП-языках). Если программа работает с какой-либо сущностью, то эта сущность должна быть описана в программе посредством структуры или класса, если используется объектно-ориентированный язык. Сложная программа, в которой нет ни одного массива или структуры, – это плохая программа.

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

Неправильно:

#include <stdio.h>

#include <math.h>

double a=0.2,b=1.0,i,h,x,s;

int n=50,k;

void ffa(void)

{h=(b-a)/n;x=a+h/2;s=0;

for(k=1;k<=n;k++){s+=sin(x);x+=h;}

s*=h;} void main(void) {

ffa();

рrintf("значение=%.8f\n",s);}

Правильно:

#include <stdio.h>

#include <math.h>

#define INTEGR_FUNCTION(x) sin((x))

#define INTEGR_FUNCTION_STR "sin(x)"

#define LOWER_LIMIT 0.2

#define UPPER_LIMIT 1.0

#define INTERVALS 50

 

typedef

struct integr_task {

double from;

double to;

double (*what)(double); /* интегрируемая функция */

int nint; /* число интервалов */

} INTEGR_TASK;

typedef

enum integr_error {

INTEGR_OK = 0,

INTEGR_NO_TASK_OR_RES,

INTEGR_NO_FUNC,

INTEGR_BAD_LIMITS,

INTEGR_BAD_NINT,

INTEGR_LAST_ERROR

} INTEGR_ERROR;

 

char *integr_error_str[INTEGR_LAST_ERROR+1] = {

"Все хорошо",

"Указатель на задание или результат равен NULL",

"Указатель на функцию равен NULL",

"Верхний предел меньше нижнего",

"Неправильное число интервалов",

"_INTEGR_LAST_ERROR_"

};

INTEGR_ERROR integrate_rect(INTEGR_TASK * task, double * result);

#define INTEGRATE integrate_rect

 

double function(double arg)

{

return INTEGR_FUNCTION(arg);

}

int main(void)

{

double integral_val;

INTEGR_ERROR error;

 

INTEGRJTASK test_task = {

LOWER_LIMIT,

UPPER_LIMIT,

function,

INTERVALS

};

error = INTEGRATE(&test_task, &integral_val);

 

if (error) {

printf("Ошибка в данных (%s).\n", integr_error_str[error]);

return 1;

};

printf(

"\nЗначение определенного интеграла от функции f(x)=

%s\nв пределах от %.8f до %.8f: %.8f\n",

INTEGR_FUNCTION_STR,

LOWER_LIMIT,

UPPER_LIMIT,

integral_val

);

return 0;

}

INTEGR_ERROR integrate_rect(INTEGR_TASK * task, double * result)

{

double x, s, step;

int j;

 

/* проверка на корректность данных */

if ((!task) || (!result)) {

return INTEGR_NO_TASK_OR_RES;

};

 

if (!task->what) {

return INTEGR_NO_FUNC;

};

 

if (task->from > task->to) {

return INTEGR_BAD_LIMITS;

};

 

if (task->nint < 1) {

return INTEGR_BAD_NINT;

};

 

/* собственно вычисление */

step = (task->to - task->from)/task->nint;

x = task->from+step/2.0;

s = 0;

 

for (j = 1; j <= task->nint; j++, s += task->what(x), x += step);

 

s *= step;

*result = s;

 

return INTEGR_OK;

}

 

 


Приложение 4. Заголовочный файл <math.h> {<cmath.h>} – математические функции

acos Возвращает арккосинус аргумента
asin Возвращает арксинус аргумента
atan Возвращает арктангенс аргумента
atan2 Возвращает арктангенс отношения аргументов
ceil Округляет вверх
cos Вычисляет косинус
cosh Вычисляет гиперболический косинус
exp Возвращает степень числа е
fabs Возвращает модуль числа
floor Округляет вниз
fmod Возвращает остаток от деления х на у
frexp Выделяет из числа мантиссу и экспоненциальную часть
ldexp Преобразует мантиссу и показатель степени в число
log Вычисляет натуральный логарифм
log10 Вычисляет логарифм по основанию 10
modf Разбивает число на целую и дробную части
pow Возводит число в степень
sin Вычисляет синус
sinh Вычисляет гиперболический синус
sqrt Вычисляет квадратный корень
tan Возвращает тангенс аргумента
tanh Возвращает гиперболический тангенс аргумента

 

 


[1] Программист может задать тип константы самостоятельно.

[2] Могут быть опущены либо целая часть, либо дробная, но не обе сразу.

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

[4] Если переменная в том же операторе инициализируется, спецификатор extern игнорируется.

[5] Пробелы между символами внутри операции не допускаются.

[6] Препроцессором называется предварительная фаза компиляции, то есть перевода программы с С++ на машинный язык.

[7] Приведем еще две наиболее употребительные спецификации: %d–для величин целого типа в деся­тичной системе счисления, %lf – для величин типа double. Более полный список спецификаций см. в Приложении 1.

 


1 | 2 |

Поиск по сайту:



Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.172 сек.)