Язык Си в примерах/Учимся складывать: различия между версиями
Содержимое удалено Содержимое добавлено
ISbot (обсуждение | вклад) м Замена <tt /> на <code />; избыточные <big /> и <font /> вокруг <source />; {{SUBPAGENAME}}; пробелы. |
Выделены три раздела; дополнения и удаления (NB: материал следует выборочно вернуть); ссылки на стандарт. |
||
Строка 1:
{{{{BASEPAGENAME}}/Содержание
Разнообразные вычисления
моделирование, решение алгебраических и дифференциальных уравнений
это то, для чего и создавались первые компьютеры.
Давайте и мы научимся использовать компьютер для вычислений.
Начнём со сложения двух чисел.
== Вариант «простой» ==
В отличие от рассмотренной ранее [[../Простейшая программа «Hello World»|простейшей программы]], в данной задаче нам потребуются [[w:Переменная (программирование)|переменные]] — ячейки памяти, в которые функция ввода сохранит введенные пользователем числа, подлежащие сложению.
Как и функции (в том числе <code>main</code>), объявление переменных в Си предполагает указание их типов. Основные числовые типы языка — <code>int</code> ([[w:Целое число|целые числа]] фиксированной разрядности) и <code>double</code> ([[w:Число с плавающей запятой|числа с плавающей запятой]].) Поскольку мы уже использовали тип <code>int</code> в описании функции <code>main</code>, применим его же в данной задаче.
<source lang="c">
#include <assert.h>
#include <stdio.h>
int
main ()
{
int a, b;
int r
= scanf ("%d%d", &a, &b);
assert (r == 2);
printf ("%d\n", a + b);
return 0;
}
</source>
Рассмотрим выполнение этой программы почти с ее завершения — вызова функции <code>printf</code>.<ref name="fprintf" >[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=327 WG14 N1570 Committee Draft — April 12, 2011] 7.21.6.1 ''The fprintf function''</ref> Данная функция выведет целое число в десятичной форме (согласно ''указателю преобразования'' <code>%d</code>), завершая вывод [[w:Перевод строки|переводом строки]] (<code>\n</code>).
Число, которое будет выведено, является результатом вычисления выражения <code>a + b</code> — или же, проще говоря, — суммой значений переменных <code>a</code> и <code>b</code>.
Вводимые пользователем числа помещаются в эти переменные функцией <code>scanf</code>, вызываемой в коде выше как <code>scanf ("%d%d", &a, &b)</code>.<ref name="fscanf" >[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=335 WG14 N1570 Committee Draft — April 12, 2011] 7.21.6.2 ''The fscanf function''</ref> Здесь, как и в <code>printf</code>, используется указатель преобразования <code>%d</code>, означающий на этот раз ''считывание'' числа в десятичной форме (возможно — предваряемого пробелами). Поскольку указатель повторен дважды, будет считано два числа, которые будут помещены в упомянутые в аргументах переменные <code>a</code> и <code>b</code>. (Необходимый здесь унарный оператор <code>&</code> оставим пока без внимания.)
Как и <code>printf</code>, функция <code>scanf</code> ''объявлена'' в ''заголовке'' (англ. {{lang|en|header}}) <code>stdio.h</code>.<ref name="stdio.h" >[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=314 WG14 N1570 Committee Draft — April 12, 2011] 7.21 ''Input/output <code>stdio.h</code>''</ref>
В [[../Простейшая программа «Hello World»|простейшей программе]] от действий пользователя не зависело ровным счетом ничего. Каким, однако, будет результат выполнения данной программы, если ввод пользователя не будет начат двумя числами в десятичной форме?
Для проверки соответствия ввода пользователя требованиям программы мы ''сохраняем'' (<code>=</code>) результат выполнения <code>scanf</code> — количество успешно измененных переменных — в целочисленной переменной с именем <code>r</code> (<code>int r</code>), после чего ''требуем'' равенства ее значения двум (<code>assert (r == 2);</code>.)
<small>Действие ''макроподстановки'' <code>assert</code> заключается в сравнении результата вычисления выражения, переданного ей первым (и единственным) аргументом и ''аварийном завершении'' программы в случае, если полученное значение — ноль («логическая ложь».)<ref name="assert" >[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=204 WG14 N1570 Committee Draft — April 12, 2011] 7.2.1.1 ''The assert macro''</ref></small>
Наконец, в самом начале функции <code>main</code> ''определены'' (помимо упомянутой уже <code>r</code>) целочисленные переменные <code>a</code> и <code>b</code>. Их значение в начале выполнения функции <code>main</code> может быть произвольным,<ref name="init" >[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=157 WG14 N1570 Committee Draft — April 12, 2011] 6.7.9 ''Initialization''</ref> но после успешного (что проверяется вызовом <code>assert</code>) завершения <code>scanf</code> они будут содержать два числа, которые удалось последовательно считать со [[w:Стандартные потоки#Стандартный ввод|стандартного ввода]].
== Вариант «дробный» ==
Рассмотренную [[#Вариант «простой»|выше]] программу несложно изменить для использования [[w:Число с плавающей запятой|чисел с плавающей запятой.]]
<source lang="c">
#include <assert.h>
#include <stdio.h>
int
main ()
{
double a, b;
int r
= scanf ("%lg%lg", &a, &b);
assert (r == 2);
printf ("%lg\n", a + b);
return 0;
}
</source>
Как видно, в этом случае изменяются лишь тип переменных <code>a</code>, <code>b</code> (<code>int</code> → <code>double</code>) и указатели преобразований (<code>%d</code> → <code>%lg</code>.)
<small>Здесь следует отметить, что в случае <code>scanf</code> совершенно идентично будут действовать указатели преобразований <code>%lf</code> и <code>%le</code>. Напротив, в случае <code>printf</code> не будет разницы между <code>%lg</code> и <code>%g</code>. Причины такого поведения мы также пока оставим без внимания.</small>
== Вариант «полный» ==
Ниже приведена программа, которая считывает два действительных числа и
выводит результат четырех арифметических операций: сложения, вычитания, умножения и деления.
Причём, программа выводит результаты вычислений два раза
в обычном виде, а потом со специальным форматированием.
Формат <code>"%10.3lf"</code> соответствует выводу числа типа <code>double</code>,
Строка 128 ⟶ 121 :
Заметьте, что после каждой команды стоит точка с запятой.
Одна из самых популярных синтаксических ошибок начинающих программистов
==Примечания==
{{Примечания}}
[[Категория:Язык Си в примерах|{{SUBPAGENAME}}]]
|