Теоретические сведения. Присваивание (выражение и оператор)
Присваивание (выражение и оператор). Символ "=" в языке Си обозначает бинарную операцию, у которой в выражении должно быть два операнда - левый (обычно переменная) и правый (обычно выражение). Если z - имя переменной, то
z = 2.3 + 5.1
есть выражение со значением 7.4. Одновременно это значение присваивается и переменной z. Только в том случае, когда в конце выражения с операцией присваивания помещен символ ";", это выражение становится оператором присваивания. Таким образом,
z = 2.3 + 5.1;
есть оператор простого присваивания переменной z значения, равного 7.4.
Тип и значение выражения с операцией присваивания определяются значением выражения, помещенного справа от знака '='. Однако этот тип может не совпадать с типом переменной из левой части выражения. В этом случае при определении значения переменной выполняется преобразование (приведение).
Так как выражение справа от знака '=' может содержать, в свою очередь, операцию присваивания, то в одном операторе присваивания можно присвоить значения нескольким переменным, т.е. организовать "множественное" присваивание, например:
c=x=d=4.0+2.4;
Здесь значение 6.4 присваивается переменной d, затем 6.4 как значение выражения с операцией присваивания "d=4.0+2.4" присваивается х и, наконец, 6.4 как значение выражения "x=d" присваивается с. Естественное ограничение - слева от знака '=' в каждой из операций присваивания может быть только леводопустимое выражение (имя переменной).
В языке Си существует целый набор "составных операций присваивания" {ранг 14). Каждая из составных операций присваивания объединяет некоторую бинарную логическую или арифметическую операцию и собственно присваивание. Операция составного присваивания является основой оператора составного присваивания:
имя переменной ор=выражение;
где ор - одна из операций *, /, %, +, -, &, Ù, |, «, ». Если рассматривать конструкцию "ор=" как две операции, то вначале выполняется ор, а затем '='. Например, х*=2; z+=4; i/=x+4*z;
При выполнении каждого из этих операторов операндами для операции ор служат переменная из левой части и выражение из правой. Результат присваивается переменной из левой части.
Таким образом, первый пример можно рассматривать как обозначение требования "удвоить значение переменной х"; второй пример - "увеличить на 4 значение переменной z"; третий пример - "уменьшить значение переменной i в (x+4*z) раз". Этим операторам эквивалентны такие операторы простого присваивания:
х=х*2; z=z+4; i=i/(x+4*z) ;
В последнем из них пришлось ввести скобки для получения правильного результата. Перейти от простого оператора присваивания к составному можно только в тех случаях, когда одна переменная используется в обеих частях. Более того, для некоторых операций эта переменная должна быть обязательно первым (левым) операндом. Например, не удастся заменить составными следующие простые операторы присваивания:
a=b/a; x=z%x.
В качестве левого операнда в операциях присваивания может использоваться только модифицируемое именующее выражение (l-значение), т.е. ссылка на некоторую именованную область памяти, значение которой доступно изменениям.
Перечислим операции присваивания, отметив, что существуют одна простая операция присваивания и ряд составных операций:
= - простое присваивание: присвоить значение выражения-операнда из правой части операнду левой части. Пример: Р = 10.3 - 2*х;
*= - присваивание после умножения: присвоить операнду левой части произведение значений обоих операндов. Р *= 2 эквивалентно Р = Р * 2;
/= - присваивание после деления: присвоить операнду левой части частное от деления значения левого операнда на значение правого. Р /= 2.2 - d эквивалентно Р=- Р / (2.2 - d);
%= - присваивание после деления по модулю: присвоить операнду левой части остаток от целочисленного деления значения левого операнда на значение правого операнда. N %= 3 эквивалентно N = N % 3;
= - присваивание после суммирования: присвоить операнду левой части сумму значений обоих операндов А += В эквивалентно А = А + В;
-= - присваивание после вычитания: присвоить операнду левой части разность значений левого и правого операндов. X -= 4.3 - Z эквивалентно X = X - (4.3 - Z);
Обратите внимание, что для всех составных операций присваивания форма присваивания Е1 ор= Е2 эквивалентна Е1 = El op (E2), где ор - обозначение операции.
Запятая в качестве операции (ранг 15)
Несколько выражений, разделенных запятыми ",", вычисляются последовательно слева направо. В качестве результата сохраняются тип и значение самого правого выражения. Например, если переменная х имеет тип int, то значением выражения (х=3, 3*х) будет 9, а переменная х примет значение 3.
Стандартные математические функции (файл math.h):
Функция | Краткое описание |
abs | нахождение абсолютного значения выражения типа int |
acos | вычисление арккосинуса. Аргументы этой и других тригонометрических функций задаются в радианах |
asin | вычисление арксинуса |
atan | вычисление арктангенса х |
atan2 | вычисление арктангенса от у/х |
cabs | нахождение абсолютного значения комплексного числа |
ceil | нахождение наименьшего целого, большего или равного х |
_clear87 | получение значения и инициализация слова состояния сопроцессора и библиотеки арифметики с плавающей точкой |
_control87 | получение старого значения слова состояния для функций арифметики с плавающей точкой и установка нового состояния |
cos | вычисление косинуса |
cosh | вычисление гиперболического косинуса |
exp | вычисление экспоненты |
fabs | нахождение абсолютного значения типа double |
floor | нахождение наибольшего целого, меньшего или равного х |
fmod | нахождение остатка от деления х/у |
_fpreset | повторная инициализация пакета плавающей арифметики |
frexp | вычисляет для х вещественную мантиссу m и целое n так, что x=m*2n |
hypot | вычисление гипотенузы |
labs | нахождение абсолютного значения типа long |
ldexp | вычисление х*2e |
log | вычисление натурального логарифма |
log10 | вычисление логарифма по основанию 10 |
matherr | управление реакцией на ошибки при выполнении функций математической библиотеки |
modf | разложение х на дробную и целую часть |
pow | вычисление х в степени у |
sin | вычисление синуса |
sinh | вычисление гиперболического синуса |
sqrt | нахождение квадратного корня |
_status87 | получение значения слова состояния с плавающей точкой |
tan | вычисление тангенса |
tanh | вычисление гиперболического тангенса |
В библиотеке определен также ряд констант, таких как M_PI (число π), M_E (основание натурального логарифма e) и др.
Функция форматированного вывода.Достаточно часто для вывода информации из ЭВМ в программах используется функция printf(). Она переводит данные из внутреннего кода в символьное представление и выводит полученные изображения символов результатов на экран дисплея. При этом у программиста имеется возможность форматировать данные, т.е. влиять на их представление на экране дисплея.
Возможность форматирования условно отмечена в самом имени функции с помощью литеры fв конце ее названия (print formatted).
Оператор вызова функции printf() можно представить так:
printf(форматная строка, список _аргументов);
Форматная строка ограничена двойными кавычками и может включать произвольный текст, управляющие символы и спецификации преобразования данных. Список аргументов (с предшествующей запятой) может отсутствовать. Например:
#include <stdio.h> void main( )
{ printf ("\n Здравствуй, Мир!\n");
}
Директива #include <stdio.h>включает в текст программы описание (прототип) библиотечной функции printf(). (Если удалить из текста программы эту препроцессорную директиву, то появятся сообщения об ошибках и исполнимый код программы не будет создан. Среди параметров функции printf() есть в этом примере только форматная строка (список аргументов отсутствует). В форматной строке два управляющих символа '\n' - "перевод строки". Между ними текст, который выводится на экран дисплея:
Здравствуй, Мир!
Первый символ '\n' обеспечивает вывод этой фразы с начала новой строки. Второй управляющий символ '\n' переведет курсор к началу следующей строки, где и начнется вывод других сообщений (не связанных с программой) на экран дисплея.
Для изображения в программе соответствующих символьных констант используются комбинации из нескольких символов, имеющих графическое представление. Каждая такая комбинация начинается с символа ‘\’ (обратная косая черта - backslash). Такие наборы литер, начинающиеся с символа ‘\’, в литературе по языку Си называют управляющими последовательностями. Ниже приводится их список:
'\n'- перевод строки;
'\t' - горизонтальная табуляция;
'\r' - возврат каретки (курсора) к началу строки;
'\\' - обратная косая черта \;
'\n''- апостроф (одиночная кавычка);
'\'" - кавычка (символ двойной кавычки);
'\0'-нулевой символ;
'\а' - сигнал-звонок;
'\b'- возврат на одну позицию (на один символ);
'\f' - перевод (прогон) страницы;
'\v'- вертикальная табуляция;
'\?' - знак вопроса.
Итак, произвольный текст (не спецификации преобразования и не управляющие символы) непосредственно без изменений выводится на экран. Управляющие символы (перевод строки, табуляция и т.д.) позволяют влиять на размещение выводимой информации на экране дисплея.
Спецификации преобразования данных предназначены для управления формой внешнего представления значений аргументов функции printf(). Обобщенный формат спецификации преобразования имеет вид:
%фпажки ширина _поля.точность модификатор спецификатор
Среди элементов спецификации преобразования обязательными являются только два — символ '% ' и спецификатор.
В задачах вычислительного характера будем использовать спецификаторы:
d - для целых десятичных чисел (тип int);
u -для целых десятичных чисел без знака (тип unsigned);
f- для вещественных чисел в форме с фиксированной точкой (типы float и double);
е - для вещественных чисел в форме с плавающей точкой (с мантиссой и порядком) - для типов double и float.
В список аргументов функции printf() включают объекты, значения которых должны быть выведены из программы. Это выражения и их частные случаи - переменные и константы. Количество аргументов и их типы должны соответствовать последовательности спецификаций преобразования в форматной строке. Например, если вещественная переменная summa имеет значение 2102.3, то при таком вызове функции
printf("\n summa=%f", summa);
на экран с новой строки будет выведено: summa=2102.3
После выполнения операторов
float с, е ;
int к;
с=48.3; к=-83; e=16.33;
printf ("\nc=%f\tk=%d\te=%e", с, к, e);
на экране получится такая строка:
с=48.299999 к=-83 e=1.63300e+01
Здесь обратите внимание на управляющий символ \t (табуляция). С его помощью выводимые значения в строке результата отделены друг от друга.
Для вывода числовых значений в спецификации преобразования весьма полезны "ширина поля" и "точность".
Ширина_поля - целое положительное число, определяющее длину (в позициях на экране) представления выводимого значения.
Точность - целое положительное число, определяющее количество цифр в дробной части внешнего представления вещественного числа (с фиксированной точкой) или его мантиссы (при использовании формы с плавающей точкой).
Пример с теми же переменными:
printf ("\nc=%5.2\tk=%5d\te=%8.2f\te=%11.4e", c, k , e, e) ;
Результат на экране:
с=48.30 к= -83 e= 16.33 e= 1.6330e+01
В качестве модификаторов в спецификации преобразования используются символы:
h - для вывода значений типа short int;
I - для вывода значений типа long;
L - для вывода значений типа long double.
Ввод данных.Для ввода данных с клавиатуры ЭВМ в программе будем использовать функцию (описана в заголовочном файле stdio.h):
scanf {форматная_строка, список_аргументов);
Функция scanf() выполняет "чтение" кодов, вводимых с клавиатуры. Это могут быть как коды видимых символов, так и управляющие коды, поступающие от вспомогательных клавиш и от их сочетаний. Функция scanf() воспринимает коды, преобразует их во внутренний формат и передает программе. При этом программист может влиять на правила интерпретации входных кодов с помощью спецификаций форматной строки. (Возможность форматирования условно отмечена в названии функции с помощью литеры fв конце имени.)
И форматная строка, и список аргументов для функции scanf()обязательны. Форматную строку для функции scanf() будем формировать из спецификаций преобразования вида:
% * ширина_поля модификатор спецификатор
Среди элементов спецификации преобразования обязательны только % и спецификатор. Для ввода числовых данных используются спецификаторы:
d- для целых десятичных чисел (тип int);
u - для целых десятичных чисел без знака (тип unsigned int);
f -для вещественных чисел (тип float);
е - для вещественных чисел (тип float).
Ширина_поля - целое положительное число, позволяющее определить, какое количество байтов (символов) из входного потока соответствует вводимому значению.
В качестве модификаторов используются символы:
h- для ввода значений типа short int (hd);
l- для ввода значений типа long int (ld)или double (lf, le);
L- для ввода значений типа long double (Lf, Le).
В отличие от функции printf() аргументами для функции scanf() могут быть только адреса объектов программы, в частном случае - адреса ее переменных. Не расшифровывая понятие адреса (адресам и указателям будут рассмотрены позже), напомним, что в языке Си имеется специальная унарная операция & получения адреса объекта:
& имя_обьекта
Выражение для получения адреса переменной будет таким:
& имя_переменной
Итак, для обозначения адреса перед именем переменной записывают символ &. Если name - имя переменной, то &name -ее адрес.
Например, для ввода с клавиатуры значений переменных n, z, х можно записать оператор:
scanf ("%d%f%f",&n,&z,&x);
В данном примере спецификации преобразования в форматной строке не содержат сведений о размерах полей и точностях вводимых значений. Это разрешено и очень удобно при вводе данных, диапазон значений которых определен не строго. Если переменная n описана как целая, z и х - как вещественные типа float,то после чтения с клавиатуры последовательности символов 18 18 -0.431 переменная n получит значение 18, z — значение 18.0, х-значение -0.431.
При чтении входных данных функция scanf() воспринимает в качестве разделителей полей данных "обобщенные пробельные символы" - собственно пробелы, символы табуляции, символы новых строк.
Пример 16: Вычисление объема цилиндра.
/*Вычисление объема прямого цилиндра*/
#include <stdio.h>
void main( )
{
double h, r, v;
const float PI = 3.14159;
/*h - высота цилиндра, r -радиус цилиндра*/
/*v - объем цилиндра, PI - число "пи" */
printf("\n Радиус цилиндра r= ");
scanf("%lf", &r);
printf("Высота цилиндра h= "); ;
scanf("%lf”, &h);
v = h * PI * r * r;
printf("Объем цилиндра: %10.4f" ,v):
}
В тексте программы несколько особенностей. Определена константа PI, т.е. со значением 3.14159 связано имя PI, которое до конца выполнения программы будет именовать только это значение.
Перед каждым вводом помещены вызовы функции printf(), выводящей на экран запрос-подсказку, вслед за которой на экране отображается набираемое на клавиатуре вводимое значение. Функция scanf() считывает только это значение, как только будет нажата клавиша "Ввод" (Enter), что воспринимается как признак конца строки ввода. Поэтому очередной вызов функции printf() выводит данные на следующую строку. Обратите внимание на спецификации преобразования %lf Если бы переменные h и r имели тип float,то в форматных строках функций scanf() нужно было бы применять спецификации %f или %е. Текст на экране при выполнении программы может быть таким:
радиус цилиндра r= 2.0
высота цилиндра h= 4.0
Объем цилиндра: 50.2654
Здесь пользователь ввел 2.0 для г и 4.0 для h. Другой вариант:
радиус цилиндра r= 4.0
высота цилиндра h= 2.0
Объем цилиндра: 100.5309
Еще раз обратите внимание на использование в функции scanf() не имен переменных, а их адресов &r, &h.
Сумма членов ряда Фибоначчи.Ряд Фибоначчи определен, если известны первые два его члена f1, f2, так как очередной член fi =fi-1 + fi-2 для r>2. Необходимо вычислить сумму заданного количества (k) первых членов ряда Фибоначчи, если известны первые два: р = F1 и r = F2. Следующая программа решает эту задачу:
/*Вычисление суммы членов ряда Фибоначчи*/
#include <stdio.h>
void main( )
{
int k,i;/*к-число членов; i-номер члена */
float s,p,r,f; /* s - искомая сумма */
/*Члены: р -первый; r - второй; f- i-й*/
Ml: printf("\n Введите число членов ряда k=") ;
scanf ("%d",&k) ;
if( k > 2 ) goto M2;
printf("\n Ошибка! k должно быть > 2 !");
goto Ml;
M2: printf("\n Первый член ряда р=") ;
scanf("%f",&p);
printf("\n Второй член ряда r=");
scanf("%fn,&r);
i = 3;
s = p + r;
M: f = p + r;
s = s + f;
p = r;
r = f ;
i = i + 1;
if ( i <= k ) goto M;
printf("\n Сумма членов ряда: %10.3f", s);
}
Обратите внимание на строки, где выполняется проверка введенного значения k. Программа может правильно работать только при к>2, поэтому только в этом случае выполняется переход к метке М2. В противном случае печатается сообщение об ошибке, и после перехода к метке Ml запрашивается новое значение k.
Особенность и недостаток программы состоят в том, что она никогда не закончит вычислений, если не ввести допустимого значения к>2.
Ход работы
1 Изучить теоретические сведения.
2 Выполнить загрузку интегрированной среды разработки С (IDE) для Borland C, расположенной в каталоге N:\APL\BC\BIN\BC.EXE, из активной директории.
3 Ознакомиться с форматом функций printf()иscanf().
4 Скопировать примеры для функций printf, scanf из встроенной помощи в активное окно и изучить их работу. Изучить синтаксические конструкции, приведенные во встроенной помощи.
5 Выполнить загрузку программ-примеров (N:\APL\TC\LAB\*.CPP),их корректировку с использованием различных возможностей функций printf (), scanf (),сохранение файлов и компиляцию.
6 Написать отчет и сделать выводы по работе.
7 Подготовиться к защите лабораторной работы, изучив вопросы по данной теме, изучив контрольные вопросы по теме.