Язык Си в примерах/Учимся складывать: различия между версиями

Вводная дополнена «стандартной формулой»; новые XML id; →‎Примечания: {{Cite web | … | publisher = ISO/IEC | …}}.
(Отмена правок до 106713 — для ctags(1) (см. Обсуждение:Язык Си в примерах#Оформление кода); →‎if: новый XML id.)
(Вводная дополнена «стандартной формулой»; новые XML id; →‎Примечания: {{Cite web | … | publisher = ISO/IEC | …}}.)
Давайте и мы научимся использовать компьютер для вычислений.
Начнём со сложения двух чисел.
 
; {{Якорь2 |Дано}}: два разделенных ''пробельными символами'' [[w:Целое число |целых чисел]] (в «текстовом» десятичном представлении) на [[w:Стандартные потоки#Стандартный ввод |стандартном вводе]] программы.
; Найти: значение суммы (разности, произведения, частного от деления — если имеет смысл) этих двух чисел.
; Новые элементы языка: переменные; тип [[#double |double]]; операторы [[#& |&]], [[#* |*]], [[#? : |? :]] контекста ''выражения'' и оператор [[#if |if]] контекста ''утверждения''; макроподстановка [[#assert |assert]], функции [[#printf |printf]], [[#scanf |scanf]].
 
== Вариант «простой» ==
</source>
 
{{Якорь |printf}}
Рассмотрим выполнение этой программы почти с ее завершения — вызова функции <code >printf</code>.<ref name="fprintf" /> Данная функция выведет целое число в десятичной форме (согласно ''указателю преобразования'' <code >%d</code>), завершая вывод [[w:Перевод строки |переводом строки]] (<code >\n</code>).
 
Число, которое будет выведено, является результатом вычисления выражения <source lang="c" enclose="none" >a + b</source> — или же, проще говоря, — суммой значений переменных <var >a</var> и <var >b</var>.
 
{{Якорь |scanf}}
Вводимые пользователем числа помещаются в эти переменные функцией <code >scanf</code>, вызываемой в коде выше как <source lang="c" enclose="none" >scanf ("%d%d", &a, &b)</source>.<ref name="fscanf" /> Здесь, как и в <code >printf</code>, используется указатель преобразования <code >%d</code>, означающий на этот раз ''считывание'' числа в десятичной форме (возможно — предваряемого пробелами). Поскольку указатель повторен дважды, два числа будут считаны и помещены в упомянутые в аргументах две переменные <var >a</var> и <var >b</var>. (Необходимый здесь унарный оператор <code >&</code> оставим пока без внимания.)
 
В [[../Простейшая программа «Hello World» |простейшей программе]] от действий пользователя не зависело ровным счетом ничего. Каким, однако, будет результат выполнения данной программы, если ввод пользователя <em >не будет</em> начат двумя числами в десятичной форме?
 
{{Якорь |assert}}
Для проверки соответствия ввода пользователя требованиям программы мы ''сохраняем'' (<code >=</code>) результат выполнения <code >scanf</code> — количество успешно измененных переменных — в целочисленной переменной с именем <var >r</var> (<source lang="c" enclose="none" >int r</source>), после чего ''требуем'' равенства ее значения двум (<source lang="c" enclose="none" >assert (r == 2);</source>.)
 
== Вариант «дробный» ==
 
{{Якорь |double}}
Рассмотренную [[#Вариант «простой»|выше]] программу несложно изменить для использования [[w:Число с плавающей запятой|чисел с плавающей запятой.]]
 
Вызов функции в чем-то подобен отправке письма. Мы указываем на конверте имя функции, вкладываем в конверт копии значений, которые хотим передать, и отправляем письмо (вызываем функцию).
 
{{Якорь |&}}
В некоторых случаях, однако, мы хотим получить от функции что-либо обратно. Иногда, для этого достаточно предусмотренного языком ''возвращаемого значения''. Иначе, можно отправить функции своего рода ''конверт с обратным адресом'' (один или несколько). Именно для этого — для получения ''адреса л-значения'' — служит унарный оператор <code>&</code>.
 
Справа от оператора <code >&</code> указывается ''л-значение'' (англ. {{lang|en|lvalue}}.<ref name="lvalues et al" /> Не вдаваясь в подробности отметим, что под л-значением понимают любое выражение, которое может стоять ''слева'' от оператора присваивания <code >=</code>. В частности, л-значением является любое выражение, состоящие из имени действительной в данном контексте (англ. {{lang |en|scope}}) переменной.
 
{{Якорь |*}}
Для обращения к ячейки памяти по ссылке используется унарный оператор <code >*</code>. Так, выражение <source lang="c" enclose="none" >*(&a) = 1</source> полностью равнозначно <source lang="c" enclose="none" >a = 1</source>.
 
== Вариант «тернарный» ==
 
{{Якорь |? :}}
Используя условный оператор контекста ''выражения'' (англ. {{lang|en|conditional operator}}), а также приняв во внимание тот факт, что <code>printf</code> проигнорирует «избыточные» аргументы (аргументы сверх количества, требуемого указателями преобразований в указанной первым аргументом строке формата), можно незначительно сократить код [[#Вариант «арифметический»|предыдущего примера]].
 
{{Примечания | refs =
<!-- Пожалуйста поддерживайте алфавитный порядок для name. Спасибо. -->
<ref name="assert" >{{Cite web | title = 7.2.1.1 The assert macro | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=204 | work = WG14 N1570 Committee Draft | publisher = <!-- FIXME: ? -->ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="conditional" >{{Cite web | title = 6.5.15 Conditional operator | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=118 | work = WG14 N1570 Committee Draft | publisher = <!-- FIXME: ? -->ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="fprintf" >{{Cite web | title = 7.21.6.1 The fprintf function | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=327 | work = WG14 N1570 Committee Draft | publisher = <!-- FIXME: ? -->ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="fscanf" >{{Cite web | title = 7.21.6.2 The fscanf function | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=335 | work = WG14 N1570 Committee Draft | publisher = <!-- FIXME: ? -->ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="if" >{{Cite web | title = 6.8.4.1 The if statement | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=166 | work = WG14 N1570 Committee Draft | publisher = <!-- FIXME: ? -->ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="init" >{{Cite web | title = 6.7.9 Initialization | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=157 | work = WG14 N1570 Committee Draft | publisher = <!-- FIXME: ? -->ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="lvalues et al" >{{Cite web | title = 6.3.2.1 Lvalues, arrays, and function designators | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=72 | work = WG14 N1570 Committee Draft | publisher = <!-- FIXME: ? -->ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="stdio.h" >{{Cite web | title = 7.21 Input/output <code >stdio.h</code> | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=314 | work = WG14 N1570 Committee Draft | publisher = <!-- FIXME: ? -->ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
}}
 
3890

правок