Цель работы
Изучение способов задания макроопределений, библиотеки математических функций и функций форматированного ввода и вывода.
Методические указания
1. Макроподстановка в тексте программы
Препроцессор просматривает текст программы перед ее компилированием и, встретив директиву
#define ИМЯ СТРОКА,
далее в тексте заменяет все отдельные вхождения вида ИМЯ на набор символов СТРОКА (пробелы слева и справа от СТРОКА игнорируются). Например, если дано макроопределение
# define PI 3.14
и в тексте встречается оператор
x = PI/2;
то препроцессор заменит PI на набор символов 3.14 и этот оператор примет следующий вид:
x = 3.14/2;
При этом любое вхождение символов pi в состав других имен игнорируется. Например, встретив имя picture, препроцессор оставит его без изменений.
Директива
# define ИМЯ (ИМЯ 1, ИМЯ 2,...) СТРОКА
без пробелов между ИМЯ и открывающей круглой скобкой является макроопределением с аргументами. Например, если дано макроопределение
# define square (i) i*i
и в тексте программы встретится оператор
j =square (2);
то препроцессор до компиляции программы заменит его оператором
j = 2*2;
Запись символа \ в конце директивы означает, что следующая строка является продолжением набора символов СТРОКА. Следующий фрагмент является текстом вполне законченной программы:
# define my-program main () \
{ int i = 2; \
printf(²\n i = %d², i); \
}
my - program;
После работы препроцессора над программой компилятор получит следующий текст:
main ()
{ int i = 2;
printf(²\n i = %d², i);
}
Библиотека Турбо Си
Библиотека Турбо Си содержит свыше 300 наиболее часто употребляемых в практике программирования функций. Чтобы программа при выполнении могла вызывать библиотечную функцию, в ее текст необходимо включить файл заголовков, в котором объявлена или описана эта функция. Например, математическая функция арктангенса объявлена в файл заголовков math.h и для ее вызова необходимо включить файл math.h в текст программы:
|
# include <math.h>.
Некоторые компиляторы находят библиотечные функции, даже если соответствующие файлы заголовков не включены в текст программы. Рекомендуется всегда включать требуемые файлы заголовков, так как они содержат еще и макроопределения и описания некоторых параметров, задающие режимы нормального функционирования библиотечных функций. А некоторые библиотечные функции полностью описаны в файле заголовков.
2.Математические функции
Эти функции объявлены в одной из наиболее важных файлов с именем stdlib.h и в специальном файле math.h. В файле stdlib.h среди множества других объявлены некоторые математические функции (табл. 1). В файле math.h объявлены функции, перечисленные в табл. 2, и даны макроопределения часто используемых констант, округленных до 21 значащей цифры (табл. 3).
Таблица 1
![]() ![]() | Обозначение в языке | Типы значений аргумента функции | |
Абсолютное значение | Abs (i) Labs (l) | int long | int long |
Генератор случайных чисел в диапазоне от 0 до 32767 | Rand () | _______ | int |
Инициализатор генератора случайных чисел начиная с целого числа n | Srand (n) | int | _________ |
Таблица 2
![]() ![]() | Обозначение в языке | Типы значений Аргумента функции |
Арккосинус | Acos(x) | Double double |
Арксинус | Asin(x) | Double double |
Арктангенс | Atan(x) | Double double |
Арктангенс с 2 от ![]() | Atan2(y,x) | Double double |
Косинус | Cos(x) | Double double |
Синус | Sin(x) | Double double |
Тангенс | Tan(x) | Double double |
Косинус гиперболичес-кий | Cosh(x) | Double double |
Окончание табл.2
|
Синус гиперболичес-кий | Sinh(x) | Double double |
Тангенс гиперболичес-кий | Tanh(x) | Double double |
Округление до большого целого | Ceil(x) | Double double |
Округление до меньшего целого | Floor(x) | Double double |
Экспонен-циальная функция ex | Exp(x) | Double double |
Экспонен-циальная функция x.2n | ldexp(x,n) | Double, int double |
Степенная функция xy | pow(x,y) | double, double double |
Степенная функция 10n | pow10(n) | int double |
Натуральный логарифм | log(x) | Double double |
Десятичный логарифм | log10(x) | Double double |
Корень натуральный | sqrt(x) | Double double |
Остаток от деления x на y | fmod(x,y) | Double, double double |
Таблица 3
№ | Обозначение в файле math.h | Обозначение в математике |
M_E | Натуральное число е | |
M_LOG2E | log2(e) | |
M_LOG10E | lg(e) | |
M_LN2 | ln(2) | |
M_LN10 | ln(10) |
Окончание табл.3
M_PI | число p | |
M_PI_2 | p/2 | |
PI_4 | p/4 | |
M_1_PI | 1/p | |
M_2_PI | 2/p | |
M_1_SQRTPI | 1/ ![]() | |
M_2_SQRTPI | 2/ ![]() | |
M_SQRT2 | ![]() | |
M_SQRT_2 | ![]() |
3. Функции форматирования ввода и вывода
Существуют различные библиотечные функции ввода исходных данных с клавиатуры и вывода результатов на экран. Со всеми стандартными типами значений аргументов работают только функции форматирования ввода scanf и вывода printf. Они работают с одним и тем же множеством типов и по одним и тем же правилам языка Си. Поэтому между ними много общего на уровне формальной записи. Например, они одинаково объявлены в файле stdio.h и обе возвращают количество успешно обработанных символов. Синтаксис вывода этих функций также выглядит внешне схожим образом:
|
printf (управляющая строка [, список аргументов])
scanf (управляющая строка, список аргументов).
В действительности же они выполняют различные действия: функция printf отображает значения программных объектов на экране, а scanf принимает последовательность символов с клавиатуры и преобразует их в значения программных объектов. Управляющая строка в вызове printf определяет форму отображения значений, а в вызове scanf - способ истолкования введенной последовательности символов. Вызов функции scan f обязательно должен содержать адреса программных объектов (то есть обязательный список указывает эти адреса), а вызов printf может содержать (может и не содержать) список выражений, значения которых отображаются на экране.
3.1 Функция форматирования вывода на экран
Функция printf объявлена в файле stdio.h. Синтаксис ее вызова выглядит следующим образом:
printf (управляющая строка [, список аргументов])
При этом список аргументов может быть пустым. Если же список не пустой, то на месте любого аргумента должно быть выражение, значение которого определяется компьютером до передачи управления функции printf. Управляющая строка - это заключенная в кавычки последовательность символов. Она показывает, как должны быть отображены значения аргументов, он содержит объект трех типов:
обычные символы, вводимые текстуально на экран;
спецификации преобразования (форматы), каждая из которых указывает формат отображения значения определенного аргумента из списка. Каждому аргументу в определенном месте должна быть указана спецификация преобразования. Спецификация преобразования обязательно начинается символом % и заканчивается символом типа (таблица 4);
Управляющие символьные константы (см. лабораторную работу № 1).
Проанализируем следующую программу:
# include <math.h>
# include <stdio.h>
main ()
{ const char s [ ] = ²Сумма²;
float e = M_E, pi = M_PI;
print f (²\n %s %d-x чисел %f и %f равна %f²,
s, 2, e, M_PI, M_E + pi);
}
Результат выполнения этой программы на экране отобразится в следующем виде:
Сумма 2-х чисел 2.718282 и 3.141593 равна 5.859875
В программе использованы макроопределения чисел е (М_Е) и p (M_PI), заданных директивами #define в файле math.h (таблица 3).
Вызов функции printf содержит управляющую строку
²\n %s %d-x чисел %f и %f равна %f²
и список аргументов
s, 2, e, M_PI, M_E + pi
Управляющая строка содержит символьную константу \n и печатаемые текстуально символы:
_, - х _ чисел_, _ и _, _ равна _,
где знаком _ обозначены пробелы.
Каждому аргументу из списка соответствует свой спецификатор преобразования. Например, строковой константе s соответствует спецификатор %s, целой константе 2 - %d, действительному значению е - %f, константе M_PI - %f, значению M_E + pi - %f.
В таблице 4 приведены обозначения спецификаторов преобразования и соответствующие им типы вводимых значений.
Для ввода последовательности символов можно обойтись без спецификации преобразования и аргумента. Например, оператор
printf (²\n Сидоров Иван Петрович²);
с новой строки напечатает
Сидоров Иван Петрович
Таблица 4
Спецификатор преобразования | Тип вводимого значения |
% d | Десятичное целое число |
% c | Один символ |
% s | Строка символов |
% e | Число с плавающей точкой, экспоненциальная запись |
% f | Число с плавающей точкой, десятичная запись |
% g | Выбрать наиболее короткую форму вывода % e и % f |
% u | Десятичное число без знака |
% o | Восьмеричное число без знака |
% x | Шестнадцатеричное число без знака |
В управляющей строке символ % используется для обозначения спецификатора преобразования. Поэтому принять правило: для вывода символа % в управляющей строке нужно дважды указать этот символ - %%. Например, оператор
printf (²\n 0.5 - это 50 %% от 1²);
на экране отобразит
0.5 - это 50 % от 1
3.2.Модификаторы преобразования
Спецификатор преобразования всегда начинается символом % и заканчивается указателем типа, как перечислено в таблице 4. В общем случае он может содержать и другие необязательные поля:
%[flag][width][.prec][F½N½h½l] mun
В прямоугольных скобках перечислены необязательные поля.
Если на месте flag нет ничего, то это означает ²вводимое значение выравнивать по правому краю, заполняя оставшиеся слева поля пробелами². Для выравнивания по левому краю на месте flag нужно записать знак -. При выводе числовых значений можно потребовать, чтобы всегда ставился знак числа, тогда на месте flag пишут символ +. Если же на месте flag стоит пробел (пробел означает ‘пусто’), то знак числа указывается только для отрицательного числа.
На месте слова width десятичным целым числом n указывают, что при выводе нужно использовать по крайней мере n позиций, заполняя не используемые позиции пробелами.
На месте слова prec целым числом m указывают, что при выводе дробной части действительного числа нужно использовать не более m позиций.
Символ l указывает, что соответствующий аргумент имеет значение типа long.
Например, в результате вывода:
printf(²\n \t i =% ld; \n j = %d, a = %6.2 f. \n², i, j, a);
при условии, что i= 123456, j = 127, а = 86,531, будет выведена информация вида:
i = 123456;
j = 127, a = 86,53.
Следующий оператор десятичное целое 336 выводит на экран в десятичной, восьмеричной, шестнадцатеричной формах:
printf(²\n %d. %0 %x²,336, 336, 336);
На экране увидим:
336 520 150
Оператор
printf(²\n %с %d²,’A’, ‘A’);
на экране увидим результат
А 65,
где А - это значение выражения ‘A’, а 65 - десятичный код ASCII символа А.
3.3. Функция форматированного ввода
При вызове функции форматированного ввода scanf используются такие же форматы, как и при вызове функции printf. Но нужно четко соблюдать два правила:
Для ввода значения переменной (например, х) в список аргументов включается имя переменной со знаком &(scan (²% f², &x));
Для строковых переменных символ & не используется. Например,
char *str;
scan f (²% s², str);
В спецификаторах преобразования функция scan f имеет следующие отличия:
Отсутствует формат %g.
Форматы %f и %e эквивалентны.
Для чтения целых типа short используется формат %h.
Управляющая строка содержит спецификации преобразования и используется для установления количества и типов аргументов, в нее могут включаться:
1) пробелы, символы табуляции и перехода на новую строку (все они игнорируются при вводе),
2) спецификаторы преобразования.
Исходные данные во входном потоке записываются (то есть набираются на клавиатуре) через один или несколько пробелов, символов табуляции или новой строки. Если входные данные в каком-то месте разделяются другими символами, то и в управляющей строке соответствующие этому месту спецификаторы преобразования должны быть разделены точно такими же символами.
Для повышения надежности работы с программой рекомендуется организовать несложные операции ввода и сопровождать эти операции приглашениями ко вводу. Например, аргумент программы
printf(²%n Введите через пробелы значения x и y Þ²);
scanf (²% f %f², &x, &y);
на экране отобразит
Введите через пробелы значения x и y Þ __
и курсор будет мигать на месте, где указан символ подчеркивания.
4. Пример выполнения задания
Составить программу, которая вычисляет значения x и z при
x = arctg (1);
y = tg(x) + sin2(x) - x-3 + ln (x + p) - lg(x + ex),
z = 1 + .
Программа может иметь следующий вид:
# include <math.h>
# include <stdio.h>
# define FIO ²Сидоров Иван Петрович²
# define GR ²студент группы 111²
# define LR2 ²лабораторная работа 2²
main ()
{ float y, z; const float x - atan (1.);
int yy, dd, mm;
printf (²\n Через пробелы введите номер года, месяца и числа:²);
scanf (²%d %d %d², &yy, &mm, &dd);
printf (²\n %d.%d.%d², dd, mm, yy);
printf (²\n %s \n %s_ %s², LR2,GR,FIO);
printf (²\n исходные данные: x = %e², x);
y = tan(x) + pow(sin(x),2) - pow(x, -3)+
log(x + M_PI) - log10(x + exp(x));
z = pow(y, 1./3) + 1;
printf (²\n Результаты: y = %f z = %f², y, z);
{
При выполнении программы на экране появится следующая информация:
Через пробелы введите номер года, месяца, числа: 1998 3 5
5.3.1998
Лабораторная работа 2
Студент группы 111 Сидоров Иван Петрович
Исходные данные: x = 7.85398e-01
Результат: y = 0.329752 z = 1.690869
Контрольные вопросы
Какие действия и на каком этапе выполняются в соответствии с директивой # define?
Из каких частей состоит директива макроопределения?
Каков синтаксис вызова функции форматированного ввода?
Каков синтаксис вызова функции форматированного вывода?
Какой смысл несут в себе аргумент в вызовах функций print f и scan f?
Каковы основные отличия между функциями print f и scan f?
Как узнать восьмеричный код ASCII символа?
Как записать оператор форматированного ввода трех целых десятичных чисел, разделенных при вводе запятыми?