Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Программирование задачи. Программирование подобного класса задач опирается на структуры предыдущего раздела, с учетом особенностей

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

Каждая из функций Си представляется одной из упрощенных структур

[тип] имя([тип b1,...,тип bi,...,тип bn,тип *d1,...,тип *dj,...,тип *dm])

{

тело

функции

[return РВ;]

}

где имя – идентификатор (название) функции;

тип – описатель типа функции (результата);

bi – список входных формальных параметров с указанием типа каждого;

dj – список выходных формальных параметров – указателей, определяющих возвращаемые результаты, с указанием типа каждого и признака указателя при описании (*);

() – ограничители списка формальных параметров;

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

return РВ; – оператор возврата (return) результата вычислений;

РВ – результат вычислений (выражение);

[ ] – признак необязательности содержимого;

{ } – ограничители тела функции.

Первую строка структуры является заголовком функции.

 

Структура вызова функции:

имя ([a1,..., ai,..., an,c1,..., cj,..., cm])[;]

где имя – идентификатор функции;

a1, ai, an – список входных фактических параметров (аргументов), численные значения которых требуется передать в дополнительную функцию (подпрограмму);

c1, cj, cm – список адресов выходных фактических параметров (аргументов), численные значения которых требуется получить из дополнительной функции (подпрограммы);

() – ограничители аргументов;

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

Прототип функции аналогичен ее заголовку и имеет структуру

[тип] имя([тип b1,...,тип bi,...,тип bn,тип *d1,...,тип *dj,...,тип *dm]);

где имя – идентификатор (название) функции;

тип – описатель типа функции (результата);

bi – список входных формальных параметров с указанием типа каждого;

dj – список выходных формальных параметров – указателей, определяющих возвращаемые результаты, с указанием типа каждого и признака указателя при описании (*);

() – ограничители списка формальных параметров;

[ ] – признак необязательности содержимого;

; – признак оператора.

Правила записи и использования функций с несколькими возвращаемыми значениями совпадают с указанными ранее для функций с одним результатом со следующими дополнениями:

7. количества и типы входных и выходных формальных параметров должны соответствовать аналогичным фактическим, т.е. каждый ai имеет свой bi, а каждый cj – свой dj, при этом тип и взаимное расположение их в списке определяется программистом;

8. в качестве входных формальных параметров используются переменные;

9. в качестве выходных формальных параметров используются указатели;

10.в качестве входных фактических параметров используются константы, переменные, вызовы функций, выражения и адреса массивов;

11.в качестве выходных фактических параметров используются адреса переменных и адреса массивов;

12.каждое обращение к подпрограмме, как правило, оформляется как отдельный оператор, в соответствии с требованиями алгоритма;

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

14.при использовании структуры с оператором return, вызов функции может служить операндом выражения в вызываемой функции;

15.если логика задачи не позволяет выделить основной результат, то использование оператора return необязательно. В этом случае в заголовке дополнительной функции в качестве описателя типа необходимо указывать ключевое слово void;

16.вызов функции, оформленный простым оператором, заканчивается символом «;», если является операндом выражения – признак оператора не указывается;

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

18.в списке формальных параметров прототипа допускается опускать их имена, оставляя для входных их типы, а для выходных типы с последующими символами «*».

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

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

Рис. 6.6. Передача параметра по значению

 

Рис. 6.7. Передача параметра по адресу

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

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

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

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

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

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

... main() { int j = 1, i = 1; ... printf("j=%d i=%d", j, i); func(j, &i); printf("j=%d i=%d", j, i); ... } void func(int j, int *pi) {... *pi = 0.5 * j + 1.; j = 2; ... }

Так фрагмент программы в качестве фактических параметров использует входной – переменную j и выходной – адрес переменной i. Этим параметрам в вызываемой подпрограмме соответствуют одноименный входной формальный параметр – переменная j и выходной – указатель pi. В теле подпрограммы численные значения обрабатываемых переменных i и j изменены (i – с помощью разадресации указателя pi, j – напрямую). Выполнение программы приведет к выводу исходных значений j и i (j=1 i=1), а затем их же значений после обращения к дополнительной функции (j=1 i=1.5). Значение входного фактического параметра j не изменилось, а выходного (i) – приняло новое значение. Это произошло потому, что обработка параметра j велась по схеме 1 (разные ячейки), а обработка параметра i – по схеме 2.

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

Перед составлением программы решения примера 6.3 выполним идентификацию переменных (табл. 6.3).

Таблица 6.3

Обозначение в алгоритме   n m i j xi yj
Обозначение в программе   n m i j x[ i ] y[ j ]

 

Окончание табл. 6.3

  SX PX SY PY d k z i SZ PZ
  sx px sy py d k z[ i ] sz pz

 

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

sp(x, n, &sx, &px); и sp(y, m, &sy, &py);

а заголовок дополнительной функции преобразуется к виду

void sp(float *z, int k, float *sz, *pz)

т. е. входные параметры передаются по значению, а выходные через адреса.

 

Программа решения примера 6.3

#include <stdio.h> /* stdio.h - файл с прототипами функций ввода-вывода */

#include <conio.h> /* conio.h - файл с прототипом функции getch(), clrscr() */

#include <math.h> /* math.h - файл с прототипами математических функций*/

 

void sp(float *z, int k, float *sz, float *pz); /*прототип функции sp */

 

main() /* заголовок головной функции */

{

float d, sx, px, sy, py, x[30], y[50]; /* описатели локальных */

int i, j, n, m; /* переменных и массивов */

clrscr();

printf("\n Введите значения n, m: ");

scanf("%d%d", &n, &m);

fprintf(stdout,"\n n=%d m=%d\n", n, m);

for(i = 0; i < n; i++) /* заголовок цикла ввода x[ i ] */

{

printf(" Введите значение x(%d): ", i+1);

scanf("%f", &x[i]);

}

for(i = 0; i < n; i++) /* заголовок цикла вывода x[ i ] */

fprintf(stdout," %.2f",x[i]);

printf("\n"); /* перевод курсора в начало следующей строки */

for(j = 0; j < m; j++) /* заголовок цикла ввода y[ j ] */

{

printf(" Введите значение y(%d): ", j+1);

scanf("%f", &y[j]);

}

for(j = 0; j < m; j++) /* заголовок цикла вывода y[ j ] */

fprintf(stdout," %f",y[j]);

sp(x, n, &sx, &px); /* вызовы дополнительной функции */

sp(y, m, &sy, &py); /* оформленные простыми операторами */

d = (sx + sqrt(fabs(py))) / (log(px) - sy); /* вычисление d*/

fprintf(stdout,"\n sx=%.2f px=%.2f sy=%.2f py=%.2f d=%.2f \n",

sx,px, sy, py, d);

getch();

}

 

/* определение функции sp */

void sp(float *z, int k, float *sz, float *pz)

{

int i; /* описание локальной переменной i */

*sz = 0;

*pz = 1;

for(i = 0; i < k; i++) /* заголовок цикла расчета суммы */

{

*sz = *sz + z[ i ];

*pz = *pz * z[ i ];

fprintf(stdout,"\n %2d %6.2f %8.2f %12.2f ",

i+1, z[ i ], *sz, *pz);

}

}

5 6

1 1.6 1.8 15 23

0.6 0.76 0.99 180 67.7 200

В программе использованы только два массива – на 30 и 50 элементов. Первый из них используется как фактический под именем x и формальный под именем z, второй, аналогично, под именами y и z. Отсутствие оператора return определяется равнозначностью возвращаемых значений.

 

<== предыдущая лекция | следующая лекция ==>
Составление алгоритма решения. Анализ показывает, что решение задачи требует двукратного вычисления суммы и произведения элементов массива | Математическая формулировка. Подпрограмма с результатом – массивом
Поделиться с друзьями:


Дата добавления: 2014-01-07; Просмотров: 257; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.044 сек.