C++ 使用Istream参数读取的Istream函数

C++ 使用Istream参数读取的Istream函数,c++,function,class,ostream,istream,C++,Function,Class,Ostream,Istream,我正在努力理解这个代码 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 &

我正在努力理解这个代码

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&read(istream&is、销售数据和项目)
{
双倍价格=0;
是>>item.bookNo>>item.units\u销售>>价格;
item.revenue=价格*item.units\u售出;
回报是;
} 
ostream&print(ostream&os、const Sales_数据和项目)
{

os
std::cin
std::cout
std::istream
std::ostream
的特定实例。因此,您可以调用这些函数并将
std::cin
std::cout
作为您想要使用的流传递。这使得函数更具通用性,因为我们可以使用streams不仅仅用于命令行输入和输出


特别是,
std::ifstream
std::ofstream
用于文件I/O,以及
std::istringstream
std::ostringstream
用于字符串I/O。

要理解
读取
打印
函数中发生的事情,需要了解的微妙之处不止一点。从代码的观点来看,代码> > ISReAM/ OFSUCT/COD>是一般的输入和输出类,它为C++中的流I/O提供了基础,其他的答案和注释正确地表示,<代码> STD::CIN < /C>和 STD::CUT是源于<代码> ISTRAM<<代码>和 oSoS,以提供输入/输出FRO。m标准流
stdin
stdout

流本身具有一个状态,该状态确定流是否良好,是否可以读取或写入,或者是否发生了阻止进一步I/O的流错误(有些故障是可恢复的,有些是不可恢复的),有关构成流状态的位(
goodbit,badbit,failbit,eofbit
)的讨论,请参阅和

现在看看你的函数原型:

istream &read(istream &is, Sales_data &item)

注意第一个参数是如何引用当前流的?注意返回也是如何引用同一流的?这很重要,因为它传递了对流的引用,因此函数中发生的蒸汽状态的任何更改都将在返回时可用。因此如果在
r中遇到
eof
ead
函数,状态更改将在返回时可用。您的
打印
函数也是如此(尽管更改流的潜在错误更少且不同)

read
中,您正在从流中读取3条信息,
item.bookNo,item.units\u saled
price
,并更新
item.revenue

is >> item.bookNo >> item.units_sold >> price; 
item.revenue = price * item.units_sold;
您可以通过将其作为
的参数is
传递来读取
std::cin
,也可以传递打开的文件流。流操作将适用于任何有效流

打印函数的作用正好相反,它将
item.isbn()、item.units\u saled、item.revenue的返回作为输出输出,并将
item.avg\u price()的返回作为输出。如果您将
std::cout
作为
os

两个函数中的最后一个命令返回流,包括流状态的任何更改,以便调用方可以检查
读取
打印
是否成功。这是调用方能够确定是否发生I/O的关键

过于简化的示例

一个过度简化的示例可以帮助理解这些概念。这里我们声明一个简化的结构
Sales\u data
,其中包含
int bookno,units\u selled;
double price,revenue;
,例如:

#include <iostream>

struct Sales_data
{
    int bookno, units_sold;
    double price, revenue;
};
并简化
打印
,仅输出售出的
单位
收入

std::ostream &print(std::ostream &os, const Sales_data &item)
{
    os << "units sold: " << item.units_sold << " revenue: $"  << item.revenue << '\n';

    return os; 
}
示例使用/输出

$ ./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

希望讨论和示例有助于理清概念。如果您有进一步的问题,请告诉我。

“我们可以使用流进行不仅仅是命令行输入和输出”,特别是,
std:[i | o]fstream
用于文件i/o和
std:[i | o]stringstream
用于字符串I/O。很好的澄清。我偷了它并将其添加到我的答案中:)欢迎使用堆栈溢出!您可以使用此示例了解我们网站的概述。此示例非常有用!!!现在我更清楚了。谢谢!因此基本上,参数istream&is是cin的参考。(cin和is是istream的实例)正是。您正在传递希望从中读取的任何流。在上面的例子中,它是
std::cin
,也可以是一个打开的文件流。您通常会看到,这是通过重载的
运算符完成的,而不是编写
读取
打印
函数,但是ei也可以。有关重载的最新示例,请参见。
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