В игре есть несколько тонкостей, которые вам необходимо понять, чтобы понять, что происходит в функциях read
и print
. С точки зрения обзора istream
и ostream
являются общими классами ввода и вывода, которые обеспечивают основу для потокового ввода-вывода в C ++. Как правильно указывают другие ответы и комментарии, std::cin
и std::cout
получены из istream
и ostream
для обеспечения ввода / вывода из стандартного потока stdin
и stdout
.
Сами потоки имеют состояние, которое определяет, является ли поток хорошим и может ли считываться или записываться, или произошла ошибка потока, препятствующая дальнейшему вводу / выводу (некоторые сбои исправимы, некоторые нет). См. std :: basic_ ios :: rdstate и std :: basic_ ios :: setstate для обсуждения битов (goodbit, badbit, failbit, eofbit
), составляющих состояние потока.
Теперь посмотрим на прототипы вашей функции:
istream &read(istream &is, Sales_data &item)
и
ostream &print(ostream &os, const Sales_data &item)
Обратите внимание, как первый параметр является ссылкой на текущий поток? И обратите внимание, что возвращение также является ссылкой на тот же поток? Это важно, потому что он передает ссылку на поток, поэтому любые изменения в Steam State , происходящие внутри функции, будут доступны по возвращении. Поэтому, если в функции read
встречается eof
, это изменение состояния будет доступно по возвращении. То же самое для вашей функции print
(хотя потенциальные ошибки, которые могли бы изменить поток, бывают меньше и отличаются)
В пределах read
вы читаете 3 потока информации из потока, item.bookNo, item.units_sold
и price
и обновление item.revenue
:
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
Вы можете прочитать из std::cin
, передав его в качестве аргумента для is
, или вы можете передать открытый файл-поток. Потоковые операции будут работать для любого допустимого потока.
Функция печати делает противоположное, она выводит возврат item.isbn(), item.units_sold, item.revenue
и возврат от item.avg_price()
в качестве вывода. Если вы передадите std::cout
как os
Последняя команда в обеих функциях возвращает поток, включая любые изменения в состоянии потока , чтобы вызывающий мог проверить, является ли read
или print
прошло успешно. Это ключ к тому, чтобы вызывающий мог определить, был ли выполнен ввод-вывод.
Слишком упрощенный пример
Слишком упрощенный пример, выполняющий функцию, может помочь концепциям здесь мы объявляем упрощенную структуру Sales_data
с int bookno, units_sold;
и double price, revenue;
Например:
#include <iostream>
struct Sales_data
{
int bookno, units_sold;
double price, revenue;
};
Затем мы упрощаем read
для чтения только bookno, units_sold
и price
и вычислите revenue
для этого единственного элемента, например,
std::istream &read(std::istream &is, Sales_data &item)
{
is >> item.bookno >> item.units_sold >> item.price;
item.revenue = item.price * item.units_sold;
return is;
}
и упростите print
, чтобы вывести только units_sold
и revenue
:
std::ostream &print(std::ostream &os, const Sales_data &item)
{
os << "units sold: " << item.units_sold << " revenue: $" << item.revenue << '\n';
return os;
}
Теперь вы можете видеть очень просто, предлагая пользователю ввести bookno, units_sold
и price
, как работают функции read
и print
, а также как ошибка, возникающая в одной из функций, изменяет состояние потока . Короткое значение main()
может быть:
int main (void) {
Sales_data sd;
std::cout << "enter bookno units_sold price: ";
if (read (std::cin, sd)) /* if read succeeds */
print (std::cout, sd); /* print data */
else
std::cerr << "error: invalid input\n";
}
Пример использования / вывода
$ ./bin/readprintstream
enter bookno units_sold price: 12 100 12.95
units sold: 100 revenue: $1295
или в случае ошибки:
$ ./bin/readprintstream
enter bookno units_sold price: 23 banannas 12.28
error: invalid input
Надеемся, что обсуждение и пример помогут немного прояснить концепцию. Если у вас есть дополнительные вопросы, дайте мне знать.