Intmain()// Основная функция программы – начало выполнения программы
Intmain()
{
cout<< "Это пример программы на языке C++"<<endl;
return 0;
}
Это исходный код программы (исходный код – это текст, написанный на одном из языков высокого уровня – в данном случае – на языке C++). Его нельзя выполнить. Для выполнения программы с помощью компилятора надо получить результирующую программу (объектный код).
Таким образом, необходимо выполнить следующие действия:
1. написать текст программы (создать исходный код);
2. откомпилировать этот текст (получить объектный код результирующей программы);
3. выполнить результирующую программу.
Особенности выполнения этих действий существенно зависят от используемой системы программирования.
Программа, приведенная выше, имеет несколько недостатков:
1. При ее выполнении в большинстве случаев (в зависимости от используемой среды программирования) невозможно увидеть результат ее работы;
2. Выведенный в консольное окно текст на русском языке будет нечитабельным.
Вот второй вариант этой же программы, лишенный этих недостатков:
#include<iostream>/* Директива препроцессору включить в текст заголовочный файлбиблиотеки классов C++ для управления вводом – выводом */
usingnamespacestd;/*Директива компилятору использоватьпространство имен std стандартной библиотеки С++ */
Intmain()// Основная функция программы – начало выполнения программы
{
setlocale(0, "");// Установка локальных настроек на вывод русского текста
cout<< "Это пример программы на языке С++"<<endl; // Вывод на экран
system("Pause");// Приостановка выполнения программы
Номера разрядов: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Значения разрядов: 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 ,
а отрицательное число -22выглядит следующим образом:
Номера разрядов: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Intmain()
{
inti = 100000, k;
shortj = 10000, m;
k = j; // Короткое целое преобразуется к целому без потерь
m = i; // Преобразованиецелого к короткому целому приводит к искажению данных
cout<<k<< " " <<m<<endl; // На экран будет выведено: 10000 -31072
k = 12500;
m = k; // Потери данных нет
cout<<k<< " " <<m<<endl; // На экран будет выведено: 12500 12500
doubled = 1.8234, n1, n2;
n1 = i; // Без ошибок
n2 = j; // Без ошибок
k = d; // С потерей точности
j = d; // С потерей точности
/* На экран будет выведено: 100000 10000 1 1 */
cout<<n1 << " " <<n2 << " " <<k<< " " <<j<<endl;
d = 1e+100;
k = d; // С потерей данных
m = d; // С потерей данных
/* На экран будет выведено: 1е+100 -2147483648 0 */
cout<< d << " " << k << " " << m <<endl;
system("Pause");
return 0;
}
Операция присваивания в свою очередь является выражением, значением которого является значение переменной в левой части после присваивания (эту переменную часто называют L-значением (от слова left– левая сторона)).Например:
#include<iostream>
usingnamespacestd;
Intmain()
{
inti = 7, j = 30, k;
cout<<i * j<<endl;
cout<< (k = i * j) <<endl;
cout<< k <<endl;
system("Pause");
return 0;
}
Результат работы программы: 210,210, 210.
Благодаря тому, что операция присваивания является выражением, в языке C++ возможно множественное присваивание: <Переменная1> = <Переменная2> = … = <ПеременнаяN> = <Выражение>. Например:
#include <iostream>
using namespace std;
Int main()
{
inti = 7, j = 30, k, l, m, n;
k = l = m = n = i + j;
cout<< k << " " << l << " " << m << " " << n << " " <<endl;
system("Pause");
return 0;
}
Результат работы программы: 37 37 37 37
Операция присваивания имеет самый низкий приоритет
Операции составного присваивания
Операции этой группы перечислены в следующей таблице:
Операция | Использование | Эквивалент |
*= | a *= b | a = a * b |
/= | a /= b | a = a / b |
%= | a %= b | a = a % b |
+= | a += b | a = a + b |
-= | a -= b | a = a - b |
<<= | a <<= b | a = a << b |
>>= | a >>= b | a = a >> b |
&= | a &= b | a = a & b |
|= | a |= b | a = a | b |
^= | a ^= b | a = a ^ b |
Общий формат записи выражений с использованием этих операций: < Переменная>< Операция >= < Выражение>
Эквивалентом этого формата в общем случае является:< Переменная> = <Переменная>< Операция >< Выражение>
Таким образом, выражение с использованием составного присваивания является укороченной формой записи соответствующего эквивалентного выражения.
17. Понятие L – значения.
Операция присваивания в свою очередь является выражением, значением которого является значение переменной в левой части после присваивания (эту переменную часто называют L-значением (от слова left– левая сторона)).Например:
#include<iostream>
usingnamespacestd;
Intmain()
{
inti = 7, j = 30, k;
cout<<i * j<<endl;
cout<< (k = i * j) <<endl;
cout<< k <<endl;
system("Pause");
return 0;
}
Результат работы программы: 210,210, 210.
18. Преобразование типов данных.
Рассмотрим пример:
Определены переменные
inta = 5;
doubleb = 7.6;
В программе необходимо подсчитать их сумму a + b.
Внутреннее (машинное) представление типа intи типа double существенно различаются. Существенно различаются и процедуры сложения целых значений и процедуры сложения вещественных значений. Как же тогда сложить целое и вещественное? Выход – преобразовать оба значения к одному и тому же типу данных, а затем выполнить соответствующую операцию. Но если преобразовать значение переменной b к целому типу данных (отбросить дробную часть или округлить до ближайшего целого) результат будет равен либо 12, либо 13, то есть произошла потеря точности. А вот если сначала преобразовать значение a к типу double и сложить их как вещественные значения, тогда точность потеряна не будет (результат будет равен 12.6 и будет вещественного типа). На самом деле так и происходит.
Следовательно, при выполнении различных операций над разнотипными данными необходимы преобразования одних типов данных к другим.
В языке C++ различают неявное (автоматическое) и явное преобразование типов данных.
Неявное преобразование типов данных при выполнении операций, подобной рассмотренной выше (и в ряде других случаев), выполняется компилятором по определенным правилам автоматически. В чем же состоят эти правила?
Схема преобразования, используемая при выполнении арифметических операций, называется обычными арифметическими преобразованиями. Эта схема может быть описана следующими правилами:
1. Все данные типов char и shortint преобразуются к типу int.
2. Если хотя бы один из операндов имеет тип double, то и другой операнд преобразуется к типу double (если он другого типа); результат вычисления имеет тип double.
3. Если хотя бы один из операндов имеет тип float, то и другой операнд преобразуется к типу float (если он другого типа); результат вычисления имеет тип float.
4. Если хотя бы один операнд имеет тип long, то и другой операнд преобразуется к типу long (если он другого типа); результат имеет тип long.
5. Если хотя бы один из операндов имеет тип unsigned, то и другой операнд преобразуется к типу unsigned (если его тип не unsigned); результат имеет тип unsigned.
Если ни один из случаев 1-5 не имеет места, то оба операнда должны иметь тип int; такой же тип будет и у результата.
Следует отметить, что компиляторы языка C++ достаточно свободно выполняют подобные преобразования, что может в ряде случаев привести к неожиданным результатам. Например:
#include <iostream>
using namespace std;
Int main()
{
unsigned a = 5;
int b = 10;
cout<< a << " - " << b << " = " << a - b <<endl;
system("Pause");
return 0;
}
Результат работы программы: 5 – 10 = 4294967291
Таким образом, несмотря на то, что язык C++ достаточно «снисходителен» к действиям программиста, это требует от программиста еще большей дисциплины в его действиях и четких знаний нюансов языка программирования.
Для исправления ошибки в работе предыдущей программы можно, например, изменить вычисление выражения a–bследующим образом: (int) a – bили int(a) – b.В этом случае мы получим правильный результат: 5 – 10 = -5.
Здесь было использовано явное преобразование типов данных.
Явное преобразование типов данных осуществляется с помощью соответствующей операции преобразования типов данных, которая имеет один из двух следующих форматов:(<тип данных>) <выражение>или <тип данных> (<выражение>). Например:
(int) 3.14int (3.14)
(double) aилиdouble (a)
(long) (a + 1e5f) long (a + 1e5f)
Подобные преобразования имеют своим исходом три ситуации:
· преобразование без потерь;
· с потерей точности;
· с потерей данных.
Преобразование происходит без потерь, если преобразуемое значение принадлежит множеству значений типа, к которому осуществляется преобразование. Например:
shorta = 100;
cout<< (int) a<<endl; // На экран выведено 100
cout<< (char) a<<endl; // Выведена буква d(ее десятичный эквивалент - 100)
cout<< (float) a<<endl; // На экран выведено 100
cout<< (double) a<<endl; // На экран выведено 100
float b = 3.14f;
cout<< (double) b <<endl; // Наэкранвыведено3.14
double d = 3.14;
cout<< (float) d<<endl; // На экран выведено 3.14
Преобразование любого вещественного типа к целому осуществляется путем отбрасывания дробной части вещественного значения, поэтому практически всегда такие преобразования приводят к потере точности (осуществляются приближенно). Например:
doubled = 3.74;
cout<< (int) d<<endl; // Наэкранвыведено3
А вот попытки преобразования значений выходящих за пределы диапазона типа данных, к которому осуществляется преобразование, приводят к полному искажению данных. Например:
int a = -100;
cout<< (unsigned) a <<endl; // Наэкранвыведено4294967196
int a = 50000;
cout<< (short) a <<endl; // Наэкранвыведено-15536
float b = 3e+9f;
cout<< (int) b <<endl; // Наэкранвыведено-2147483648
double d = 3e+9;
cout<< (int) d <<endl; // Наэкранвыведено-2147483648
double d = 3e+40;
cout<< (float) d <<endl; // Наэкранвыведено1.#INF- переполнение
double d = -3e+40;
cout<< (float) d<<endl; // На экран выведено -1.#INF- переполнение
Рассмотренная операция преобразования типов перешла в C++ изC. В C++ имеются свои операции преобразования типов данных. Например, рассмотренные выше преобразования в C++ можно было бы выполнить с помощью операции static_cast, имеющей следующий формат:static_cast<тип данных> (выражение).Например:static_cast<double> (a + 2e+40f)
Пользоваться явными преобразованиями типов следует очень аккуратно и только там, где это действительно необходимо.
При явном преобразовании типов значения преобразуемых величин на самом деле не изменяются – изменяется только представление этих значений при выполнении действий над ними.
19. Арифметические преобразования.
Унарный плюс (+) и унарный минус (-)Единственный операнд любого арифметического типа. Формат записи: + < Выражение >,- < Выражение >
Унарный плюс возвращает значение операнда без изменений.
Унарный минус (его иногда называют арифметическим отрицанием) меняет знак операнда на обратный.
Умножение - * - бинарная операция. Примеры записи: a * b 2 * 3 a * 0.56
Операнды могут быть любого арифметического типа данных. Тип данных результата операции определяется правилами неявного преобразования типов.
При выполнении возможен выход реального значения результата за допустимый диапазон значений типа данных – при этом значение результата операции трудно предсказать. Например: cout<< 1000000 * 1000000; // Результат: -727379968,cout<< 1е20f * 1e20f; // Результат: 1.#INF –переполнение (+ бесконечность), cout<< 1е20f * -1e20f; // Результат: -1.#INF –переполнение (- бесконечность).
Деление - / - бинарная операция. Примеры записи: a / b 2 / 3 a / 0.56
Если оба операнда являются целыми, то результат деления будет целым. В этом случае целый результат получается отбрасыванием дробной части от полученного реального значения (не округление). Например:5 / 3 - результат равен 1.
Если все же в результате выполнения этой операции требуется получить значение с дробной частью, необходимо чтобы хотя бы один из операндов был вещественного типа. Например:5.0 / 3или 5 / 3.или5.0 / 3.0 или5 / 3fили 5f / 3или 5f / 3fили float (5) / 3илиdouble (5) / 3
Результатом вычисления всех этих выражений будет значение 1.6666… одного из вещественных типов.
Однако, например, выражение double (5 / 3)хотя и будет вещественного типа, но его значение все равно будет равно 1, поскольку сначала будет вычислено выражение в скобках, результат которого будет целого типа и будет равен 1, а затем это значение будет приведено к вещественному типу.
При выполнении операции возможен выход реального значения результата за допустимый диапазон значений типа данных – при этом значение результата операции трудно предсказать. Например: cout<< 1е35f / 0.0001f; // Результат: 1.#INF –переполнение (+ бесконечность), cout<< 1е20f / -0.0001f; // Результат: -1.#INF –переполнение (- бесконечность), cout<< 1е200 / 1e-200; // Результат: 1.#INF –переполнение (бесконечность).
Если первый операнд вещественного типа, то деление на 0 дает значение 1.#INF или -1.#INF. Если же он целого типа, возникает ошибка режима исполнения (деление на 0).
Остаток от деления - % - бинарная операция. Операнды только целого типа. Результат операции целого типа. Например: 5 % 1 - результат 0,5 % 2 - результат 1,5 % 3 - результат 2,5 % 4 - результат 1, 5 % 5 - результат 0, 5 % 6 - результат 5…..
Если второй операнд равен 0, возникает ошибка режима исполнения (деление на 0).
Сложение (+) и вычитание (-) – бинарные операции. Операнды могут быть любых арифметических типов данных. Примеры записи:a + b, a – b
Тип результата операций определяется правилами неявного преобразования типов.
При выполнении операций возможны ошибки переполнения и некорректного преобразования типов данных операндов.Например:
unsignedshortn = 0, m;
m = n - 1;
cout<<m<<endl; //На экран будет выведено65535
n = m + 1;
cout<<n<<endl; //На экран будет выведено0
20. Операции инкремента и декремента, их разновидности
Инкремент (++) и декремент (--) – унарные операции увеличения и уменьшения операнда на 1соответственно. Операнд может быть любого арифметического типа данных.
Операции имеют две формы – префиксную(++a, --a) ипостфиксную(a++, a--).
Независимо от формы операция инкремента эквивалентна следующему оператору: a = a + 1; аоперациядекрементаследующему:a = a - 1; Например:
#include <iostream>
using namespace std;
Int main()
{
inti = 7, j = 10;
++ i;
j ++;
cout<<i<< "\t" <<j<<endl; // На экран выведено 8 11
-- i;
j --;
cout<<i<< "\t" <<j<<endl; // На экран выведено 7 10
system("Pause");
return 0;
}
Изпримеравидно, что разница между префиксной и постфиксной формами этих операций не чувствуется. Действительно в этом примере эти две формы работают одинаково.
Немного изменим текст программы:
#include <iostream>
using namespace std;
Int main()
{
inti = 7, j = 10;
cout<< ++ i<< "\t " <<j ++ <<endl; // На экран выведено 8 10
cout<<i<< "\t " <<j<<endl; // На экран выведено 8 11
cout<< -- i<< "\t " <<j -- <<endl; // На экран выведено 7 11
cout<<i<< "\t " <<j<<endl; // На экран выведено 7 10
system("Pause");
return 0;
}
Разница между префиксной и постфиксной формами этих операций заключается в том, что при префиксной форме, переменная сначала меняет свое значение, а потом это измененное значение обрабатывается. В постфиксной форме значение переменной сначала обрабатывается и только потом ее значение изменяется на 1.
В первом примере операторы ++ i; j ++;просто изменяютзначения переменных iи jбез какой-либо другой обработки и только после окончания работы этих операторов на экран выводятся эти измененные значения. Поэтому различие между префиксной и постфиксной формами не чувствуется. То же самое происходит и при выполнении операторов -- i; j--;.
Во втором примерепрефиксные и постфиксные формыопераций инкремента и декремента участвуют в выполнении оператора вывода данных на экран. Поэтому при выполнении префиксных операций сначала происходит изменение значений переменной i, потом эти измененные значения выводятся на экран, а при выполнении постфиксных операций сначала выводятся неизмененные значения переменной j, а уже после этого производятся изменения значения этой переменной.
А как интерпретировать такие выражения:a+++b, a---b
Эти выражения следует интерпретировать так:(a++) + b,(a--) - b
Но не так: a + (++b), a - (--b)
Для более понятной записи текста программы в подобных случаях лучше использовать скобки.
21. Операции отношения.
Операции этой группы служат для сравнения значений. Сюда входят следующие операции:
· == - равно;
· != - не равно;
· >- больше;
· >= - больше или равно;
· < - меньше;
· <= - меньше или равно.
Все эти операции бинарные. В качестве операндов могут быть использованы выражения любых арифметических типов данных. Результат этих операций всегда логического типа (bool).
Примеры: a == b,a != b,a> 10,(a - 3) >= (b + 10).
22. Логические операции.
Эти операции используются при построении сложных логических выражений. В эту группу входят 3 операции:
· !- логическое отрицание (логическое НЕ);
· && - конъюнкция (логическое И);
· || - дизъюнкция (логическое ИЛИ).
Первая операция унарная, две остальные – бинарные. Операнды – выражения любого арифметического типа данных, значения которых интерпретируются как значения логического типа (отличное от 0 значение – true; 0 - false) . Результат этих операций - логического типа.
Правила записи и результаты выполнения логических операций приведены в следующей таблице:
a | b | !a | a&&b | a||b |
Пусть, например, имеется математическое неравенство:0 <x< 10. На языке C++ это неравенство следует записывать так:(0 <x) && (10 >x)или (х > 0) && (x< 10). А математическое неравенство 0 >x> 10должно выглядеть следующим образом: (0 >x) || (10 <x)или (х < 0) || (x> 10).
Особенностью выполнения операций &&и || является то, что второй операнд (в правой части операций) вычисляется не всегда. Он вычисляется только в том случае, если значения первого операнда недостаточно для получения результата операций &&или ||.
Например. Если в выражении (a + 10) && (b – 1)значение первого (левого) операнда a + 10равно 0 (false) (это будет при значении a = -10), то вычисление второго (правого) операнда b – 1не выполняется, так как и без его вычисления, значение результата операции &&уже известно – это false. А в выражении (a + 10) || (b – 1) второй операнд не будет вычисляться в том случае, если первый операнд не равен 0– в этом случае результат операции ||и так уже известен – он равен true.
23. Побитовые операции сдвига
Побитовые операции рассматривают операнды как упорядоченные наборы битов,
каждый бит может иметь одно из двух значений - 0 или 1 (наборы двоичных значений).Такие операции позволяютпрограммисту манипулировать значениями отдельных битов. Объект, содержащий наборбитов, иногда называют битовым вектором. Он позволяет компактно хранить наборфлагов- переменных, принимающих значение "да" "нет".
Операции сдвига - <<и >> - бинарные операции. Операнды целого типа. Результат также целого типа. Формат записи:< Операнд 1 ><<< Операнд 2 > -сдвиг влево, < Операнд 1 >>>< Операнд 2 > -сдвиг вправо
Операции выполняют копирование битов двоичного представления первого операнда с сдвигом на количество разрядов, указанное во втором операнду, в соответствующем направлении.
Значение второго операнда должно быть больше или равно 0 и меньше количества двоичных разрядов первого операнда, иначе результат выполнения операций не гарантирован (зависит от реализации, но обычно равен 0). Примеры:
unsigned a = 20, n = 3, r;
r = a << n;
cout<< r <<endl; //Наэкранвыведено160
r = a >> n;
cout<<r<<endl; //На экран выведено 2
Иллюстрация:
Номер разряда: 31 30 … 8 7 6 5 4 3 2 1 0
Значение a: 0 0 … 0 0 0 0 1 0 1 0 0 = 20
Операция: a<<n
Значение r: 0 0 … 0 1 0 1 0 0 0 0 0 = 160
Операция: a>>n
Значение r: 0 0 … 0 0 0 0 0 0 0 1 0 = 2
Операция сдвига влево осуществляет перемещение битов левого операнда a в сторону больших разрядов на количество разрядов, равное значению правого операнда n. Это эквивалентно умножению значения a на 2 в степени n(20 * 8 = 160).
Операция сдвига вправо осуществляет перемещение битов левого операнда a в сторону меньших разрядов на количество разрядов, равное значению правого операнда n. Это эквивалентно делению значения a на 2 в степени n(целочисленное деление 20 / 8 = 2).
Используя операцию сдвига влево очень просто получить любую целую степень двойки в диапазоне степеней равной количеству двоичных разрядов правого операнда без 1. Например, так:1U<< 20 - равно 2 в степени 20, то есть 1048576
При сдвиге влево (в сторону старших разрядов), освобождающиеся младшие разряды замещаются 0 (нулями). При сдвиге вправо возможны две ситуации: если первый операнд беззнаковый (unsigned), то освобождающиеся старшие разряды замещаются 0; если же первый операнд знаковый, то освобождающиеся старшие разряды замещаются либо знаковым разрядом, либо 0 (нет гарантии - зависит от реализации).
Примеры применения побитовых операций.
Примеры:
unsigned a = 20, n = 3, r;
r = a << n;
cout<<r<<endl; //На экран выведено 160
r = a >> n;
cout<<r<<endl; //На экран выведено 2
Иллюстрация:
Номер разряда: 31 30 … 8 7 6 5 4 3 2 1 0
Значение a: 0 0 … 0 0 0 0 1 0 1 0 0 = 20
Операция: a<<n
Значение r: 0 0 … 0 1 0 1 0 0 0 0 0 = 160
Операция: a>>n
Значение r: 0 0 … 0 0 0 0 0 0 0 1 0 = 2
inta = 14, b = 7, r;
r = a&b;
cout<<r<<endl; //На экран выведено6
r = a | b;
cout<<r<<endl; //На экран выведено15
r = a ^ b;
cout<<r<<endl; //На экран выведено9
Иллюстрация:
Номер разряда: 31 30 … 8 7 6 5 4 3 2 1 0
Значение a: 0 0 … 0 0 0 0 0 1 1 1 0 = 14
Значение b: 0 0 … 0 0 0 0 0 0 1 1 1 = 7
Операция: a&b
Значение r: 0 0 … 0 0 0 0 0 0 1 1 0 = 6
Операция: a | b
Значение r: 0 0 … 0 0 0 0 0 1 1 1 1 = 15
Операция: a ^ b
Значение r: 0 0 … 0 0 0 0 0 1 0 0 1 = 9
unsigneda = 1234; // Целое значение, битами которого мы будем управлять
unsignedshortn = 4;// Номер необходимого бита (от 0 до 31)
boolr; // Значение результата (0 или 1)
/* Узнаем, чему равен n-й бит (двоичный разряд) значения a. Результат поместим в переменную r */
r = a& (1U<<n);
cout<< "Разряд с номером " <<n<< " равен " <<r<<endl; //значение1
Иллюстрация вычисления этого выражения:
Номер разряда: 31 30 … 11 10 9 8 7 6 5 4 3 2 1 0
1U: 0 0 … 0 0 0 0 0 0 0 0 0 0 0 1 = 1
1U<<n: 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0
Значение a: 0 0 … 0 1 0 0 1 1 0 1 0 0 1 0 = 1234
a& (1U<<n): 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0 = 16
Int main ()
{
setlocale (0, "");
int a;
printf ("Введите целое число:\t");
scanf ("%d", &a);
printf ("Выввелизначение:\t%d\n\n", a);
system ("Pause");
return 0;
}
Второй способ, характерный для C++, основан на использовании стандартных потоков ввода (cin) и вывода (cout). Та же самая программа в стиле C++ будет выглядеть так:
#include <iostream>
using namespace std;
Int main ()
{
setlocale (0, "");
int a;
cout<< "Введите целое число:\t";
cin>>a;
cout<< "Вы ввели значение:\t" <<a<< "\n\n";
// cout<< "Вы ввели значение:\t" <<a<<endl<<endl;
system ("Pause");
return 0;
}
В одной и той же программе совмещать эти два способа не рекомендуется.
При использовании потоков для вывода данных на экран используется операция <<, которая так и называется: операция вывода или операция вставки (данные "вставляются" в поток вывода).
Ввод данных с клавиатуры осуществляется с помощью операции ввода>>(операция извлечения данных из потока ввода).
Обе эти операции "знают" как осуществлять ввод и вывод стандартных простых типов данных. Более того эти операции можно "научить", как осуществлять ввод/вывод нестандартных пользовательских типов данных (перегрузка операций).
Вывод текстовых строк
Текстовые (строковые) литералы в C++ представляются как последовательность символов, заключенная в двойные кавычки. Например: "Это пример текстовой строки".
Вывод текстовых строк на экран осуществляется через стандартный поток вывода с помощью операции вывода <<: cout<< "Это пример текстовой строки";
Внутрь текстовых строк можно вставлять управляющие escape-последовательности. Escape-последовательности служат для управления выводом, и представляют собой специальные последовательности из двух или более символов, начинающиеся символом обратной наклонной черты - \. При этом каждая такая последовательность воспринимается компилятором как 1 символ. Примерами таких управляющих последовательностей в предыдущих программах являются \t - символ табуляции и \n - символ перевода строки (все эти последовательности приведены в разделе 3.5). С помощью Escape-последовательностей в текстовую строку можно включить любой символ с помощью его восьмеричного или шестнадцатеричного кода (в том числе и символы, которых нет на клавиатуре). Например:cout<< "Это символ с восьмеричным кодом 254:\t\254\n";cout<< "А это символ с шестнадцатеричным кодом xAA:\t\xAA\n";
На экран будут выведены две строки: Это символ с восьмеричным кодом 254: А это символ с шестнадцатеричным кодом xAA: Є
Если на экран необходимо вывести пустую строку, достаточно вставить в поток дважды подряд управляющую последовательность \n:
cout<< "Это первая строка\n";
cout<< "\n";// Вторая строка пустая
cout<< "Это третья строка\n";
При выводе длинных текстовых строк их можно в тексте программы разбивать на части следующим образом:
cout<< "Это " \
"условный " \
"пример " \
"длинного " \
"текста\n"
или так
cout<< "Это " "условный " "пример "
"длинного " "текста\n";
На экран будет выведена одна строка, после чего экранный курсор перейдет на новую строку (управляющая последовательность \n): Это условный пример длинного текста
Символ \ и символ пробела можно использовать для "сцепления" отдельных строк. Если в программе встречаются два или более строковых литерала, разделенные только пробелами, то они будут рассматриваться как одна символьная строка.
Ввод текстовых строк с клавиатуры будет рассмотрен позже.
Int main ()
{
setlocale (0, "");
inti;
double d;
char c;
bool b;
cin>>i;
cout<<i;
cin>> d;
cout<< d;
cin>> c;
cout<< c;
cin>> b;
cout<< b;
system ("Pause");
return 0;
}
Особенности:
1. Ввод/вывод целочисленных значений осуществляется обычным образом в десятичной системе счисления.
2. Ввод вещественных типов данных можно осуществлять либо в формате с фиксированной точкой, либо в экспоненциальном формате.
3. Формат вывода вещественных значений выбирается автоматически в зависимости от выводимого значения.
4. Ввод символьных значений можно осуществлять только в виде одиночного символа. При вводе нескольких символов переменной cбудет присвоен только первый символ. Могут возникнуть сложности с вводом русских букв.
5. Ввод/вывод логических значений осуществляется в числовом формате (0 - false, 1 - true).
Замечание:
При вводе числовых данных с клавиатуры могут возникать непредвиденные ошибки, вызванные вводом символов, недопустимых для числовых форматов. Например:inti;cin>>i;
При попытке ввода с клавиатуры числа 1234 допущена ошибка - набрано 12y34 и нажата клавиша ENTER (ошибочно была нажата клавиша y). Переменная i в этом случае будет содержать значение 12, и эта ошибка может привести к непредсказуемому дальнейшему поведению программы. В любом случае символы из потока ввода извлекаются оператором >>до тех пор, пока они соответствуют числовому формату. Как только в потоке ввода встречается символ, не соответствующий числовому формату, уже извлеченные символы преобразуются в числовое значение и присваиваются переменной ввода. Остальные символы игнорируются.
31. Флаги форматирования потоков ввода\вывода.
Более гибкое управление вводом/выводом (форматирование ввода/вывода) в C++ осуществляется либо с помощью установки флагов форматирования, либо с помощью специальных манипуляторов ввода/вывода.
Intmain ()
{
setlocale (0, "");
cout<< 255 <<endl; //На экране видим 255 -по умолчанию установлен флаг dec
cout.setf (ios :: hex); //Включаем флагhex- хотим видеть на экране ff
cout<< 255 <<endl; //На экране видим 255- изменений не произошло
system ("Pause");
return 0;
}
В этом примере установка флагаhex не привела ни к каким изменениям. Причиной этого явилось то, что одновременно с установленным флагом hex остался установленным и флаг dec. Для исправления ситуации необходимо сначала отключить флаг dec, а затем уже установить флаг hex:
cout.unsetf(ios :: dec); //Отключаемфлагdec
cout.setf(ios :: hex); //Включаемфлагhex- хотим видеть на экране ff
cout<< 255 <<endl;//На экране видим ff- то, что хотели
Среди всех флагов можно выделить три группы, в каждой из которых флаги управляют одной и той же характеристикой ввода / вывода, но являются взаимоисключающими. Флагам каждой из этих групп в классе ios присвоены обобщающие имена:
Группа | Флаги | Обобщающее имя |
Флаги основания систем счисления | dec, oct,hex | basefield |
Флаги выравнивания | left, right,internal | adjustfield |
Флаги формата вещественных значений | scientific,fixed | floatfield |
Обобщающие имена групп удобно использовать для выполнения операции со всеми флагами группы, например, для сброса всех флагов группы:cout.unsetf (ios ::basefield); //Отключаемфлагиdec, oct, hexза один прем
Болеетого, функциюsetfможно использовать с двумя параметрами: setf (новые флаги, маска)
В этом случае функция setfустанавливает только те флаги, которые одновременно присутствуют и в первом и во втором параметре, а те флаги, которые присутствуют во втором параметре, но отсутствуют в первом, будут сброшены. Это дает возможность отключать и включать флаги за один вызов функции setf. Например, для установки любого флага из группы basefield достаточно использовать всего один оператор: cout.setf (ios :: hex, ios ::basefield);
Здесь второй параметр содержит три флага: dec, oct,hex. Первый параметр содержит флаг hex. Этот флаг будет установлен, а флаги dec и oct будут сброшены.
В классе coutимеются еще несколько функций управляющих форматом вывода данных. К ним относятся:
· precision - определяет точность представления вещественных значений;
· width - устанавливает ширину поля вывода;
· fill - определяет символ заполнения при выводе данных.
34. Управление шириной поля вывода и выравниванием данных при выводе
35. Управление форматом вывода вещественных значений
36. Основные понятия структурного программир<