Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <string>
- #include <fstream>
- #include <ostream>
- #include <iostream>
- #include <iomanip>
- #include <sstream>
- #include <vector>
- using namespace std;
- // перегрузка операторов ввода-вывода
- /* работу со структурами и классами можно сделать более удобной и более похожей на работу со стандартными типами;
- когда мы считываем целое число из консоли, или выводим его туда, мы делаем это очень удобно с помощью
- операторов ввода и вывода; так что же нам мешает для наших кастомных структур данных определить точно также
- операторы ввода и вывода */
- // но обо всем по порядку; определим структуру
- struct Duration {
- int hour;
- int min;
- };
- // логично предположить, что когда-нибудь мы будем считывать эту структуру из потока и выводить в поток
- Duration ReadDuration(istream& stream) { // функция примет на вход поток, из которого мы ее читаем
- int h = 0;
- int m = 0;
- stream >> h;
- stream.ignore(1); // пропустим разделитель (формат ввода h:m)
- stream >> m;
- return Duration {h, m};
- }
- // логично определить функцию, которая будет выводить нашу структуру-интервал в поток,
- // в который мы хотим ее вывести; а также экземпляр класса, который мы хотим вывести
- void PrintDuration(ostream& stream, const Duration& duration) {
- stream << setfill('0'); // чтобы единицы от 0 до 9 выводились с заполнителем 0
- const auto& [h, m] = duration;
- stream << setw(2) << h << " :: " << setw(2) << m; // endl не пишем, т.к. имхо за перенос строки должен отвечать тот код, который вызывает PrintDuration
- }
- /* void operator<<(ostream& stream, Duration duration) {
- stream << setfill('0');
- stream << setw(2) << duration.hour << " ::: " << setw(2) << duration.min;
- } */
- ostream& operator<<(ostream& stream, Duration& duration) {
- stream << setfill('0');
- stream << setw(2) << duration.hour << " ::: " << setw(2) << duration.min;
- return stream;
- }
- istream& operator>>(istream& stream, Duration& duration) {
- stream >> duration.hour;
- stream.ignore(1);
- stream >> duration.min;
- return stream;
- }
- int main() {
- /* stringstream dur("01:50"); // заведем поток, чтобы каждый раз не считывать из консоли
- Duration duration1 = ReadDuration(dur);
- ofstream output_file("output.txt");
- PrintDuration(cout, duration1); // 01 :: 50
- PrintDuration(output_file, duration1); // в файле output.txt первая строка это 01 :: 50 */
- /* но согласитесь, что каждый раз вызывать функцию PrintDuration и ReadDuration в принипе можно, но было бы
- намного удобнее, если бы мы могли воспользоваться оператором ввода >> из любого потока (например, из cin) и
- оператором вывода << нашего объекта в любой поток (например, в cout); что для этого нужно сделать?
- для этого в языке С++ уже все есть; попробуем определить наш оператор, пусть он возвращает void, после чего идет
- ключевое слово operator и дальше мы должны написать оператор вывода в поток <<; далее идут аргументы в скобочках
- первый аргумент это поток, в который мы будем делать запись, второй аргумент структура, которую нужно вывести
- получилась функция:
- void operator<<(ostream& stream, Duration duration) {
- stream << setfill('0');
- stream << setw(2) << duration.hour << " ::: " << setw(2) << duration.min << endl;
- }
- попробуем вывести структуру в поток cout */
- /* stringstream dur("01:50"); // заведем поток, чтобы каждый раз не считывать из консоли
- Duration duration1 = ReadDuration(dur);
- cout << duration1; // 01 ::: 50 */
- /* здорово, структура распечаталась, и мы сделали оператор вывода более удобным, и теперь мы смело можем удалить
- функцию PrintDuration; однако если добавить перенос строки */
- /* cout << duration1 << endl; */
- /* получается ошибка, мы не можем записать endl в поток; попробуем вывести тривиальное что-то */
- /* cout << "hello" << " world" << endl; // hello world */
- /* тривиальное вывелось; представим этот код по-другому, при помощи глобального оператора вывода */
- /* operator<<(cout, "hello"); // первым аргументом он принимает поток, а вторым набор символов, которые надо вывести */
- /* после запуска кода у нас есть вывод: hello */
- /* при этом оператор вывода возвращает сам тот поток, в который он делал вывод; то есть результатом работы
- operator<<(cout, "hello") будет поток cout; поэтому мы можем еще раз по цепочке вызвать оператор вывода,
- передав результат работы первого оператора (результат работы -- поток) во второй оператор */
- /* operator<<(operator<<(cout, "hello"), " world"); // hello world */
- /* теперь мы понимаем, что на самом деле оператор вывода должен возвращать не void, а ссылку на поток!!!
- получилась функция:
- ostream& operator<<(ostream& stream, Duration duration) {
- stream << setfill('0');
- stream << setw(2) << duration.hour << " ::: " << setw(2) << duration.min << endl;
- return stream;
- } */
- /* stringstream dur("01:50"); // заведем поток, чтобы каждый раз не считывать из консоли
- Duration duration1 = ReadDuration(dur);
- cout << duration1 << endl; // 01 ::: 50\n
- cout << duration1 << endl; // 01 ::: 50\n */
- /* теперь мы можем определить оператор ввода из потока */
- Duration duration2 = {0, 0}; // инициализируем нуевой интервал
- stringstream dur("01:50"); // заведем строковый поток
- dur >> duration2; // делаем считывание из потока в инициализированную переменную при помощи оператора ввода
- cout << duration2 << endl; // выводим в поток вывода считанный интервал
- cin >> duration2;
- cout << duration2 << endl;
- // таким образом рассмотрена перегрузка операторов ввода-вывода для наших собственных объектов
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement