<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Электронный научно-практический журнал «Современные научные исследования и инновации» &#187; потоки ввода-вывода</title>
	<atom:link href="http://web.snauka.ru/issues/tag/potoki-vvoda-vyivoda/feed" rel="self" type="application/rss+xml" />
	<link>https://web.snauka.ru</link>
	<description></description>
	<lastBuildDate>Sat, 18 Apr 2026 09:41:14 +0000</lastBuildDate>
	<language>ru</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>О неоднозначности генерации кода компиляторами С++</title>
		<link>https://web.snauka.ru/issues/2014/04/33610</link>
		<comments>https://web.snauka.ru/issues/2014/04/33610#comments</comments>
		<pubDate>Mon, 28 Apr 2014 10:56:50 +0000</pubDate>
		<dc:creator>Дмитриев Владислав Леонидович</dc:creator>
				<category><![CDATA[05.00.00 ТЕХНИЧЕСКИЕ НАУКИ]]></category>
		<category><![CDATA[C ++ programming language]]></category>
		<category><![CDATA[compiler]]></category>
		<category><![CDATA[indeterminacy]]></category>
		<category><![CDATA[input/output streams]]></category>
		<category><![CDATA[компилятор]]></category>
		<category><![CDATA[неоднозначность]]></category>
		<category><![CDATA[потоки ввода-вывода]]></category>
		<category><![CDATA[язык программирования С++]]></category>

		<guid isPermaLink="false">https://web.snauka.ru/?p=33610</guid>
		<description><![CDATA[В большинстве случаев выбор компилятора обусловлен соображениями наибольшей популярности или удобства использования (а в некоторых случаях, возможно, и силой привычки). Одними из самых распространенных сред разработки программ на языке С++ являются компиляторы Borland C++ 5.02, wxDev C++ 7.4, Microsoft Visual C++. В некоторых случаях в зависимости от используемого компилятора можно получить прирост производительности до 10% [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">В большинстве случаев выбор компилятора обусловлен соображениями наибольшей популярности или удобства использования (а в некоторых случаях, возможно, и силой привычки). Одними из самых распространенных сред разработки программ на языке С++ являются компиляторы Borland C++ 5.02, wxDev C++ 7.4, Microsoft Visual C++. В некоторых случаях в зависимости от используемого компилятора можно получить прирост производительности до 10% и более (разумеется, в рамках решаемой задачи). Но сразу ответить на вопрос о том, какой компилятор выбрать, чтобы он сгенерировал код максимально правильно и быстро, к сожалению, невозможно. Дело в том, что одни компиляторы лучше оптимизируют виртуальные вызовы, другие – лучше работают с памятью. В силу проблем оптимизации многие компиляторы при этом часто ограничивают область анализа функциями и дополнительно к этому могут выполнять межпроцедурный анализ (англ. inter-procedural analysis, IPA), с целью удаления &#8220;мёртвого&#8221; кода (англ. dead code elimination, DCE) и недостижимого кода (англ. unreachable code elimination, UCE). Кроме того, в некоторых, даже самых простых ситуациях, могут возникать разного рода неоднозначности сбора проекта (программы) из программного кода при использовании разных компиляторов [1]. Ниже приводятся некоторые из таких типичных ситуаций.</p>
<p style="text-align: justify;"><span>Рассмотрим вначале пример простой программы, в которой осуществляется присваивание значений элементам одномерного массива, состоящего из четырех целых чисел. Ниже в таблице 1 показаны результаты выполнения программы, построенной отмеченными выше компиляторами.<br />
</span></p>
<p style="text-align: left;"><span>Таблица 1 – Результат заполнения массива при использовании некоторых компиляторов<br />
</span></p>
<div style="margin-left: 5pt;">
<table style="border-collapse: collapse;" border="0">
<colgroup>
<col style="width: 30px;" />
<col style="width: 210px;" />
<col style="width: 120px;" />
<col style="width: 108px;" />
<col style="width: 176px;" /></colgroup>
<tbody valign="top">
<tr>
<td style="padding-left: 7px; padding-right: 7px; border: solid 1pt;" rowspan="2" valign="middle">
<p style="text-align: center;"><span>№</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: solid 1pt; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" rowspan="2" valign="middle">
<p style="text-align: center;"><span>Исходный фрагмент кода программы</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: solid 1pt; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" colspan="3" valign="middle">
<p style="text-align: center;"><span>Значения элементов массива</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>wxDev C++ 7.4</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>Borland C++ 5.02</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>Microsoft Visual C++ 2005 Express</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>1</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: justify;"><span><em>int i=1, m[4];<br />
</em></span></p>
<p style="text-align: justify;"><span><em>int main()<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ m[i]=(++i)++;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> for (int j=0; j&lt;4;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> cout&lt;&lt;m[j++]&lt;&lt;&#8221;t&#8221;);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> getch(); return 0;}</em></span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 2 0</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 0 2</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 2 0</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>2</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: justify;"><span><em>int i=1, m[4];<br />
</em></span></p>
<p style="text-align: justify;"><span><em>int main()<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ m[i]=++i;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> for (int j=0; j&lt;4;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> cout&lt;&lt;m[j++]&lt;&lt;&#8221;t&#8221;);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> getch(); return 0;}</em></span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 2 0 0</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 2 0</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 2 0</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>3</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: justify;"><span><em>int m[4];<br />
</em></span></p>
<p style="text-align: justify;"><span><em>int main()<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ int i=1;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> m[i]=++i;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> for (int j=0; j&lt;4;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> cout&lt;&lt;m[j++]&lt;&lt;&#8221;t&#8221;);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> getch(); return 0;}</em></span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 2 0</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 2 0</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 2 0</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>4</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: justify;"><span><em>int m[4];<br />
</em></span></p>
<p style="text-align: justify;"><span><em>int main()<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ int i=1;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> m[i]=(++i)++;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> for (int j=0; j&lt;4;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> cout&lt;&lt;m[j++]&lt;&lt;&#8221;t&#8221;);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> getch(); return 0;}</em></span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 2 0</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 0 2</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>0 0 2 0</span></p>
</td>
</tr>
</tbody>
</table>
</div>
<p style="text-align: justify;"><span>Как видно, результаты вычислений зависят от используемого компилятора – один и тот же код дает различающиеся результаты для разных компиляторов. Стоит, однако, отметить компилятор Microsoft Visual C++ 2005 Express, который дал ожидаемый по написанному коду результат для всех рассмотренных случаев.<br />
</span></p>
<p style="text-align: justify;"><span>Рассмотрим теперь примеры, демонстрирующие использование функций с переменным количеством параметров. Здесь также могут возникать неоднозначности. Как известно, количество параметров можно задать двумя способами [2]: передать это количество вызываемой функции явным образом через обязательный аргумент; просто договориться о некотором специальном признаке конца списка аргументов.<br />
</span></p>
<p style="text-align: justify;"><span>В обоих случаях доступ к аргументам осуществляется с использованием указателей. Рассмотрим реализацию первого способа на примере задачи о нахождении суммы заранее неизвестного количества элементов.<br />
</span></p>
<p style="text-align: justify;"><span><em>int summa1(int n, &#8230;)<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ int s=0; int *a=&amp;n;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> while (n&#8211;) s+=*(++a);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> return s; }<br />
</em></span></p>
<p style="text-align: justify;"><span><em>int main()<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ cout&lt;&lt;&#8221;Сумма элементов 1, 5, 7, 3: &#8220;&lt;&lt;summa1(4, 1, 5, 7, 3)&lt;&lt;endl;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> cout&lt;&lt;&#8221;Сумма элементов 4, 11, 5, 3, 4: &#8220;&lt;&lt;summa1(5, 4, 11, 5, 3, 4);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> getch(); return 0; }<br />
</em></span></p>
<p style="text-align: justify;"><span>Здесь используется указатель <img src="https://web.snauka.ru/wp-content/uploads/2014/04/041214_1156_1.png" alt="" /> для перебора суммируемых аргументов; его значение инициализируется адресом обязательного первого аргумента <img src="https://web.snauka.ru/wp-content/uploads/2014/04/041214_1156_2.png" alt="" /> (адресом начала списка аргументов) и затем в цикле наращивается для получения доступа к следующему аргументу.<br />
</span></p>
<p style="text-align: justify;"><span>Рассмотрим теперь реализацию второго способа на примере той же задачи.<br />
</span></p>
<p style="text-align: justify;"><span><em>double summa2(double x, &#8230;)<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ double s=0.0; double *a=&amp;x;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> while (*a) s+=*(a++);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> return s; }<br />
</em></span></p>
<p style="text-align: justify;"><span><em>int main()<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ cout&lt;&lt;&#8221;Сумма элементов 4.1,1.0,-5.1,7.3: &#8220;&lt;&lt;summa2(4.1,1.0,-5.1,7.3,0.0)&lt;&lt;endl;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> cout&lt;&lt;&#8221;Сумма элементов 5.2,4.3,11.1,5.1,3.1: &#8220;&lt;&lt;summa2(5.2,4.3,11.1,5.1,3.1,0.0);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> getch(); return 0;}<br />
</em></span></p>
<p style="text-align: justify;"><span>В этом случае цикл суммирования перебирает аргументы до тех пор, пока не встретит нулевой элемент, который должен быть обязательно использован при вызове функции summa2. Разные компиляторы также дают для приведенного здесь кода (для второго способа реализации) разные результаты в зависимости от префиксной или постфиксной формы записи (таблица 2). Первый способ реализации для обсуждаемых в статье компиляторов при этом дает одинаковый результат (таблица 3).<br />
</span></p>
<p style="text-align: left;"><span>Таблица 2 – Результат работы функции с переменным количеством параметров (способ 2)<br />
</span></p>
<div style="margin-left: 5pt;">
<table style="border-collapse: collapse;" border="0">
<colgroup>
<col style="width: 264px;" />
<col style="width: 192px;" />
<col style="width: 186px;" /></colgroup>
<tbody valign="top">
<tr>
<td style="padding-left: 7px; padding-right: 7px; border: solid 1pt;" rowspan="2" valign="middle">
<p style="text-align: center;"><span>Используемый<br />
</span></p>
<p style="text-align: center;"><span>компилятор</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: solid 1pt; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" colspan="2" valign="middle">
<p style="text-align: center;"><span>Результат работы<br />
</span></p>
<p style="text-align: center;"><span>в зависимости от вида кода в цикле while</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span><em>while (*a) s+=*(a++);</em></span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span><em>while (*a) s+=*(++a);</em></span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: center;"><span>Borland C++ 5.02</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>7.3 и 28.8</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>3.2 и 23.6</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: center;"><span>wxDev-C++ 7.4</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>15.5 и 39.2</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>7.3 и 28.8</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: center;"><span>Microsoft Visual C++ 2005 Express</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>7.3 и 28.8</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>3.2 и 23.6</span></p>
</td>
</tr>
</tbody>
</table>
</div>
<p style="text-align: left;"><span>Таблица 3 – Результат работы функции с переменным количеством параметров (способ 1)<br />
</span></p>
<div style="margin-left: 5pt;">
<table style="border-collapse: collapse;" border="0">
<colgroup>
<col style="width: 264px;" />
<col style="width: 192px;" />
<col style="width: 186px;" /></colgroup>
<tbody valign="top">
<tr>
<td style="padding-left: 7px; padding-right: 7px; border: solid 1pt;" rowspan="2" valign="middle">
<p style="text-align: center;"><span>Используемый<br />
</span></p>
<p style="text-align: center;"><span>компилятор</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: solid 1pt; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" colspan="2" valign="middle">
<p style="text-align: center;"><span>Результат работы<br />
</span></p>
<p style="text-align: center;"><span>в зависимости от вида кода в цикле while</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span><em>while (*a) s+=*(a++);</em></span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span><em>while (*a) s+=*(++a);</em></span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: center;"><span>Borland C++ 5.02</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>16 и 27</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>16 и 27</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: center;"><span>wxDev-C++ 7.4</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>16 и 27</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>16 и 27</span></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;">
<p style="text-align: center;"><span>Microsoft Visual C++ 2005 Express</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>16 и 27</span></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle">
<p style="text-align: center;"><span>16 и 27</span></p>
</td>
</tr>
</tbody>
</table>
</div>
<p style="text-align: justify;"><span>Результат работы компилятора wxDev-C++ 7.4, на первый взгляд, не совсем ясен. Также отмечу, что если при описании приведенной здесь функции summa2 тип double везде поменять на тип float, то программа будет работать некорректно (при использовании все того же компилятора wxDev-C++ 7.4).<br />
</span></p>
<p style="text-align: justify;"><span>Функцию summa1, реализующую первый способ передачи количества параметров, можно несколько видоизменить, чтобы она позволяла работать с аргументами типа double – измененный текст программы приведен ниже.<br />
</span></p>
<p style="text-align: justify;"><span><em>double summa1(int n, double k, &#8230;)<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ double s=0. ;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> double *a=&amp;k;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> while (n&#8211;) s+=*(a++);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> return s; }<br />
</em></span></p>
<p style="text-align: justify;"><span><em>int main()<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ cout&lt;&lt;&#8221;Сумма эл-в 1.15, 10.5, 2.7, 5.3: &#8220;&lt;&lt;summa1(4, 1.15, 10.5, 2.7, 5.3)&lt;&lt;endl;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> cout&lt;&lt;&#8221;Сумма эл-в 4, 1.11, 5.1, 2.23, 4.7: &#8220;&lt;&lt;summa1(5, 4., 1.11, 5.1, 2.23, 4.7);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> getch(); return 0; }<br />
</em></span></p>
<p style="text-align: justify;"><span>Представленный здесь код при использовании компилятора wxDev-C++ 7.4 снова дает неправильный результат. Очевидно, это связано с преобразованием типов и моделью памяти, принимаемым в данном компиляторе. Вот код того же примера, который будет нормально работать с компилятором wxDev-C++ 7.4.<br />
</span></p>
<p style="text-align: justify;"><span><em>long double summa1(int n, long double k, &#8230;)<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ long double s=0. ;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> long double *a=&amp;k;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> while (n&#8211;) s+=*a++;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> return s; }<br />
</em></span></p>
<p style="text-align: justify;"><span><em>int main()<br />
</em></span></p>
<p style="text-align: justify;"><span><em>{ cout&lt;&lt;&#8221;Сумма эл-в 1.15,10.5,2.7,5.3: &#8220;&lt;&lt;summa1(4,1.15L,10.5L,2.7L,5.3L)&lt;&lt;endl;<br />
</em></span></p>
<p style="text-align: justify;"><span><em> cout&lt;&lt;&#8221;Сумма эл-в 4,1.11,5.1,2.23, 4.7: &#8220;&lt;&lt;summa1(5,4.L,1.11L,5.1L,2.23L,4.7L);<br />
</em></span></p>
<p style="text-align: justify;"><span><em> getch(); return 0; }<br />
</em></span></p>
<p style="text-align: justify;"><span>Этот код также будет нормально работать и с компилятором Microsoft Visual C++ 2005 Express, однако с компилятором Borland C++ 5.02 будет приводить к ошибке.<br />
</span></p>
<p style="text-align: justify;"><span>Перейдем теперь к неоднозначностям, имеющим место при работе с потоками ввода-вывода. При вводе данных операция &gt;&gt; читает всё, начиная с первого символа (не являющегося символом-разделителем) до следующего символа, который не соответствует типу объекта назначения. Поэтому наиболее распространенной ошибкой при использовании потоков <em>istream</em> является ошибка, связанная с вводом данных, не соответствующих указанному формату. В таких случаях нужно или проверять состояние потока ввода перед использованием считанных данных, или использовать механизм исключений [3, 4]. Рассмотрим, например, следующий фрагмент кода:<br />
</span></p>
<p style="text-align: justify;"><span><em>float a, b;<br />
</em></span></p>
<p style="text-align: justify;"><span><em>cin&gt;&gt;a&gt;&gt;b;<br />
</em></span></p>
<p style="text-align: justify;"><span><em>cout&lt;&lt;a&lt;&lt;&#8221; &#8220;&lt;&lt;b;<br />
</em></span></p>
<p style="text-align: justify;"><span>Если при вводе данных указать, например, 1.234w, то значение переменной <em>a</em> будет равно 1.234, но значение переменной <em>b</em> будет неопределенно, т.к. сразу после ввода 1.234w программа перейдет к строке с инструкцией <em>cout</em>. Дело в том, что как только в потоке встретится символ <em>w</em>, являющийся некорректным с точки зрения ожидаемого формата вводимых данных, последним принятым символом будет 4. Символ <em>w</em> останется во входном потоке, и следующая операция &gt;&gt; начнет чтение с этой точки, что и приводит к неопределенности. Поэтому следующий фрагмент кода<br />
</span></p>
<p style="text-align: justify;"><span><em>float a;<br />
</em></span></p>
<p style="text-align: justify;"><span><em>char b;<br />
</em></span></p>
<p style="text-align: justify;"><span><em>cin&gt;&gt;a&gt;&gt;b;<br />
</em></span></p>
<p style="text-align: justify;"><span><em>cout&lt;&lt;a&lt;&lt;&#8221; &#8220;&lt;&lt;b;<br />
</em></span></p>
<p style="text-align: justify;"><span>будет работать верно при вводе строки 1.234w.<br />
</span></p>
<p style="text-align: justify;"><span>Может случиться так, что самое первое введенное значение будет ошибочным с точки зрения формата. В этом случае операция &gt;&gt; оставит значение переменной без изменений и вернет значение 0 (<em>false</em>), что позволит проверить, отвечал ли ввод требованиям установленного формата данных для переменной. Ниже представлен фрагмент программы, в котором вводятся числа и ведется подсчет их суммы до тех пор, пока вводятся корректные значения для переменной.<br />
</span></p>
<p style="text-align: justify; margin-left: 117pt;"><span><em>float a, s=0.;<br />
</em></span></p>
<p style="text-align: justify; margin-left: 117pt;"><span><em>while(cin&gt;&gt;a) s+=a;<br />
</em></span></p>
<p style="text-align: justify; margin-left: 117pt;"><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p style="text-align: justify; margin-left: 117pt;"><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s&lt;&lt;endl;<br />
</em></span></p>
<p style="text-align: justify;"><span>Пусть в процессе ввода часть чисел вводятся через нажатие клавиши &#8220;Enter&#8221;, причем это будут корректные данные; затем, в следующей строке, вводится последовательность чисел через символ-разделитель (пробел):<br />
</span></p>
<p style="text-align: justify;"><span><em>1.37<br />
</em></span></p>
<p style="text-align: justify;"><span><em>2.45<br />
</em></span></p>
<p style="text-align: justify;"><span><em>1.23 4 13.4 2.2b 3.4 5.6<br />
</em></span></p>
<p style="text-align: justify;"><span>Результатом работы фрагмента программы будет:<br />
</span></p>
<p style="text-align: justify; margin-left: 108pt;"><span><em>Значение переменной a: 2.2<br />
</em></span></p>
<p style="text-align: justify; margin-left: 108pt;"><span><em>Сумма чисел: 24.65<br />
</em></span></p>
<p style="text-align: justify;"><span>Ввод <em>cin</em> буферизуется, поэтому третья строка значений, введенных с клавиатуры, не будет пересылаться программе до тех пор, пока не будет нажата клавиша &#8220;Enter&#8221; для каждой из выше расположенных строк. Цикл прекратит работу, как только встретится символ &#8220;<em>b</em>&#8221; (третья строка), так как он не соответствует формату вещественного числа: несоответствие символа &#8220;<em>b</em>&#8221; ожидаемому формату приводит к тому, что выражение<br />
</span></p>
<p style="text-align: left;"><span><em>cin&gt;&gt;a;<br />
</em></span></p>
<p style="text-align: justify;"><span>будет оценено как <em>false</em>.<br />
</span></p>
<p style="text-align: justify;"><span>Компилятор Borland C++ 5.02 и Microsoft Visual C++ 2005 Express, как и ожидалось, дали в примере выше для переменной <em>a</em> один и тот же результат: 2.2. Однако компилятор wxDev-C++ 7.4 сбрасывает значение переменной <em>a</em> в ноль. Последнее противоречит принципу, принятому в С++: если попытаться прочитать в некоторую переменную и операция не выполняется, значение переменной должно остаться неизменным.<br />
</span></p>
<p style="text-align: justify;"><span>Приведенные примеры показывают, что стабильных правильных результатов среди рассмотренных компиляторов можно добиться только при использовании компилятора Microsoft Visual C++ 2005 Express и выше. Результаты, которые получаются с использованием компиляторов Borland C++ 5.02 и wxDev C++7.4, сильно зависят от содержания исходного кода программы.</span></p>
]]></content:encoded>
			<wfw:commentRss>https://web.snauka.ru/issues/2014/04/33610/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Использование методов класса ios_base для проверки состояния потока ввода в С++</title>
		<link>https://web.snauka.ru/issues/2016/12/75931</link>
		<comments>https://web.snauka.ru/issues/2016/12/75931#comments</comments>
		<pubDate>Sat, 10 Dec 2016 07:44:12 +0000</pubDate>
		<dc:creator>Дмитриев Владислав Леонидович</dc:creator>
				<category><![CDATA[05.00.00 ТЕХНИЧЕСКИЕ НАУКИ]]></category>
		<category><![CDATA[input/output streams]]></category>
		<category><![CDATA[the C++programming language]]></category>
		<category><![CDATA[the ios_base class]]></category>
		<category><![CDATA[класс ios_base]]></category>
		<category><![CDATA[потоки ввода-вывода]]></category>
		<category><![CDATA[язык программирования С++]]></category>

		<guid isPermaLink="false">https://web.snauka.ru/?p=75931</guid>
		<description><![CDATA[При обучении программированию на С++ необходимо уделять достаточно внимания работе с потоками ввода-вывода [1], так как практически любая программа использует ввод и вывод. Однако почти всегда изучение этой темы ограничивается лишь стандартным использованием операций ввода и вывода на основе cin и cout. Другие особенности и возможности потоков остаются так и не затронутыми, и неизвестными для [...]]]></description>
			<content:encoded><![CDATA[<p><span>При обучении программированию на С++ необходимо уделять достаточно внимания работе с потоками ввода-вывода [1], так как практически любая программа использует ввод и вывод. Однако почти всегда изучение этой темы ограничивается лишь стандартным использованием операций ввода и вывода на основе <em>cin</em> и <em>cout</em>. Другие особенности и возможности потоков остаются так и не затронутыми, и неизвестными для учащихся. С целью устранения такого ограничения в статье рассматриваются отдельные вопросы, связанные с проверкой состояния потоков ввода-вывода. Предполагается, что учащиеся уже имеют базовые представления о языке программирования C++.<br />
</span></p>
<p><span>Класс <em>istream</em> определяет оператор &gt;&gt; (&#8220;прочесть из&#8221;) для организации ввода встроенных типов. По умолчанию операция &gt;&gt; используется также в качестве битовой операции сдвига, однако это не имеет отношения к вводу: класс <em>istream</em> переопределяет операцию &gt;&gt; для организации ввода, причем эта операция перегружена и может применяться со всеми базовыми типами C++. Класс <em>istream</em> вводит оператор &gt;&gt; для каждого из этих типов данных, причем оператор &gt;&gt; возвращает ссылку на объект <em>istream</em>.<br />
</span></p>
<p><span>При вводе данных операция &gt;&gt; читает всё, начиная с первого символа (не являющегося символом-разделителем) до следующего символа, который не соответствует типу объекта назначения. Поэтому наиболее распространенной ошибкой при использовании потоков <em>istream</em> является ошибка, связанная с вводом данных, не соответствующих указанному формату. В таких случаях нужно или проверять состояние потока ввода перед использованием считанных данных, или использовать механизм исключений [4-6].<br />
</span></p>
<p><span>Рассмотрим, например, следующий фрагмент кода:<br />
</span></p>
<p><span><em>float a, b;<br />
</em></span></p>
<p><span><em>cin&gt;&gt;a&gt;&gt;b;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;a&lt;&lt;&#8221; &#8220;&lt;&lt;b;<br />
</em></span></p>
<p><span>Если при вводе данных указать, например<br />
</span></p>
<p><span><em>1.234w<br />
</em></span></p>
<p><span>то значение переменной <em>a</em> будет равно <em>1.234</em>, но значение переменной <em>b</em> будет неопределенно, т.к. сразу после ввода <em>1.234w</em> программа перейдет к строке с инструкцией <em>cout</em>. Дело в том, что как только в потоке встретится символ <em>w</em>, являющийся некорректным с точки зрения ожидаемого формата вводимых данных, последним принятым символом будет 4. Символ <em>w</em> останется во входном потоке, и следующий оператор &gt;&gt; начнет чтение с этой точки, что и приводит к неопределенности. Поэтому следующий фрагмент кода<br />
</span></p>
<p><span><em>float a; char b;<br />
</em></span></p>
<p><span><em>cin&gt;&gt;a&gt;&gt;b;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;a&lt;&lt;&#8221; &#8220;&lt;&lt;b;<br />
</em></span></p>
<p><span>будет работать верно при вводе строки <em>1.234w</em>.<br />
</span></p>
<p><span>Может случиться так, что самое первое введенное значение будет ошибочным с точки зрения формата. В этом случае операция &gt;&gt; оставит значение переменной без изменений и вернет значение <em>0</em> (<em>false</em>), что позволит проверить, отвечал ли ввод требованиям установленного формата данных для переменной. Ниже представлен фрагмент программы, в котором вводятся числа, и ведется подсчет их суммы до тех пор, пока вводятся корректные значения для переменной.<br />
</span></p>
<p><span><em>float a, s=0.;<br />
</em></span></p>
<p><span><em>while(cin&gt;&gt;a) s+=a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s&lt;&lt;endl;<br />
</em></span></p>
<p><span>Пусть в процессе ввода часть чисел вводятся через нажатие клавиши &#8220;<em>Enter</em>&#8220;, причем это будут корректные данные; затем, в следующей строке, вводится последовательность чисел через символ-разделитель (пробел):<br />
</span></p>
<p><span><em>1.37<br />
</em></span></p>
<p><span><em>2.45<br />
</em></span></p>
<p><span><em>1.23 4 13.4 2.2b 3.4 5.6<br />
</em></span></p>
<p><span>Результатом работы фрагмента программы будет:<br />
</span></p>
<p><span><em>Значение переменной a: 2.2<br />
</em></span></p>
<p><span><em>Сумма чисел: 24.65<br />
</em></span></p>
<p><span>Ввод <em>cin</em> буферизуется, поэтому третья строка значений, введенных с клавиатуры, не будет пересылаться программе до тех пор, пока не будет нажата клавиша &#8220;<em>Enter</em>&#8221; для каждой из выше расположенных строк. Цикл прекратит работу, как только встретится символ &#8220;<em>b</em>&#8221; (третья строка), так как он не соответствует формату вещественного числа: несоответствие символа &#8220;<em>b</em>&#8221; ожидаемому формату приводит к тому, что выражение <em>cin&gt;&gt;a</em> будет оценено как <em>false</em>.<br />
</span></p>
<p><span>Компилятор Borland C++ 5.02 и Microsoft Visual C++ 2005 Express, как и ожидалось, дали в примере выше для переменной <em>a</em> один и тот же результат: 2.2. Однако компилятор wxDev-C++ 7.4 сбрасывает значение переменной <em>a</em> в ноль. Последнее противоречит принципу, принятому в С++: если попытаться прочитать в некоторую переменную и операция не выполняется, значение переменной должно остаться неизменным [1].<br />
</span></p>
<p><span>Объекты <em>cin</em> и <em>cout</em> содержат член данных, который описывает <em>состояние потока</em>. Состояние потока определяется тремя элементами класса <em>ios_base</em>: <em>eofbit</em>, <em>badbit</em>, <em>failbit</em>. Значение каждого такого элемента может принимать значения 0 (сброшен) или 1 (установлен). Так, когда <em>cin</em> достигает конца файла, <em>eofbit</em> устанавливается в значение 1. Если <em>cin</em> не может прочитать ожидаемый формат данных (как в примерах выше) или производится попытка чтения недоступного файла, то <em>failbit</em> устанавливается в значение 1. Элемент <em>badbit</em> устанавливается в 1, если происходит не поддающийся диагностике сбой, который может привести к повреждению потока. Стоит отметить, что различие между состояниями <em>failbit</em> и <em>badbit</em> очень незначительно. Можно сказать, что если поток в состоянии <em>failbit</em>, но не в <em>badbit</em>, то он не испорчен (при этом символы могут быть потеряны); однако если имеет место состояние <em>badbit</em>, то ни о чем с уверенностью сказать нельзя. Считается, что с потоком все в порядке, если все три первых бита состояния установлены в 0. Таким образом, состояние потока представляется в виде набора флагов (кроме перечисленных выше трех флагов есть еще флаг <em>goodbit</em>, но он выступает просто как другой способ выражения состояния 0).<br />
</span></p>
<p><span>Класс <em>ios_base</em> предоставляет также некоторые методы, которые позволяют сообщать о состоянии потока, или изменять его. Эти методы представлены в таблице 1.<br />
</span></p>
<p style="text-align: left;"><span>Таблица 1. Методы управления состояниями потоков<br />
</span></p>
<div style="margin-left: 5pt;">
<table style="border-collapse: collapse;" border="0">
<colgroup>
<col style="width: 151px;" />
<col style="width: 491px;" /></colgroup>
<tbody valign="top">
<tr style="height: 30px;">
<td style="padding-left: 7px; padding-right: 7px; border: solid 1pt;" valign="middle"><span>Метод класса <em>ios_base</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: solid 1pt; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle"><span>Описание</span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span><em>eof()</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>Возвращает <em>true</em>, если установлен флаг <em>eofbit</em></span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span><em>bad()</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>Возвращает <em>true</em>, если установлен флаг <em>badbit</em></span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span><em>fail()</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>Возвращает <em>true</em>, если установлен один из флагов: <em>badbit</em> или <em>failbit</em></span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span><em>good()</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>Возвращает <em>true</em>, если поток можно использовать (все биты в состоянии 0)</span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span><em>rdstate()</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>Возвращает состояние потока</span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span><em>clear(iostate x)</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>Устанавливает состояние потока в <em>x</em> (по умолчанию <em>x</em> есть 0).<br />
</span><span>Создает исключение <em>basic_ios::failure</em> в случае <em>(rdstate() &amp; exceptions()) != 0</em></span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span><em>setstate(iostate x)</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>Вызывает <em>clear(rdstate() | x)</em>, в результате чего биты состояния устанавливаются в соответствии с тем, что содержит <em>x</em>. Остальные биты состояния потока остаются неизменными.</span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span><em>exceptions()</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>Возвращает битовую маску для идентификации флагов, ставших причиной исключения.</span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span><em>exceptions(iostate x)</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>Устанавливает состояния, которые вызовут <em>clear()</em> для генерации исключения. Так, если <em>x</em> – это <em>failbit</em>, то <em>clear()</em> возбудит исключение, когда будет установлен <em>failbit</em>.</span></td>
</tr>
</tbody>
</table>
</div>
<p><span>Если для потока установилось состояние <em>good()</em>, то предыдущая операция выполнилась успешно, и можно выполнять следующий ввод; в противном случае ввод не выполнится.<br />
</span></p>
<p><span>Метод <em>clear()</em> устанавливает состояние в соответствии со значением переданного аргумента. Например, вызов<br />
</span></p>
<p><span><em>cin.clear();<br />
</em></span></p>
<p><span>использует аргумент по умолчанию (0), поэтому очищаются все три бита состояния (устанавливаются в 0). Однако вызов<br />
</span></p>
<p><span><em>cin.clear(eofbit);<br />
</em></span></p>
<p><span>устанавливает флаг <em>eofbit</em> в 1, а остальные два бита оставшихся флагов очищаются.<br />
</span></p>
<p><span>Метод <em>setstate()</em>, в отличие от <em>clear()</em>, касается только тех бит, которые установлены для его аргумента. Поэтому, например, вызов<br />
</span></p>
<p><span><em>cin.setstate(eofbit);<br />
</em></span></p>
<p><span>устанавливает только флаг <em>eofbit</em> в значение 1, а остальные биты не изменяются.<br />
</span></p>
<p><span>Наиболее частой причиной использования сброса состояния потока является необходимость осуществления повторного ввода после получения данных не того формата, что ожидалось. Установка битов состояния потока очень важна: если введенные данные не соответствуют ожидаемому формату, то поток закрывается для дальнейшего ввода или вывода до тех пор, пока соответствующий бит не будет очищен. Например, следующий код не будет работать (повторно ввести значение для <em>a</em> не удастся):<br />
</span></p>
<p><span><em>float a, s=0.;<br />
</em></span></p>
<p><span><em>void *p;<br />
</em></span></p>
<p><span><em>while((p=cin&gt;&gt;a) &amp;&amp; a !=0) s+=a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s&lt;&lt;endl;<br />
</em></span></p>
<p><span><em>if (p==0) {cout&lt;&lt;&#8221;Обнаружена ошибка ввода. &#8221;<br />
</em></span></p>
<p><span><em>&lt;&lt;&#8221;Повторите ввод: &#8220;;<br />
</em></span></p>
<p><span><em>cin&gt;&gt;a;<br />
</em></span></p>
<p><span><em>s+=a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s; }<br />
</em></span></p>
<p><span>Чтобы фрагмент программы продолжил читать ввод после возникновения ошибки, необходимо сбросить биты состояния потока в нормальное состояние. Это можно сделать, используя метод <em>clear()</em>. Однако только одного сброса состояния потока недостаточно, т.к. некорректный ввод все также остается во входной очереди, и будет вновь прочитан. Здесь можно предложить по крайней мере три способа решения проблемы.<br />
</span></p>
<p><span>Во-первых, можно продолжить чтение до очередного символа-разделителя (по умолчанию – &#8220;пробел&#8221;), для чего использовать функцию <em>isspace()</em>:<br />
</span></p>
<p><span><em>float a, s=0.;<br />
</em></span></p>
<p><span><em>void *p;<br />
</em></span></p>
<p><span><em>while((p=cin&gt;&gt;a) &amp;&amp; a!=0) s+=a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s&lt;&lt;endl;<br />
</em></span></p>
<p><span><em>if (p==0) {cout&lt;&lt;&#8221;Обнаружена ошибка ввода. &#8221;<br />
</em></span></p>
<p><span><em>&lt;&lt;&#8221;Повторите ввод: &#8220;;<br />
</em></span></p>
<p><span><em>cin.clear(); // сброс состояния потока<br />
</em></span></p>
<p><span><em>while(!isspace(cin.get())); // продолжаем //считывать до символа-разделителя<br />
</em></span></p>
<p><span><em>cin&gt;&gt;a; s+=a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s; }<br />
</em></span></p>
<p><span>Введем в качестве данных, например, следующие:<br />
</span></p>
<p><span><em>2.45<br />
</em></span></p>
<p><span><em>1.23 4 13.4 2.2b 3.4 5.6<br />
</em></span></p>
<p><span>При этом в качестве следующего значения переменной <em>a</em> автоматически (без нового ввода с клавиатуры) будет взято следующее корректное значение из буфера ввода, которое равно 3.4. Поэтому на экране увидим:<br />
</span></p>
<p><span><em>Значение переменной а: 2.2<br />
</em></span></p>
<p><span><em>Сумма чисел: 23.28<br />
</em></span></p>
<p><span><em>Обнаружена ошибка ввода. Повторите ввод:<br />
</em></span></p>
<p><span><em>Значение переменной а: 3.4<br />
</em></span></p>
<p><span><em>Сумма чисел: 26.68<br />
</em></span></p>
<p><span>Во-вторых, можно отбросить остаток строки буфера, а не очередные символы из него:<br />
</span></p>
<p><span><em>float a, s=0.;<br />
</em></span></p>
<p><span><em>void *p;<br />
</em></span></p>
<p><span><em>while((p=cin&gt;&gt;a) &amp;&amp; a!=0) s+=a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s&lt;&lt;endl;<br />
</em></span></p>
<p><span><em>if (p==0) {cout&lt;&lt;&#8221;Обнаружена ошибка ввода. &#8221;<br />
</em></span></p>
<p><span><em> &lt;&lt;&#8221;Повторите ввод: &#8220;;<br />
</em></span></p>
<p><span><em> cin.clear(); // сброс состояния потока<br />
</em></span></p>
<p><span><em> while(cin.get() != &#8216;n&#8217;); //отбрасываем остаток строки<br />
</em></span></p>
<p><span><em>cin&gt;&gt;a; s+=a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s; }<br />
</em></span></p>
<p><span>Возможно отбросить остаток строки буфера еще двумя способами:<br />
</span></p>
<ul>
<li>
<div style="text-align: justify;"><span>Воспользоваться функцией-членом <em>ignore()</em> класса <em>istream</em>, которая извлекает из потока символы и отбрасывает их. Функция имеет два аргумента: количество <em>n</em> отбрасываемых символов и символ-признак, после которого отбрасывание прекращается. Таким образом, функция <em>ignore()</em> отбрасывает либо <em>n</em> символов, либо все символы до первой встречи символа-признака. Так как нам нужно отбросить весь остаток строки в буфере, то в коде выше вместо строки<br />
</span></div>
</li>
</ul>
<p><span><em>while(cin.get() != &#8216;n&#8217;);</em><br />
</span></p>
<p><span>необходимо написать строку:<br />
</span></p>
<p><span><em>cin.ignore(numeric_limits&lt;streamsize&gt;::max(), &#8216;n&#8217;);</em><br />
</span></p>
<p><span>При этом также необходимо подключить файл <em>limits</em>. Способ не применим к компилятору Borland C++ 5.02.<br />
</span></p>
<ul>
<li>
<div style="text-align: justify;"><span>Воспользоваться функцией-членом <em>rdbuf()</em> класса <em>istream</em> для обращения к буферу ввода. Чтобы узнать, сколько символов в нем содержится, нужно вызвать функцию <em>in_avail()</em> этого буфера – это количество символов мы будем игнорировать. Поэтому в коде выше вместо строки<br />
</span></div>
</li>
</ul>
<p><span><em>while(cin.get() != &#8216;n&#8217;);</em><br />
</span></p>
<p><span>необходимо написать строку:<br />
</span></p>
<p><span><em>cin.ignore(cin.rdbuf()-&gt;in_avail());</em><br />
</span></p>
<p><span>Данный способ не стал работать с компилятором wxDev-C++ 7.4; компиляторы Borland C++ 5.02 и Microsoft Visual C++ 2005 Express дали при этом одинаковый верный результат.<br />
</span></p>
<p><span>В-третьих, можно воспользоваться методом <em>sync()</em>, который позволяет очистить буфер стандартного ввода от имеющихся в нем символов:<br />
</span></p>
<p><span><em>float a, s=0.; void *p;<br />
</em></span></p>
<p><span><em>while((p=cin&gt;&gt;a) &amp;&amp; a!=0) s+=a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s&lt;&lt;endl;<br />
</em></span></p>
<p><span><em>if (p==0) {cout&lt;&lt;&#8221;Обнаружена ошибка ввода. &#8221;<br />
</em></span></p>
<p><span><em>&lt;&lt;&#8221;Повторите ввод: &#8220;;<br />
</em></span></p>
<p><span><em>cin.clear(); // сброс состояния потока<br />
</em></span></p>
<p><span><em>cin.sync();<br />
</em></span></p>
<p><span><em>cin&gt;&gt;a; s+=a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nЗначение переменной а: &#8220;&lt;&lt;a;<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s; }<br />
</em></span></p>
<p><span>Стоит отметить, что синхронизация потока <em>istream</em> и буфера, выполняемая на основе <em>sync()</em>, не всегда выполняется правильно. Кроме того, функция <em>sync()</em> для буфера, связанного с <em>ostream</em>, сбрасывает содержимое буфера на устройство вывода.<br />
</span></p>
<p><span>Рассмотрим еще небольшой фрагмент кода, позволяющий подсчитывать сумму вещественных чисел последовательности, признаком конца которой является 0. При этом код обрабатывает ситуации с некорректно введенными данными. В качестве тренировки предлагаем читателю изменить ниже расположенный код таким образом, чтобы из подсчета полностью исключалось некорректно введенное число.<br />
</span></p>
<p><span><em>float a, s=0.;<br />
</em></span></p>
<p><span><em>void *p;<br />
</em></span></p>
<p><span><em>do { p=cin&gt;&gt;a;<br />
</em></span></p>
<p><span><em>if (p==0) { cin.clear(); cin.sync(); }<br />
</em></span></p>
<p><span><em>else s+=a; } while(a!=0);<br />
</em></span></p>
<p><span><em>cout&lt;&lt;&#8221;nСумма чисел: &#8220;&lt;&lt;s;<br />
</em></span></p>
<p><span>После изучения представленного выше материала с целью оценки уровня усвоения учащимися учебного материала может оказаться удобным использование всевозможных программ-тестов [2, 3], в том числе в дистанционной форме.<br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>https://web.snauka.ru/issues/2016/12/75931/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>О потоках ввода-вывода в С++: некоторые возможности класса ostream</title>
		<link>https://web.snauka.ru/issues/2016/12/75884</link>
		<comments>https://web.snauka.ru/issues/2016/12/75884#comments</comments>
		<pubDate>Thu, 29 Dec 2016 12:40:58 +0000</pubDate>
		<dc:creator>Дмитриев Владислав Леонидович</dc:creator>
				<category><![CDATA[05.00.00 ТЕХНИЧЕСКИЕ НАУКИ]]></category>
		<category><![CDATA[input/output streams]]></category>
		<category><![CDATA[the C++programming language]]></category>
		<category><![CDATA[the ostream class]]></category>
		<category><![CDATA[класс ostream]]></category>
		<category><![CDATA[потоки ввода-вывода]]></category>
		<category><![CDATA[язык программирования С++]]></category>

		<guid isPermaLink="false">https://web.snauka.ru/?p=75884</guid>
		<description><![CDATA[Область применения языка программирования C++ в настоящее время весьма обширна, он широко используется для разработки программного обеспечения, и является одним из самых популярных языков программирования. В настоящее время существует множество реализаций языка C++, как коммерческих, так и бесплатных (например, Microsoft Visual C++ 2005-2013). При обучении программированию на С++ необходимо уделять достаточно внимания работе с потоками [...]]]></description>
			<content:encoded><![CDATA[<p><span>Область применения языка программирования C++ в настоящее время весьма обширна, он широко используется для разработки программного обеспечения, и является одним из самых популярных языков программирования. В настоящее время существует множество реализаций языка C++, как коммерческих, так и бесплатных (например, Microsoft Visual C++ 2005-2013).<br />
</span></p>
<p><span>При обучении программированию на С++ необходимо уделять достаточно внимания работе с потоками ввода-вывода [1], так как практически любая программа использует ввод и вывод. Однако почти всегда изучение этой темы ограничивается лишь стандартным использованием операций ввода и вывода на основе <em>cin</em> и <em>cout</em>. Другие особенности и возможности потоков остаются так и не затронутыми, и неизвестными для учащихся (обычно в дальнейшем особо заинтересованные учащиеся изучают их самостоятельно).<br />
</span></p>
<p><span>В данной статье рассматриваются некоторые вопросы, связанные с перегруженной операцией &lt;&lt; и отдельными методами класса <em>ostream</em>. Предполагается, что учащиеся уже имеют базовые представления о языке программирования C++.<br />
</span></p>
<p><span>Вывод в С++ рассматривается как поток байтов, и на самом деле представляет собой преобразование объектов некоторого типа в последовательность символов. Это связано с тем, что многие виды данных (даже стандартных типов) организованы в более крупные единицы, чем байт. Поэтому наиболее важной задачей, стоящей перед классом <em>ostream</em>, является задача преобразования типов, таких как <em>int</em>, <em>float</em>, <em>double</em> и других, в поток символов. Для выполнения таких преобразований в классе <em>ostream</em> предусмотрено несколько методов [1, 4-6].<br />
</span></p>
<p><span>Как понимать утверждение &#8220;объект представляет собой поток&#8221;? Например, когда в файле <em>iostream</em> объявляется объект <em>cout</em> для программы, то этот объект получает данные-члены, содержащие информацию относительно вывода (ширина поля вывода, количество знаков после десятичной точки, адрес объекта <em>streambuf</em>, и др.)<br />
</span></p>
<p><span>Рассмотрим, что происходит, когда в программе встречается инструкция <em>cout</em> [4]:<br />
</span></p>
<p><span><em>cout&lt;&lt;&#8221;Введите строку данных&#8221;;<br />
</em></span></p>
<p><span>Данная инструкция помещает символы из строки &#8220;<em>Введите строку данных</em>&#8221; в буфер, управляемый <em>cout</em> через объект <em>streambuf</em>. Буфер (<em>buffer</em>) – это блок оперативной памяти, выполняющий роль посредника, который используется средствами ввода-вывода для промежуточного (временного) хранения данных, передаваемых между программой и устройством хранения.<br />
</span></p>
<p><span>Буфер помогает, например, согласовать обмен данными между программами и приводами дисков: программы очень часто обрабатывают данные по одному байту за раз, а приводы дисков обычно передают информацию блоками размером по 512 байт и более. Кроме того, если считывать данные из файла по одному символу, то такое чтение требует больших аппаратных затрат, и достаточно медленно. Буферизованный подход заключается в том, что достаточно большая порция данных читается с диска и сохраняется в буфере. Затем можно производить чтение данных из буфера по одному символу – это будет намного быстрее, так как в таком случае производится чтение байтов из памяти. После того, как программа в процессе чтения и обработки данных достигнет конца буфера, она может считать следующую порцию данных с диска. Аналогично, при выводе программа может сначала наполнить буфер данными, а затем целиком передать этот блок данных на жесткий диск; затем буфер используется для приема новых данных.<br />
</span></p>
<p><span>При вводе данных с клавиатуры программа, в принципе, не нуждается в буфере, так как клавиатурный ввод даёт один символ за раз. Однако буферизированный ввод с клавиатуры обеспечивает возможность исправить введенные данные до того, как они поступят в программу. Программа на С++ обычно сбрасывает содержимое такого буфера в программу после нажатия на клавишу &#8220;<em>Enter</em>&#8220;. При выводе на экран буфер обычно сбрасывается при встрече символа новой строки.<br />
</span></p>
<p><span>Так как вывод из буфера для <em>cout</em> по умолчанию направляется на стандартный вывод (экран), то один конец потока подключается к программе, а второй – к устройству стандартного вывода – экрану. Таким образом, объект<em> cout</em> с помощью объекта типа <em>streambuf</em> управляет движением байт в потоке.<br />
</span></p>
<p><span>Класс <em>ostream</em> определяет оператор &lt;&lt; (&#8220;записать в&#8221;) для управления выводом встроенных типов (иногда операцию &lt;&lt; называют <em>операцией вставки</em>). По умолчанию операция &lt;&lt; используется также в качестве битовой операции сдвига, однако это не имеет отношения к выводу: класс <em>ostream</em> переопределяет операцию &lt;&lt; для организации вывода, причем эта операция перегружена и может применяться со всеми базовыми типами C++. Класс <em>ostream</em> предлагает определение функции <em>operator&lt;&lt;()</em> для каждого из этих типов данных, причем эта функция возвращает ссылку на объект <em>ostream</em>, для которого она вызывалась. Именно поэтому к ней можно применить другой <em>operator&lt;&lt;()</em> и может быть организован сцепленный вывод данных:<br />
</span></p>
<p><span><em>cout&lt;&lt;&#8221;Значение элемента a["&lt;&lt;i&lt;&lt;"] равно &#8220;&lt;&lt;a[i];<br />
</em></span></p>
<p><span>По той же причине строка кода<br />
</span></p>
<p><span><em>cout&lt;&lt;&#8221;a = &#8220;&lt;&lt;a&lt;&lt;endl;<br />
</em></span></p>
<p><span>будет интерпретироваться (не для компилятора Borland C++ 5.02) как<br />
</span></p>
<p><span><em>operator&lt;&lt; (cout, &#8220;a = &#8220;).operator&lt;&lt; (a)&lt;&lt;endl;<br />
</em></span></p>
<p><span>Для вывода типов, определенных пользователем, операцию &lt;&lt; необходимо перегрузить соответствующим образом. После этого перегруженным оператором &lt;&lt; можно будет пользоваться точно так же, как и оператором &lt;&lt; для встроенных типов.<br />
</span></p>
<p><span>Кроме функций <em>operator&lt;&lt;()</em>, класс <em>ostream</em> предоставляет еще и следующие методы: метод <em>put()</em> для отображения символов и метод <em>write()</em> для отображения строк. Методы реализованы в виде шаблонов, а вызываются с применением обычной нотации вызова метода класса:<br />
</span></p>
<p><span><em>cout.put(&#8216;P&#8217;);</em><br />
</span></p>
<p><span>Функция-член <em>put()</em> класса <em>ostream</em> возвращает ссылку на вызывающий объект, поэтому можно использовать сцепленный вывод:<br />
</span></p>
<p><span><em>cout.put(&#8216;P&#8217;).put(&#8216;u&#8217;).put(&#8216;t&#8217;)&lt;&lt;endl;<br />
</em></span></p>
<p><span>Фактически вызов функции <em>cout.put(&#8216;P&#8217;)</em> возвращает <em>cout</em>, который, в свою очередь, снова вызывает метод <em>put()</em>.<br />
</span></p>
<p><span>Так как метод <em>put()</em> выводит символ, а сам метод реализован в виде шаблона, то можно применять <em>put()</em> и с аргументами числовых типов. При этом будет выведен символ с соответствующим числовым ASCII-кодом:<br />
</span></p>
<p><span><em>cout.put(97); // a<br />
</em></span></p>
<p><span><em>cout.put(117.234); // u<br />
</em></span></p>
<p><span>Некоторые старые компиляторы ошибочно перегружали метод <em>put()</em> для типов аргументов <em>char</em>, <em>unsigned char</em> и <em>signed char</em>, что в результате приводило к неоднозначности. Поэтому в таких случаях было необходимо указывать явное преобразование типов. Например, чтобы предыдущий код работал в компиляторе Borland C++ 5.02, его нужно видоизменить, включив явное преобразование типов:<br />
</span></p>
<p><span><em>cout.put((char)97); // a<br />
</em></span></p>
<p><span><em>cout.put((char)117.234); // u<br />
</em></span></p>
<p><span>Рассмотрим теперь метод <em>write()</em>. Он имеет два аргумента, первый из которых представляет собой адрес строки, которую необходимо отобразить, а второй – указывает, сколько символов нужно отобразить. Тип возвращаемого функцией <em>write()</em> значения есть <em>ostream &amp;</em>, поэтому вызов <em>cout.write()</em> возвращает объект <em>cout</em>.<br />
</span></p>
<p><span>Функция-член <em>write()</em> класса <em>ostream</em> обладает интересной особенностью – она не прекращает вывод строки по достижении признака конца строки, и выводит столько символов, сколько указано вторым аргументом. Поэтому если задать вторым аргументом число, превышающее длину конкретной строки, то метод <em>write()</em> начнет выводить следующие символы, расположенные в соседних ячейках памяти.<br />
</span></p>
<p><span>Ниже приведен фрагмент кода, в котором показано использование метода <em>write()</em>.<br />
</span></p>
<p><span><em> const char *s1 = &#8220;Москва&#8221;;<br />
</em></span></p>
<p><span><em> const char *s2 = &#8220;Стерлитамак&#8221;;<br />
</em></span></p>
<p><span><em> int n=strlen(s1);<br />
</em></span></p>
<p><span><em> for(int i=1; i&lt;=n; cout.write(s1,i++)&lt;&lt;endl);<br />
</em></span></p>
<p><span><em> cout.write(s1,30)&lt;&lt;endl;<br />
</em></span></p>
<p><span>В результате работы цикла <em>for</em> этого фрагмента на экран будут выданы следующие строки:<br />
</span></p>
<p><span><em>М<br />
</em></span></p>
<p><span><em>Мо<br />
</em></span></p>
<p><span><em>Мос<br />
</em></span></p>
<p><span><em>Моск<br />
</em></span></p>
<p><span><em>Москв<br />
</em></span></p>
<p><span><em>Москва<br />
</em></span></p>
<p><span>Результат работы следующей после цикла <em>for</em> строки будет зависеть от используемого компилятора. Так, для компиляторов Borland C++ 5.02 и wxDev-C++ 7.4, скорее всего, будет выдана строка &#8220;Москва&#8221;, после которой сразу же – строка &#8220;Стерлитамак&#8221; и еще часть символов (до 30). Таким образом, отмеченные выше компиляторы располагают строки рядом, в соседних ячейках памяти. Этого нельзя сказать о компиляторе Microsoft Visual C++ 2005 Express, – он чаще всего не располагает строки в соседних ячейках памяти.<br />
</span></p>
<p><span>Как и метод <em>put()</em>, метод <em>write()</em> можно использовать с числовыми данными. Но в данном случае методу <em>write()</em> нужно передать адрес числа, приведя его тип к <em>char*</em>:<br />
</span></p>
<p><span><em>long a1 = 97, a2 = 24929, a3 = 6381921;<br />
</em></span></p>
<p><span><em>cout.write((char*) &amp;a1, sizeof(long))&lt;&lt;endl;<br />
</em></span></p>
<p><span><em>cout.write((char*) &amp;a2, sizeof(long))&lt;&lt;endl;<br />
</em></span></p>
<p><span><em>cout.write((char*) &amp;a3, sizeof(long))&lt;&lt;endl;<br />
</em></span></p>
<p><span>Такой вывод не отобразит число в корректные символы, но передаст битовое представление того, что находится в памяти. Так, например, приведенный фрагмент кода программы выдаст на экран следующие строки:<br />
</span></p>
<p><span><em>a<br />
</em></span></p>
<p><span><em>aa<br />
</em></span></p>
<p><span><em>aaa<br />
</em></span></p>
<p><span>Полученный результат легко объясняется с точки зрения его интерпретации как ASCII-кода символа в двоичном представлении, что показано ниже в таблице 1. Таким образом, в некоторых случаях имеет смысл использовать метод <em>write()</em> для отображения числовых данных.<br />
</span></p>
<p style="text-align: left;"><span>Таблица 1. Интерпретация результата работы метода <em>write()</em> для числовых данных типа long<br />
</span></p>
<div style="text-align: center; margin-left: 5pt;">
<table style="border-collapse: collapse;" border="0">
<colgroup>
<col style="width: 156px;" />
<col style="width: 150px;" />
<col style="width: 333px;" /></colgroup>
<tbody valign="top">
<tr>
<td style="padding-left: 7px; padding-right: 7px; border: solid 1pt;" valign="middle"><span>Результат работы<br />
</span><span>метода <em>write()</em></span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: solid 1pt; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle"><span>Значение числовой<br />
</span><span>переменной</span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: solid 1pt; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;" valign="middle"><span>Двоичный код числовой<br />
</span><span>переменной</span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span>a</span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>97</span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>01100001</span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span>aa</span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>24929</span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>01100001 01100001</span></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 1pt; border-bottom: solid 1pt; border-right: solid 1pt;"><span>aaa</span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>6381921</span></td>
<td style="padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 1pt; border-right: solid 1pt;"><span>01100001 01100001 01100001</span></td>
</tr>
</tbody>
</table>
</div>
<p><span>После изучения представленного выше материала с целью оценки уровня усвоения учащимися учебного материала может оказаться удобным использование всевозможных программ-тестов [2, 3], в том числе в дистанционной форме. </span></p>
]]></content:encoded>
			<wfw:commentRss>https://web.snauka.ru/issues/2016/12/75884/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
