【问题标题】:Istream function to read with istream parameter使用 istream 参数读取的 Istream 函数
【发布时间】:2020-02-17 03:22:32
【问题描述】:

我正在尝试理解这段代码

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 打印而不是使用cincout

【问题讨论】:

  • 欢迎来到 Stack Overflow!您可以通过tour 了解我们网站的概况。

标签: c++ function class ostream istream


【解决方案1】:

std::cinstd::coutstd::istreamstd::ostream 的特定实例。因此,您可以调用这些函数并将std::cinstd::cout 作为您要使用的流传递。这使得函数更通用,因为我们可以将流用于命令行输入和输出之外。

特别是,std::ifstreamstd::ofstream 用于文件 I/O,std::istringstreamstd::ostringstream 用于字符串 I/O。

【讨论】:

  • “我们不仅可以将流用于命令行输入和输出”,尤其是 std::[i|o]fstream 用于文件 I/O,std::[i|o]stringstream 用于字符串 I/O。
  • 很好的说明。我偷了它并将其添加到我的答案中:)
【解决方案2】:

要了解readprint 函数中发生的事情,您需要了解更多的细微之处。从概述的角度来看,istreamostream 是通用输入和输出类,它们为 C++ 中的流 I/O 提供了基础。正如其他答案和 cmets 正确指出的那样,std::cinstd::cout 派生自 istreamostream 以提供来自标准流 stdinstdout 的输入/输出。

流本身有一个状态来确定流是否良好并且可以读取或写入,或者是否发生了流错误以防止进一步的 I/O(有些故障是可恢复的,有些则不能)参见std::basic_ios::rdstatestd::basic_ios::setstate 讨论构成流状态的位 (goodbit, badbit, failbit, eofbit)。

现在查看您的函数原型:

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

ostream &print(ostream &os, const Sales_data &item)

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

read 内,您正在从流中读取3 条信息,item.bookNo, item.units_soldprice 并更新item.revenue

is >> item.bookNo >> item.units_sold >> price; 
item.revenue = price * item.units_sold;

您可以通过将std::cin 作为is 的参数传递来读取std::cin,或者您可以传递打开的文件流。流操作适用于任何有效的流。

print 函数则相反,它输出item.isbn(), item.units_sold, item.revenue 的返回值和item.avg_price() 的返回值作为输出。如果您将std::cout 传递为os

两个函数中的最后一个命令返回流,包括流状态的任何变化,因此调用者可以检查readprint 是否成功。这是调用者能够确定 I/O 是否发生的关键。

过度简化的例子

一个过分简化的例子执行函数可能有助于理解概念。这里我们声明一个简化的结构Sales_dataint bookno, units_sold;double price, revenue; 例如:

#include <iostream>

struct Sales_data
{
    int bookno, units_sold;
    double price, revenue;
};

然后我们将read 简化为仅读取bookno, units_soldprice 并计算该单个项目的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_soldrevenue

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

    return os; 
}

现在您可以通过一种非常简单的方式查看提示用户输入bookno, units_soldpricereadprint 函数是如何工作的,以及其中一个函数如何发生错误更改流状态。简短的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

希望讨论和示例有助于澄清概念。如果您还有其他问题,请告诉我。

【讨论】:

  • 这个例子很有帮助!!!现在事情对我来说更清楚了。谢谢!
  • 所以基本上参数 istream &is 是 cin 的参考。(cin 和 &is 是 istream 的实例)
  • 没错。您正在传递您希望read 从中读取的任何流。在上面的例子中是std::cin,它也可以是一个打开的文件流。您通常会看到这是通过重载 &lt;&lt;&gt;&gt; 运算符而不是编写 readprint 函数来完成的,但两者都可以。有关重载 &lt;&lt;&gt;&gt; 的最新示例,请参阅 Can't load correct information from file
猜你喜欢
  • 2011-02-23
  • 2013-11-09
  • 2014-09-15
  • 2018-05-14
  • 2020-01-14
  • 2017-02-25
  • 2015-07-18
  • 2020-12-24
  • 2016-09-06
相关资源
最近更新 更多