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

Перейти к навигации Перейти к поиску
Использованы <var />, <source enclose="none" />, <em /> где возможно; →‎Примечания: перенесены <ref /> в данный раздел; использован {{Cite web|}}.
(Замечена ошибка в коде. Копировал код в компилятор - не хотел компилировать. Поставил запятую - все заработало как надо. Компилятор: Dev C++.)
(Использованы <var />, <source enclose="none" />, <em /> где возможно; →‎Примечания: перенесены <ref /> в данный раздел; использован {{Cite web|}}.)
{{{{BASEPAGENAMEBook template}}/Содержание}}
 
Разнообразные вычисления —
</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>).
 
Число, которое будет выведено, является результатом вычисления выражения <codesource lang="c" enclose="none" >a + b</codesource> — или же, проще говоря, — суммой значений переменных <codevar >a</codevar> и <codevar >b</codevar>.
 
Вводимые пользователем числа помещаются в эти переменные функцией <code >scanf</code>, вызываемой в коде выше как <codesource lang="c" enclose="none" >scanf ("%d%d", &a, &b)</codesource>.<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>, означающий на этот раз ''считывание'' числа в десятичной форме (возможно — предваряемого пробелами). Поскольку указатель повторен дважды, два числа будут считаны и помещены в упомянутые в аргументах две переменные <codevar >a</codevar> и <codevar >b</codevar>. (Необходимый здесь унарный оператор <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» |простейшей программе]] от действий пользователя не зависело ровным счетом ничего. Каким, однако, будет результат выполнения данной программы, если ввод пользователя <em >не будет</em> начат двумя числами в десятичной форме?
 
Для проверки соответствия ввода пользователя требованиям программы мы ''сохраняем'' (<code >=</code>) результат выполнения <code >scanf</code> — количество успешно измененных переменных — в целочисленной переменной с именем <codevar >r</codevar> (<codesource lang="c" enclose="none" >int r</codesource>), после чего ''требуем'' равенства ее значения двум (<codesource lang="c" enclose="none" >assert (r == 2);</codesource>.)
 
<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> ''определены'' (помимо упомянутой уже <codevar >r</codevar>) целочисленные переменные <codevar >a</codevar> и <codevar >b</codevar>. Их значение в начале выполнения функции <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:Стандартные потоки#Стандартный ввод |стандартного ввода]].
 
== Вариант «дробный» ==
</source>
 
Как видно, в этом случае изменяются лишь тип переменных <codevar >a</codevar>, <codevar >b</codevar> (<code >int</code> → <code >double</code>) и указатели преобразований (<code >%d</code> → <code >%lg</code>.)
 
<small>Здесь следует отметить, что в случае <code>scanf</code> совершенно идентично будут действовать указатели преобразований <code>%lg</code>, <code>%lf</code> и <code>%le</code>. Напротив, в случае <code>printf</code> не будет разницы между <code>%lg</code> и <code>%g</code>. Причины такого поведения мы также пока оставим без внимания.</small>
Так, запись <code>&a</code> означает ''адрес ячейки памяти, выделенной для хранения значения переменной <code>a</code>'', или же, проще, — ''ссылка'' (англ. {{lang|en|reference}}) на переменную <code>a</code>.
 
Справа от оператора <code >&</code> указывается ''л-значение'' (англ. {{lang|en|lvalue}}.<ref name="lvalues et al" >[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=72 WG14 N1570 Committee Draft — April 12, 2011] 6.3.2.1 ''Lvalues, arrays, and function designators''</ref> Не вдаваясь в подробности отметим, что под л-значением понимают любое выражение, которое может стоять ''слева'' от оператора присваивания <code >=</code>. В частности, л-значением является любое выражение, состоящие из имени действительной в данном контексте (англ. {{lang |en|scope}}) переменной.
 
Для обращения к ячейки памяти по ссылке используется унарный оператор <code >*</code>. Так, выражение <codesource lang="c" enclose="none" >*(&a) = 1</codesource> полностью равнозначно <codesource lang="c" enclose="none" >a = 1</codesource>.
 
== Вариант «арифметический» ==
</source>
 
В этой программе нам потребовался ''условный оператор контекста утверждения'' (англ. {{lang |en|if statement}}) — один из четырех (наряду с <code >&&</code>, <code >||</code> и <code >? :</code>) условных операторов языка. Его синтаксис:<ref name="if" >[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=166 WG14 N1570 Committee Draft — April 12, 2011] 6.8.4.1 ''The if statement''</ref>
<code >if (</codevar class="angled" >⟨''выражение''⟩<code>)</codevar>)
⟨''<var class="angled" >тело-если-истинно''⟩</var></code>
<code >if (</codevar class="angled" >⟨''выражение''⟩<code>)</codevar>)
⟨''<var class="angled" >тело-если-истинно''⟩</var>
<code>else</code>
⟨''<var class="angled" >тело-если-ложно''⟩</var></code>
 
Где ⟨''<var class="angled" >тело-если-истинно''⟩</var> и ⟨''<var class="angled" >тело-если-ложно''⟩</var> могут быть (каждый) единственным утверждением (завершаемым <code >;</code>), или же, как в примере выше, — <code >{ }</code>-блоком.
 
В случае, если результат вычисления ''<var >выражения''</var> — истина (другими словами — отличен от 0), выполняется ⟨''<var class="angled" >тело-если-истинно''⟩</var>; в противном случае (и если используется <code >else</code>) — ⟨''<var class="angled" >тело-если-ложно''⟩</var>.
 
Заметьте, что каждое простое ''утверждение'' (англ. {{lang|en|statement}}) завершается точкой с запятой.
В этом варианте, код вновь содержит те же самые строковые константы, что и в предыдущем, однако используется лишь один вызов функции <code>printf</code> — первым аргументом которой (в зависимости от значения переменной <code>b</code>) окажется одна из этих констант.
 
Число 42, которое передается <code >printf</code> пятым аргументом в случае нулевого значения <codevar >b</codevar>, может быть произвольным. Поскольку в этом случае функция <code >printf</code> получает строку формата лишь с ''<em >тремя''</em> указателями формата, фактически использованы будут лишь аргументы с первого (формат) по четвертый (произведение <codevar >a</codevar> и <codevar >b</codevar>).
 
Общий синтаксис тернарного оператора <code >? :</code> следующий:<ref name="conditional" >[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=118 WG14 N1570 Committee Draft — April 12, 2011] 6.5.15 ''Conditional operator''</ref>
''выражение'' <code >?<var class="angled" >выражение</codevar> ''? <var class="angled" >если-истинно'' <code/var> : </code>var ''class="angled" >если-ложно''</var></code>
 
Где ''<var class="angled" >выражение''</var> вычисляется первым, после чего, если оно истинно (отлично от 0), вычисляется и становитсяпринимается результатом оператора в целом выражение ''<var class="angled" >если-истинно''</var>; в противном случае — ''<var class="angled" >если-ложно''</var>.
 
== Примечания ==
{{Примечания}} | 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: ? --> | 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: ? --> | 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: ? --> | 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: ? --> | 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: ? --> | 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: ? --> | 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: ? --> | 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: ? --> | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
}}
 
{{BookCat}}
3890

правок

Навигация