В предишния урок разгледахме концепцията за потоците. Сега ще разгледаме различни форматиращи функции прилагащи контрол във всички видове потоци.
Какво е манипулатор на потока?
Когато започнем да работим по – сериозно с вход и изход в C++, рано или късно стигаме до момент, в който стандартния cout не е достатъчен. В C++ работим с операторите „>>“ или „<< „. Това не е нещо сложно. Това са функции. Първата чете, а втората пише фундаментни типове данни в потока.
Манипулаторът е специална функция в C++, която се използва с входно / изходни потоци (като cin, cout), за да промени начина, по който данните се показват или четат. Можем да използваме манипулатори, когато искаме:
- форматиране на числа;
- задаване на точност (десетични знаци);
- подравняване на текст;
- промяна на числовата основа (като десетична в шестнадесетична);
- контролно на разстоянието (извеждане на информация в табличен вид);
Манипулаторите са дефиниране в библиотеката <iomanip>. Taka, че трябва да я добавите във файла където ще използвате манипулаторите.
В изходния си код се очаква да подредите кода си така: че след месеци отсъствие да можете да го прочетете. Отделете операторите. Дайте отстояние на кода който прави действие.
Това е важно не само за вас, а за всеки четящ кода ви. Операторите „<<“ и „>>“ може да объркат всеки.
std::endl
Със сигурност това е най – ползвания манипулатор. Той прави две неща:
- Записва в буфера на потока знака ‘\n’ (символ за нов ред);
- Извиква метода на потока flush();
Това добавя знака за нов ред и незабавно изпразва бувера на потока към където потока е закачен. Това обикновено е текстовия изход в терминала. Но може да е файл, или нещо друго. Работи само с изходни потоци. Може би се досещате, че действието му е еднократно.
std::string a {"First line"};
std::string b {"Second line"};
std::cout << a << std::endl;
std::cout << b << std::endl;std::flush
Само изпразва бувера на потока към дестинацията. Действа еднократно в изходни потоци. В долната програма го показваме. Функцията sleep() кара програмата да заспи за 5 секунди.
#include <iostream>
#include <iomanip>
#include <thread> // sleep()
#include <chrono> // sleep()
void sleep() {
std::this_thread::sleep_for(std::chrono::seconds(5));
}
int main() {
std::string a {"First line"};
std::string b {"Second line"};
std::cout << a << '\n' << b << '\n';
sleep();
std::cout << std::flush;
}Моя компилатор (macOS) не работи както очаквах 🙂 Изпразва бувера при ‘\n’ 🙂
std::dec, std::hex, std::oct
Тези манипулатори променят потока за постоянно. В долния пример cin приема шеснайсетични числа. А cout ги извежда в десетичен вид.
#include <iostream>
int main() {
int x {}, y {}, z {};
std::cout << "Въведете три 16 - тични числа: 0x...." << std::endl;
// std::dec -> std::hex
std::cin >> std::hex;
std::cin >> x >> y >> z;
// по подразбиране изхода е std::dec (десетично)
std::cout << "Десетични стойности:" << std::endl;
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
std::cout << "z = " << z << std::endl;
}Ако въведете:
0xFF
0xff
ffРезултата ще е:
x = 255
y = 255
z = 255std::ends
Това добавя ‘\0’ в буфера. И почти не се използва в днешни времена.
std::showbase и std::noshowbase
Показват или скриват префикса на базата: осмични и шестнайсетични числа.
Показване на базата:
#include <iostream>
#include <iomanip>
int main() {
int const MAX_BYTE {255};
std::cout << "decimal: " << std::showbase << std::dec << MAX_BYTE << std::endl;
std::cout << "octal: " << std::showbase << std::oct << MAX_BYTE << std::endl;
std::cout << "hexdecimal: " << std::showbase << std::hex << MAX_BYTE << std::endl;
}Изход:
decimal: 255
octal: 0377
hexdecimal: 0xffСкриване на базата (префикса): noshowbase
#include <iostream>
#include <iomanip>
int main() {
int const MAX_BYTE {255};
std::cout << "decimal: " << std::noshowbase << std::dec << MAX_BYTE << std::endl;
std::cout << "octal: " << std::noshowbase << std::oct << MAX_BYTE << std::endl;
std::cout << "hexdecimal: " << std::noshowbase << std::hex << MAX_BYTE << std::endl;
}Изход:
decimal: 255
octal: 377
hexdecimal: ffstd::showpos, std::noshowpos
Тези манипулатори вкючват / изключват знака ‘+’ в изхода. Превода е нещо като „show positive values„.
#include <iostream>
#include <iomanip>
int main() {
int theLifeValue {42};
std::cout << "showpos: " << std::showpos << theLifeValue << std::endl;
std::cout << "noshowpos: " << std::noshowpos << theLifeValue << std::endl;
}std::uppercase
Извежда ASCII буквите като главни при извеждане на числа. Не работи за текст:
#include <iostream>
#include <iomanip>
int main() {
std::cout << std::uppercase;
std::cout << std::hex << 255 << '\n';
std::cout << std::hex << 3'600 << '\n';
}Изход:
FF
E10std::scientific
Това е научна нотация представяща числата: float и double.
double x = 1234.5;
std::cout << std::scientific << std::uppercase << x << std::endl;
std::cout << std::scientific << std::nouppercase << x << std::endl;Ред 2: Представя експонентата с главна буква.
Ред 3: Представя експонентата с малка буква.
std::setprecision(n)
Този манипулатор извежда реалните числа с точност до N след десетичната запетая.
#include <iostream>
#include <iomanip>
int main() {
const double PI = 3.14159265358979323846;
std::cout << std::setprecision(7) << PI << std::endl;
}std::setw(n)
Задава ширината на полето в която ще се изведе следващата стойност.
std::setfill
Задава символ за запълване на празното пространство. Пример:
std::cout << std::setfill('*');
std::cout << std::setw(10) << 42;Изход:
********42std::boolalpha
Извежда true, когато булев операция върне 1. Или false, когато се върне 0.
std::skipws
Пропуска бялото пространство: интервали, табулатори… нов ред…
По подразбиране входните потоци пропускат whitespace.
int x;
std::cin >> x;Ако не трябва да се пропуска:
char c;
std::cin >> std::noskipws >> c;Тук сме посочили основните манипулатор. Пълна информация има на този страница.