Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка по программированию.doc
Скачиваний:
11
Добавлен:
13.11.2019
Размер:
1.2 Mб
Скачать

Void decart(double r, double f)

{

double pil80=Pi/180;

X=r*cos(f); Y=r*sin(f);

}

Void main()

{

double rr.ff;

scanf(“%lf %If'”,&rr.&ff);

decart(rr,ff);

printf(“%lf %lf",X,Y);

}

Прежде всего, поясним новый элемент программы, появившийся в третьей строке. Мы уже говорили, что конструкции, начинающиеся символом #, являются ин­струкциями препроцессору. Такие инструкции предпи­сывают системе еще до начала компиляции произвести над программой некоторые предварительные действия. Так, инструкция #include предписывает подключить к программе соответствующий заголовочный файл. По ин­струкции #define АAА ВВВ препроцессор просматривает весь текст программы и везде, где встречается фрагмент ААА, производится его замена на фрагмент ВВВ. Под­черкнем, что замена делается именно в тексте еще до компиляции программы. Необходимость в использовании этой препроцессорной инструкции возникает только в особых случаях, с которыми, однако, читателю, возмож­но, придется столкнуться, что и побудило нас включить эту конструкцию в программу.

Функция decart в данной программе не возвраща­ет никакого значения и поэтому имеет тип void. В те­ле функции описана локальная переменная pil80, кото­рая получает значение, используемое для преобразования углов из градусной меры в радианную. Использование здесь локальной переменной явно нецелесообразно. Автор сознательно допустил это для того, чтобы читатель сам попробовал сделать необходимые корректировки. Пере­дача в главную функцию вычисленных в decart значе­ний осуществляется с помощью глобальных переменных Х и Y.

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

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

const double pil80=3.1415927/180;

Void decart(double r,double f,double *X,double*y)

{

*x=r*sin(f*pil80);

*y=r*cos(f*pil80);

}

Void main()

{ double r,f,x,y;

scanf("%lf %lf”,&r,&f);

DECART(r,f,&x,&y);

printf("%lf %1f",x,y);

}

Для начала мы оптимизировали определение значе­ния pi180. Теперь оно стало вещественной константой, которая не может и не должна меняться нигде в про­грамме. Кроме того, сразу задано ее числовое значение через деление пифагорова числа на 180. Эта операция делается в программе один раз, что и является наиболее оптимальным.

Функция DECART имеет четыре аргумента. Два пер­вых - обычные переменные типа double, а третий и четвертый - указатели на double. Тело функции со­стоит из двух выражений присваивания. Первое из них следует понимать так: "По адресу, указанному третьим аргументом функции, записать значение, равное произведению первого аргумента на синус второго аргумента, умноженного на значение константы pi180". Аналогич­ную сентенцию можно сочинить и для второго выраже­ния присваивания.

В главной функции описаны четыре вещественные пе­ременные: r, f, х, у. Значения первых двух вводятся с консоли и далее используются как "входные" параметры в функции DECART. Значения х и у формируются в ре­зультате работы этой функции. Поскольку на месте двух последних аргументов должны стоять указатели, мы и написали в вызове функции DECART &x и .

Изложенные только что представления позволят нам окончательно разобраться с функцией scanf. Вспомним, что инициализируемую с консоли переменную мы снаб­жали символом & перед ее именем. Сейчас стало по­нятным, почему это необходимо. Функция scanf должна изменить значение вводимой переменной — единствен­ная возможность сделать это без привлечения глобаль­ных объектов заключается в использовании указателей. Именно по этой причине аргументом функции scanf является не сама переменная, а ее адрес.

Рассмотрим еще один пример на использование "са­модельной" функции без параметров. В этом примере мы познакомимся с еще одним генератором случайных чи­сел, описанным в заголовочном файле stdlib.h. Эта функция называется random, имеет аргумент типа int и возвращает целое случайное число из диапазона от 0 до N-1(включительно), где N — значение аргумента функции. С помощью этой функции изготовим генератор вещественных слу­чайных чисел в диапазоне от 0 до 1, В главной функции генератор будет использован для заполнения веществен­ного массива случайными числами:

#include<stdlib.h>

const double g=l./31999.;

double RN()

{

return random(32000)*g;

}