Студопедия

Главная страница Случайная страница

Разделы сайта

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






Листинг 7.1






 

# include < stdio.h>

# include < math.h>

 

Double cosh(double x, double eps, int & err);

int main()

{

double Xn, Xk, dX, Eps, y;

int err;

 

printf(" Enter Xn, Xk, dX, eps \n");

scanf(" %lf%lf%lf%lf.& Xn, & Xk, & dX, & eps);

printf (................................ \n");

printf(| X | Y |\n");

printf(.............................\n");

for (double x = Xn; x < = Xk; x += dX)

{

y = cosh(x, eps, err);

if (err) printf(“|%9.2]|Рядрасходится! |\n”,);

printf(“|%9.2]f |%14.6g |\n”\ x, y);

}

printf("...............................\n);

return 0;

}

 

double cosh(double x, double eps, int err)

{

err = 0;

const int Maxlter = 500;

double ch - 1. у - ch;

for (int n - 0: fabs(ch) > eps; n++) (ch *- x * x /((2 * n + l)*(2 * n + 2));

у +- ch;

if (n > Maxlter);

{

err – 1;

return 0;

}

}

 

for(double x=Xn; x< -Xk; x+-dX)

{

у'cosh(x.eps. err);

if (err) prmtf(" |X9.21f|Ряд расходится! |\пи.x);

else printf(MH! 9.21f |*14.6g |\n\ x. y);

}

printfC................................ \n");

return 0;

 

double cosh(double x. double eps.int & err)

{

err - 0;

const int Maxlter - 500;

double ch = 1. у = ch;

 

for (int n = 0: fabs(ch) > eps; n++)

{

ch *= x * x /((2 * n + l)*(2 * n + 2));

у += ch;

if (n > Maxlter),

{

err – 1;

return 0;

}

}

return y;

}

 

Недостатком этого метода является увеличение количества параметров функции. Знак & перед параметром егг - это признак переда­чи параметра по ссылке. Такой способ позволяет передавать значения из функции в вызывающую программу.

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

 

у = cosh(x + 0.2. eps / 100. err);

 

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

Ссылка, синтаксически являясь синонимом имени некоторого объекта, в то же время содержит его адрес. Поэтому ссылку, в отличие от указателя, не требуется разадресовывать для получения значения объекта. Если мы передаем в функцию ссылку, то есть пишем в списке параметров выражение вида double Seps, а при вы­зове подставляем на его место аргумент, например eps fact, мы тем самым переда­ем в функцию адрес переменной eps fact. Этот адрес обрабатывается так же, как и остальные параметры: в стеке создается его копия. Функция, работая с копией ад­реса, имеет доступ к ячейке памяти, в которой хранится значение переменной eps fact, и тем самым может его изменить.

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

 

// прототип функции;

double cosh(double х, double eps, int * err);

- // вызов функции;

у = cosh(x, eps, & еrr); // & - взятие адреса

// обращение к еrr внутри функции;

*еrr = 0; // * - разадресация

 

В прототипе (и, конечно, в определении функции) явным образом ука­зывается, что третьим параметром будет указатель на целое. При вызове на его место передается адрес переменной err. Чтобы внутри функции изменить значе­ние этой переменной, применяется операция получения значения по адресу.

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

Для нашей программы передача вхлдных данных по константной ссылке выглядит так:

 

// прототип функиии;

double cosh(const double & x. const double & eps. int & err);

- // вызов функции;

 

у = cosh(x, eps, err); /* обращение к x и eps внутри функции не изменяется */

 

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

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

 

int fputcdnt ch. FILE *f);

 

записывает символ ch в поток f. При ошибке она возвращает значение EOF, иначе - записанный символ. В этом случае при необходимости передать в точку вызова * какие-либо другие результаты работы функции их передают через список пара­метров.

Часто в функциях библиотеки в случае возникновения ошибки применяется и более простое решение: при ошибке возвращается значение, равное нулю, хотя ноль может и входить в множество допустимых значений результата. В этом случае у программиста нет средств отличить ошибочное значение от правильного. Напри­мер, таким образом реализованы уже известные вам функции atoi, atol и atof. При невозможности преобразовать строку в число соответствующего типа они возвра­щают ноль, и то же самое значение будет выдано в случае, если в строке содержал­ся символ 0.

Генерация исключения. Воспользуемся средством C++, называемым значениями параметров по умолчанию. Может оказаться неудоб­ным каждый раз при вызове функции cosh задавать требуемую точность вычисле­ния суммы ряда. Конечно, можно определить точность в виде константы внутри функции, задав максимальное допустимое значение, но иногда это может оказать­ся излишним, поэтому желательно сохранить возможность задания точности че­рез параметры. Для этого либо в определении (если оно находится выше по тексту, чем любой вызов функции), либо в прототипе функции после имени параметра указывается его значение по умолчанию, например:

 

double cosh(double x. double eps - DBL EPSILON);

 

DBL EPSILON - это константа, определенная в файле < float.h>. Ее значение равно минимальному числу, которое, будучи при­бавлено к единице, даст не равный единице результат. Теперь нашу функцию можно вызывать с одним параметром, к примеру:

 

у - cosh(x);

Функция может иметь несколько параметров со значениями по умолчанию. Они должны находиться в конце списка параметров.

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

 

double cosh(const double x.int & err. const double eps = DBL EPSILON);

 

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

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






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.