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

Новые XML id для примеров; ссылки; →‎Вариант «произвольный»: новый раздел.
(Вводная дополнена «стандартной формулой»; новые XML id; →‎Примечания: {{Cite web | … | publisher = ISO/IEC | …}}.)
(Новые XML id для примеров; ссылки; →‎Вариант «произвольный»: новый раздел.)
Как и в случае функций (в том числе <code>main</code>), объявление переменных в Си предполагает указание их типов. Основные числовые типы языка — <code>int</code> ([[w:Целое число|целое число]] фиксированной разрядности) и <code>double</code> ([[w:Число с плавающей запятой|число с плавающей запятой]].) Поскольку мы уже использовали тип <code>int</code> в описании функции <code>main</code>, применим его же в данной задаче.
 
{{Якорь |plus.c}}
<source lang="c">
#include <assert.h>
 
{{Якорь |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>]] оставим пока без внимания.)
 
Как и <code >printf</code>, функция <code >scanf</code> ''объявлена'' в ''заголовке'' (англ. {{lang |en|header}}) <code >stdio.h</code>.<ref name="stdio.h" />
Рассмотренную [[#Вариант «простой»|выше]] программу несложно изменить для использования [[w:Число с плавающей запятой|чисел с плавающей запятой.]]
 
{{Якорь |plus-fp.c}}
<source lang="c">
#include <assert.h>
{{Якорь |*}}
Для обращения к ячейки памяти по ссылке используется унарный оператор <code >*</code>. Так, выражение <source lang="c" enclose="none" >*(&a) = 1</source> полностью равнозначно <source lang="c" enclose="none" >a = 1</source>.
 
== Вариант «произвольный» ==
 
Стандарт [[w:C11 |C11]] требует от реализации языка поддержки [[../Скалярные типы#Числовые типы |числовых типов]] разрядности 8, 16, 32 и 64 бит.<ref name="int-least" /> Если по каким-либо причинам в вычислениях требуется бо́льшая разрядность, следует использовать библиотеки операций с числами <em >произвольной</em> разрядности — как, например, [[w:en:GNU Multiple Precision Arithmetic Library |GNU MP.]]<ref name="gmp" />
 
В частности, благодаря GNU MP, пример ниже выведет сумму двух введенных чисел даже если любое из них — или результат сложения — превышает 2⁶⁴.
 
Код имеет следующие отличия от [[#plus.c |исходного]] варианта:
# ввод-вывод чисел произвольной разрядности выполняется функциями <code >gmp_scanf</code> и <code >gmp_printf</code> — ''определенными'' GNU MP и ''объявленными'' в <code >gmp.h</code>; заголовок <code >stdio.h</code> не требуется;
# вместо оператора сложения <code >+</code> используется вызов функции <source lang="c" enclose="none" >mpz_add (a, a, b)</source>; в такой форме, действие функции подобно действию выражения <source lang="c" enclose="none" >a += b</source> для переменных «встроенных» целочисленных типов;
# переменные GNU MP требуют обязательной инициализации, которая в примере выполнена функцией <code >mpz_inits ()</code>;
# тип используемых для вычисления переменных — <code >mpz_t</code>.
 
{{Якорь |plus-imp.c}}
<source lang="c">
#include <assert.h>
#include <gmp.h>
 
int
main (void)
{
mpz_t a, b;
mpz_inits (a, b, 0);
int r
= gmp_scanf ("%Zd%Zd", a, b);
assert (r == 2);
mpz_add (a, a, b);
gmp_printf ("%Zd\n", a);
 
return 0;
}
</source>
 
== Вариант «арифметический» ==
В программе ниже мы кроме суммы вычислим разность и произведение введенных чисел, а также, если второе число отлично от нуля, — частное от деления первого числа на второе.
 
{{Якорь |arith-if.c}}
<source lang="c">
#include <assert.h>
Используя условный оператор контекста ''выражения'' (англ. {{lang|en|conditional operator}}), а также приняв во внимание тот факт, что <code>printf</code> проигнорирует «избыточные» аргументы (аргументы сверх количества, требуемого указателями преобразований в указанной первым аргументом строке формата), можно незначительно сократить код [[#Вариант «арифметический»|предыдущего примера]].
 
{{Якорь |arith.c}}
<source lang="c">
#include <assert.h>
<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 = 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 = ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="gmp" >{{Cite web | title = The GNU MP Bignum Library | url = //gmplib.org/ | lang = en | accessdate = 2015-04-04}}</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 = 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 = ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
<ref name="int-least" >{{Cite web | title = 7.20.1.2 Minimum-width integer types | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=308 | work = WG14 N1570 Committee Draft | publisher = 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 = 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 = ISO/IEC | datepublished = 2011-04-12 | lang = en | accessdate = 2012-11-19}}</ref>
3890

правок