Remarks
Объект можно использовать для наблюдения за потоком выполнения в приложении и управления этим потоком. Объект потока, созданный с помощью конструктора по умолчанию, не связан ни с одним потоком выполнения. Объект потока, который создается с использованием вызываемого объекта, создает новый поток выполнения и вызывает вызываемый объект в этом потоке. Объекты потока можно переместить, но не копировать. Именно поэтому поток выполнения может быть связан только с одним объектом потока.
Каждый поток выполнения имеет уникальный идентификатор типа . Функция возвращает идентификатор вызывающего потока. Функция-член возвращает идентификатор потока, который управляется объектом потока. Для объекта потока, созданного конструктором по умолчанию, метод возвращает объект с одинаковым значением для всех объектов потока, созданных конструктором по умолчанию; это значение отличается от значения, которое возвращается для любого потока выполнения, который может быть присоединен во время вызова.
Использование объекта cout
Для стандартного вывода (вывода на экран) в языке C++ используется объект cout и операторы «<<«. Например, для вывода значения переменной a можно написать:
cout << a;
Для вывода значений переменных a и b через пробел так:
cout << a << » » << b;
В этом примере мы даем команду сначала вывести значение переменной a, затем строку из одного пробела, затем вывести значение переменной b.
Для перехода на следующую строку нужно либо вывести специальный символ ‘\n’, либо использовать объект endl. Приведем примеры использования обоих способов для вывода значений переменных в отдельных строках:
cout << a << «\n» << b << endl;
Через cout можно выводить все стандартные типы данных — целые и действительные числа, символы, строки (как C-строки, так и объекты string), заботиться о задании типов данных при этом не нужно, компилятор автоматически распознает необходимые типы.
Для использования стандартного ввода-вывода в языке C++ необходимо подключить заголовочный файл iostream:
#include<iostream>
Манипуляторы потока
Функцию — манипулятор потока можно включать в операции помещения в поток и извлечения из потока (<<, >>).
В С++ имеется ряд манипуляторов. Рассмотрим основные:
Манипулятор | Описание |
endl | Помещение в выходной поток символа конца строки ‘\n’ |
dec | Установка основания 10-ой системы счисления |
oct | Установка основания 8-ой системы счисления |
hex | Установка основания 16-ой системы счисления |
setbase | Вывод базовой системы счисления |
width(ширина) | Устанавливает ширину поля вывода |
fill(‘символ’) | Заполняет пустые знакоместа значением символа |
precision(точность) | Устанавливает количество значащих цифр в числе (или после запятой) в зависимости от использования fixed |
fixed | Показывает, что установленная точность относится к количеству знаков после запятой |
showpos | Показывает знак + для положительных чисел |
scientific | Выводит число в экспоненциальной форме |
get() | Ожидает ввода символа |
getline(указатель, количество) | Ожидает ввода строки символов. Максимальное количество символов ограничено полем количество |
Пример Программа ввода-вывода значения переменной в C++
1234567891011
#include <iostream>using namespace std;int main(){ int n; cout << «Введите n:»; cin >> n; cout << «Значение n равно: » << n << endl; cin.get(); cin.get(); return 0;}
12345678910
#include <stdio.h>int main(){ int n; printf(«Введите n:»); scanf(«%d», &n); printf(«Значение n равно: %d\n», n); getchar(); getchar(); return 0;}
Пример
1234567891011121314151617181920212223242526
#include <iostream>using namespace std;int main(){ double a = -112.234; double b = 4.3981; int c = 18; cout << endl << «double number:» << endl; cout << «width(10)» << endl; cout.width(10); cout << a << endl << b << endl; cout << «fill(‘0’)» << endl; cout.fill(‘0’); cout.width(10); cout << a << endl << b << endl; cout.precision(5); cout << «precision(5)» << endl << a << endl << b << endl; cout << «fixed» << endl << fixed << a << endl << b << endl; cout << «showpos» << endl << showpos << a << endl << b << endl; cout << «scientific» << endl << scientific << a << endl << b << endl; cout << endl << «int number:» << endl; cout << showbase << hex << c << » » << showbase << oct << c << » «; cout << showbase << dec << c << endl; cin.get(); return 0;}
12345678910111213141516
#include <iostream>using namespace std;int main(){ cout << fixed; for (double t = 0; t <= 3; t += 0.5) { cout.width(3); cout.precision(1); cout << t; cout.width(8); cout.precision(3); cout << cos(t) << endl; } system(«pause»); return 0;}
Язык C++
rotl
Поворачивает биты целочисленного значения без знака влево на указанное число раз. Биты, которые «попадают» из самого левого бита, поворачиваются в самый правый бит.
Целочисленное значение без знака для поворота.
s
Количество выполняемых левых поворотов.
Возвращаемое значение
Результат поворота слева, раз.
Если значение равно нулю, возвращает .
Если является отрицательным, то имеет значение . Биты, которые попадают в крайний правый бит, поворачиваются в крайний левый бит.
Комментарии
Эта функция шаблона участвует в разрешении перегрузки только в том случае, если является целочисленным типом без знака. Например: , , , и т. д.
bit_cast
Скопируйте битовый шаблон из объекта типа в новый объект типа .
Чтобы
Тип выхода.
От
Тип, в который нужно преобразовать значение.
from
Преобразуемое значение.
Возвращаемое значение
Объект типа .
Каждый бит в результате соответствует соответствующему биту в , если в не есть биты заполнения в , в этом случае эти биты в результате не будут указаны.
Комментарии
Код низкого уровня часто должен интерпретировать объект одного типа как другой тип. Переинтерпретируемый объект имеет то же битовое представление, что и исходный, но имеет другой тип.
Вместо использования , или , является лучшим способом выполнения этих преобразований. Это лучше, поскольку:
- имеет значение .
- требует, чтобы типы были просто скопированы и иметь одинаковый размер. Это позволяет избежать потенциальных проблем, с которыми можно столкнуться при использовании и, поскольку они могут использоваться для непреднамеренного и некорректного преобразования нетривиальных копий типов. Кроме того, можно использовать для непреднамеренного копирования типов, которые имеют неодинаковый размер. Например, Double (8 байт) в целое число без знака (4 байта) или наоборот.
Эта перегрузка принимает участие в разрешении перегрузки только в том случае, если:
- и являются .
Этот шаблон функции имеет значение, только если , и типы их подобъектов:
- Не является типом объединения или указателя
- Не является указателем на тип элемента
- Без временных квалификаторов
- Не иметь нестатических элементов данных, являющихся ссылочным типом
Преобразовать десятичную в двоичную
Чтобы преобразовать десятичное число в двоичное в Java Programming, вам нужно попросить пользователя ввести любое число в формате десятичного числа, чтобы преобразовать его в формат двоичного числа для отображения эквивалентного значения в двоичной системе счисления, как показано в следующей программе.
Программный код Java для преобразования десятичного числа в двоичное
После Java-программы попросите пользователя ввести любое десятичное число, чтобы преобразовать его в двоичный, а затем отобразить результат на экране:
Когда вышеуказанная Java-программа компилируется и выполняется, она выдаст следующий вывод:
rotr
Поворачивает биты справа заданное число раз. Биты, которые «попадают» из крайнего правого бита, поворачиваются обратно в самый левый бит.
Целочисленное значение без знака для поворота.
Количество выполняемых вправо поворотов.
Возвращаемое значение
Результат поворота вправо, раз.
Если значение равно нулю, возвращает .
Если является отрицательным, то имеет значение . Биты, которые попадают из самого левого бита, поворачиваются обратно в самый правый бит.
Комментарии
Эта функция шаблона участвует в разрешении перегрузки только в том случае, если является целочисленным типом без знака. Например: , , , и т. д.
Конструктор thread
Формирует объект .
Параметры
Определяемая приложением функция, которая должна быть выполнена потоком.
Список аргументов, которые необходимо передать .
Существующий объект .
Remarks
Первый конструктор создает объект, который не связан с потоком выполнения. Значение, возвращаемое вызовом для созданного объекта, — это .
Второй конструктор конструирует объект, связанный с новым потоком выполнения, и выполняет псевдо-функцию , определенную в . Если для запуска нового потока доступно недостаточно ресурсов, функция создает объект, код ошибки которого имеет значение . Если вызов F завершается с неперехваченным исключением, вызывается метод.
Третий конструктор создает объект, связанный с потоком, который, в свою очередь, связан с . затем присваивается состояние, созданное по умолчанию.
Ввод информации
cin >> идентификатор;
При этом из входного потока читается последовательность символов до пробела, затем эта последовательность преобразуется к типу идентификатора, и получаемое значение помещается в идентификатор:
int n;cin >> n;
cin >> переменная1 >> переменная2 >>…>> переменнаяn;\n, \t
int n;char j;cin >> n >> j;
cinПример
12345678910
#include <iostream>using namespace std;int main(){ char s; cin >> s; cout << s << endl; system(«pause»); return 0;}
getline()
12345678910
#include <iostream>using namespace std;int main(){ char s; cin.getline(s, 80); cout << s << endl; system(«pause»); return 0;}
Точность
По умолчанию для чисел с плавающей запятой задана точность шесть. Например, число 3466,9768 выводится как 3466,98. Чтобы изменить способ печати этого значения, используйте манипулятор. Манипулятор имеет два флага: и . Если задано значение, число выводится как 3466,976800. Если задано значение, оно распечатывается как 3.4669773 + 003.
Чтобы отобразить числа с плавающей запятой, отображаемые при , с одной значащий цифрой, замените цикл следующим образом:
Программа выведет этот список:
Чтобы исключить экспоненциальное представление, вставьте эту инструкцию перед циклом:
С фиксированной нотацией программа выводит числа с одной цифрой после десятичной запятой.
При изменении флага на выводится следующее:
В этом случае программа также выводит числа с одной цифрой после десятичной запятой. Если задан параметр или , то значение точности определяет количество цифр после десятичной запятой. Если не установлен ни один из флагов, значение точности определяет общее количество значащих цифр. Манипулятор снимает эти флаги.
ЧТО ВАМ НЕОБХОДИМО ЗНАТЬ
Из этого урока
вы узнали несколько способов использования
cout
для отображения вывода
на экран. Все программы, которые вы создадите в процессе изучения оставшейся
части книги, будут использовать
cout
для отображения вывода. Из урока
4 вы узнаете, как использовать переменные внутри своих программ для хранения
значений, которые могут изменяться в процессе выполнения программы. Однако до
изучения урока 4 убедитесь, что вы освоили следующие основные концепции:
-
-
Выходной поток
cout
позволяет вам выводить символы и числа.
-
Используя специальные
символы внутри выходного потока, ваша программа может указать новую строку,
табуляцию и другие специальные возможности.
-
Для продвижения курсора
в начало следующей строки программы могут создать новую строку, используя
символ \n или модификатор
endl.
-
Модификаторы
dec,
oct
и
hex
позволяют программам выводить значения в десятичном,
восьмеричном и шестнадцатеричном виде.
-
Используя выходной
поток
cerr,
программы могут записать сообщения в стандартное устройство
ошибок операционной системы.
-
С помощью модификатора
setw
ваши программы могут управлять шириной вывода чисел.
-
hardware_concurrency
Статический метод, который возвращает приблизительное число контекстов аппаратного потока.
Возвращаемое значение
Приблизительное число контекстов аппаратного потока. Если значение не может быть вычислено или не определено правильно, этот метод возвращает 0.
Блок, относящийся только к системам Microsoft
в настоящее время определяется для возврата числа логических процессоров, которые соответствуют числу аппаратных потоков, которые могут выполняться одновременно. Он учитывает количество физических процессоров, число ядер в каждом физическом процессоре и одновременную многопоточность на каждом отдельном ядре.
Однако в системах с более чем 64 логическими процессорами это число ограничивается числом логических процессоров в одной группе. см. раздел группы процессоров.
Небольшой тест
Вопрос 1
Рассмотрим следующую программу, которую мы использовали выше:
Программа ожидает, что вы введете целочисленное значение, поскольку переменная , в которую будет помещен пользовательские входные данные, является целочисленной переменной.
Запустите эту программу несколько раз и опишите, что произойдет, если вместо этого вы введете следующие типы входных данных:
а) Буква, например, h.
Ответ
х равно 0.
б) Число с дробной частью. Попробуйте числа с дробными составляющими меньше 0,5 и больше 0,5 (например, 3,2 и 3,7).
Ответ
Дробная составляющая опущена.
в) Небольшое отрицательное целое число, например -3.
Ответ
Всё прекрасно работает.
г) Слово, например «Hello».
Ответ
х равно 0.
д) Действительно большое число (минимум 3 миллиарда).
Ответ
Вы получаете, казалось бы, случайное число.
Последнее предложение может быть особенно неожиданным. Попробуйте! Это происходит потому, что может содержать числа только до определенного размера. После этого он «переполняется». Мы обсудим переполнение в следующем уроке.
Побитовые операторы
Для битовых манипуляций C++ предоставляет 6 операторов, часто называемых побитовыми операторами:
Оператор | Обозначение | Пример использования | Операция |
---|---|---|---|
Сдвиг влево | Все биты в сдвигаются влево на количество бит, представленное значением | ||
Сдвиг вправо | Все биты в сдвигаются вправо на количество бит, представленное значением | ||
Побитовое НЕ (NOT) | Все биты в инвертируются | ||
Побитовое И (AND) | Выполняется операция И каждого бита в с каждым соответствующим битом в | ||
Побитовое ИЛИ (OR) | Выполняется операция ИЛИ каждого бита в с каждым соответствующим битом в | ||
Побитовое исключающее ИЛИ (XOR) | Выполняется операция исключающее ИЛИ каждого бита в с каждым соответствующим битом в |
Примечание автора
В следующих примерах мы в основном будем работать с 4-битными двоичными значениями. Это сделано для удобства и простоты примеров. В реальных программах количество используемых битов зависит от размера объекта (например, 2-байтовый объект будет хранить 16 бит).
Для удобства чтения мы также опустим префикс вне примеров кода (например, вместо 0b0101 мы будем писать просто 0101).
Десятичное в двоичное преобразование в C++
Чтобы преобразовать десятичное число в двоичное число в программировании на C++ , вы должны попросить пользователя ввести десятичное число, чтобы преобразовать его в двоичное число, чтобы отобразить эквивалентное значение в двоичном формате, как показано здесь в следующей программе.
Программный код C++ Преобразование десятичного числа в двоичный
После программы на C++ попросите пользователя ввести любое число в десятичном формате, чтобы преобразовать его в двоичный, а затем отобразить результат на экране:
Когда вышеупомянутая программа C++ компилируется и выполняется, она даст следующий результат:
Как создать программу на C, которая преобразует любое заданное число (в десятичном числе) пользователем во время выполнения в его эквивалентное значение в двоичном числе. Наконец, мы также создали программу, которая использует пользовательскую функцию для преобразования десятичного числа в двоичное.
Итераторы для multiset и set
Вот как выглядит создание итератора:
set < > :: iterator it;
multiset < > :: iterator it2;
1 |
set<тип>::iterator it; multiset<тип>::iterator it2; |
Чтобы итератор работал на определенный set или multiset, должен совпадать с типом контейнера.
При создании итератора для set и multiset нужно знать, что мы сможем только наблюдать за их значением. Это значит, что мы не сможем изменять значения существующих элементов.
Вот что можно делать с итератором на множество и мультимножество:
- Использование операции разыменования — .
- Сравнивать итераторы на равенство () и неравенство ().
- Увеличивать или уменьшать итератор, с помощью инкремента () и декремента ().
Но также у него есть свои ограничения:
- Нельзя изменять итератор используя операции сложения (), умножение (), деления ().
- Также нельзя сравнивать итераторы знаками больше () и меньше ().
Чтобы обратится к значению элемента, нужно воспользоваться операцией разыменование .
#include <iostream>
#include <set>
using namespace std;
int main() {
set <int> st;
for (int i = 0; i < 5; i++) {
st.insert(i + 1);
}
set <int> :: iterator it = st.begin();
cout << *it; // 1
it++;
cout << *it; // 2
return 0;
}
1 |
#include <iostream> usingnamespacestd; intmain(){ set<int>st; for(inti=;i<5;i++){ st.insert(i+1); } set<int>::iterator it=st.begin(); cout<<*it;// 1 it++; cout<<*it;// 2 return; } |
Также можно сравнивать итераторы на равенство () и неравенство (). Мы часто будем пользоваться данной возможностью. Например, чтобы вывести все элементы.
#include <iostream>
#include <ctime>
#include <set>
using namespace std;
int main() {
setlocale(LC_ALL, «Russian»);
srand(time(NULL));
multiset <int> mst;
cout << «Добавление случайных значений: » << endl;
for (int i = 0; i < 10; i++) {
int random = rand() % 10 + 1;
mst.insert(random);
cout << i + 1 << «) » << random << endl;
}
multiset <int> :: iterator it = mst.begin();
cout << «Отсортированный вариант: » << endl;
for (int i = 1; it != mst.end(); i++, it++) {
cout << *it << » «;
}
system(«pause»);
return 0;
}
1 |
#include <iostream> usingnamespacestd; intmain(){ setlocale(LC_ALL,»Russian»); srand(time(NULL)); multiset<int>mst; cout<<«Добавление случайных значений: «<<endl; for(inti=;i<10;i++){ intrandom=rand()%10+1; mst.insert(random); cout<<i+1<<«) «<<random<<endl; } multiset<int>::iterator it=mst.begin(); cout<<«Отсортированный вариант: «<<endl; for(inti=1;it!=mst.end();i++,it++){ cout<<*it<<» «; } system(«pause»); return; } |
- В строке 11: создали multiset — .
- В строках 14 — 18: заполняем мультимножество случайными значениями.
- В строке 20: инициализируем итератор на .
- В строках 22 — 25: выводим значения пользователю.
- В строке 23: мы сравнивали итераторы на неравенство (), чтобы не выйти за диапазон значений контейнера и в последствии чтобы этот цикл не выполнялся бесконечно.
Вот пример данной программы:
==_and_!=_in_multiset.cpp
Добавление случайных чисел:
1) 7
2) 5
3) 1
4) 5
5) 9
Отсортированный вариант: 1 5 5 7 9
Process returned 0 (0x0) execution time : 0.010 s
Press any key to continue.
Одновременное чтение и запись в файл с помощью fstream
Класс (почти) способен одновременно читать содержимое файла и записывать данные в него! Нюанс заключается в том, что вы не можете произвольно переключаться между чтением и записью файла. Как только начнется чтение или запись файла, то единственным способом переключиться между чтением или записью будет выполнение операции, которая изменит текущее положение файлового указателя (например, поиск данных). Если вы не хотите перемещать файловый указатель (потому что он уже находится в нужном месте), то вы можете просто выполнить поиск текущих данных (на которые указывает файловый указатель):
// Предположим, что iofile является объектом класса fstream
iofile.seekg(iofile.tellg(), ios::beg); // перемещаемся к текущей позиции файлового указателя
1 |
// Предположим, что iofile является объектом класса fstream iofile.seekg(iofile.tellg(),ios::beg);// перемещаемся к текущей позиции файлового указателя |
Теперь давайте напишем программу, которая откроет файл, прочитает его содержимое и заменит все найденные гласные буквы на символ :
#include <iostream>
#include <fstream>
#include <cstdlib> // для использования функции exit()
int main()
{
using namespace std;
// Мы должны указать как in, так и out, поскольку используем fstream
fstream iofile(«SomeText.txt», ios::in | ios::out);
// Если мы не можем открыть iofile,
if (!iofile)
{
// то выводим сообщение об ошибке и выполняем функцию exit()
cerr << «Uh oh, SomeText.txt could not be opened!» << endl;
exit(1);
}
char chChar;
// Пока есть данные для обработки
while (iofile.get(chChar))
{
switch (chChar)
{
// Если мы нашли гласную букву,
case ‘a’:
case ‘e’:
case ‘i’:
case ‘o’:
case ‘u’:
case ‘A’:
case ‘E’:
case ‘I’:
case ‘O’:
case ‘U’:
// то перемещаемся на один символ назад относительно текущего местоположения файлового указателя
iofile.seekg(-1, ios::cur);
// Поскольку мы выполнили операцию поиска, то теперь можем переключиться на запись данных в файл.
// Заменим найденную гласную букву символом #
iofile << ‘#’;
// Теперь нам нужно вернуться назад в режим чтения файла.
// Выполняем функцию seekg() к текущей позиции
iofile.seekg(iofile.tellg(), ios::beg);
break;
}
}
return 0;
}
1 |
#include <iostream> intmain() { usingnamespacestd; // Мы должны указать как in, так и out, поскольку используем fstream fstream iofile(«SomeText.txt»,ios::in|ios::out); // Если мы не можем открыть iofile, if(!iofile) { // то выводим сообщение об ошибке и выполняем функцию exit() cerr<<«Uh oh, SomeText.txt could not be opened!»<<endl; exit(1); } charchChar; // Пока есть данные для обработки while(iofile.get(chChar)) { switch(chChar) { // Если мы нашли гласную букву, case’a’ case’e’ case’i’ case’o’ case’u’ case’A’ case’E’ case’I’ case’O’ case’U’ // то перемещаемся на один символ назад относительно текущего местоположения файлового указателя iofile.seekg(-1,ios::cur); // Поскольку мы выполнили операцию поиска, то теперь можем переключиться на запись данных в файл. // Заменим найденную гласную букву символом # iofile<<‘#’; // Теперь нам нужно вернуться назад в режим чтения файла. // Выполняем функцию seekg() к текущей позиции iofile.seekg(iofile.tellg(),ios::beg); break; } } return; } |
Результат выполнения программы (содержимое файла SomeText.txt):
Другие полезные методы классов файлового ввода/вывода в языке C++:
remove() — удаляет файл;
is_open() — возвращает , если поток в данный момент открыт, и — если закрыт.
ИСПОЛЬЗОВАНИЕ cout ДЛЯ ВЫВОДА ЧИСЕЛ
До сих пор созданные вами
программы использовали сом/ для вывода
символьных строк
(букв и чисел,
взятых в кавычки). Теперь вы узнаете, что сом/ можно также использовать для
вывода чисел. Следующая программа 1001.СРР выводит число 1001 на ваш экран:
Откомпилируйте и запустите эту программу.
На вашем экране будет отображено число 1001, как показано ниже:
Далее отредактируйте
программу и измените оператор
cout
, чтобы вывести число 2002, как показано
ниже:
Кроме отображения
целых
чисел
(чисел без десятичной точки), сом/также позволяет вашим программам
отображать
числа с плавающей точкой,
например 1.2345. Следующая программа
FLOATING.CPP использует сом/для вывода числа 0.12345 на экран:
Как и ранее, откомпилируйте
и запустите эту программу. На вашем экране появится следующий вывод:
Что?! Разве operator> не используются для ввода и вывода?
Так и есть.
Сегодняшние программы обычно не очень часто используют операторы побитового сдвига влево и вправо для сдвига битов. Скорее, у вас больше шансов увидеть оператор побитового сдвига влево, используемый с для вывода текста. Рассмотрим следующую программу:
Эта программа напечатает:
Как в приведенной выше программе знает, что в одном случае нужно сдвигать биты и выводить в другом случае? Ответ заключается в том, что перегружает (предоставляет альтернативное определение) , который выполняет вывод в консоль, а не сдвигает биты.
Когда компилятор видит, что левый операнд – это , он знает, что он должен вызвать версию , которая перегружена для вывода. Если левый операнд является целочисленным типом, то знает, что он должен выполнять обычный сдвиг битов.
То же самое касается оператора .
Обратите внимание, что если вы используете как для вывода, так и для сдвига влево, необходимо использовать скобки:
Эта программа печатает:
Первая строка печатает значение (0110), а затем литерал 1. Вторая строка печатает значение , сдвинутое влево на 1 бит (1100).
Мы поговорим больше о перегрузке операторов в следующем разделе, включая обсуждение того, как перегружать операторы для ваших собственных целей.
Вывод действительных чисел
Есть два способа вывода действительных чисел — с фиксированной точкой (соответствует форматной строке «%f» функции printf) и с плавающий точкой (соответствует «%e»). Для переключения режима вывода действительных чисел в формат с фиксированной точкой используется манипулятор fixed, для вывода с плавающей точкой — манипулятор scientific.
По умолчанию числа выводятся с точностью в 6 знаков после точки, это значение можно изменить при помощи манипулятора setprecision с параметром — шириной поля вывода.
Например:
cout << scientific << setprecision(15) << x << endl;
Данные манипуляторы после включения действуют постоянно, до следующего задания значения, то есть их не нужно задавать перед выводом каждой переменной.
По умолчанию (если не задать явно манипулятор fixed или scientific) число может выводиться или с плавающей точкой, или с фиксированной, в зависимости от величины числа. Если был установлен один из манипуляторов fixed или scientific, то вернуть «автоматический» выбор формы представления числа можно при помощи манипулятора
cout << resetiosflags(ios_base::floatfield);