Функция Istream для чтения с параметром istream - PullRequest
2 голосов
/ 17 февраля 2020

Я пытаюсь понять этот код

istream &read(istream &is, Sales_data &item) 
{
    double price = 0;    
    is >> item.bookNo >> item.units_sold >> price;   
    item.revenue = price * item.units_sold;    
    return is;
} 

ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " "    
        << item.revenue << " " << item.avg_price();    
    return os; 
}

Я не понимаю, что это за функция, также я не могу понять, почему мы используем istream для чтения и ostream для печати вместо использования cin и cout.

Ответы [ 2 ]

3 голосов
/ 17 февраля 2020

В игре есть несколько тонкостей, которые вам необходимо понять, чтобы понять, что происходит в функциях 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

Надеемся, что обсуждение и пример помогут немного прояснить концепцию. Если у вас есть дополнительные вопросы, дайте мне знать.

3 голосов
/ 17 февраля 2020

std::cin и std::cout являются c экземплярами std::istream и std::ostream. Следовательно, вы можете вызывать эти функции и передавать std::cin или std::cout в качестве потоков, которые вы хотите использовать. Это позволяет функциям быть более универсальными, поскольку мы можем использовать потоки не только для ввода и вывода из командной строки.

В частности, std::ifstream и std::ofstream для файлового ввода-вывода и std::istringstream и std::ostringstream для строкового ввода / вывода.

...