【问题标题】:C++: std::istream check for EOF without reading / consuming tokens / using operator>>C++:std::istream 在不读取/使用令牌/使用运算符的情况下检查 EOF>>
【发布时间】:2011-08-11 20:40:53
【问题描述】:

我想测试一个std::istream 是否已经到达末尾而不读取它。

我知道我可以像这样检查 EOF:

if (is >> something) 

但这有一系列问题。想象一下,有许多(可能是虚拟的)方法/函数期望 std::istream& 作为参数传递。 这意味着我必须做“家务”来检查它们中的 EOF,可能使用不同类型的 something 变量,或者创建一些奇怪的包装器来处理调用输入法的场景。

我需要做的就是:

if (!IsEof(is)) Input(is);

方法IsEof应该保证流不被改变读取,这样上面的行就相当于:

Input(is)

关于Input方法中读取的数据。

如果没有适用于和std::istream 的通用解决方案,有没有办法为std::ifstreamcin 做到这一点?

编辑: 换句话说,下面的assert 应该总是通过:

while (!IsEof(is)) {
  int something;
  assert(is >> something);
}

【问题讨论】:

  • 重新阅读问题,我不确定我第一次理解。你的意思是if (IsEof(is)) Input(is) 还是应该有一个逻辑非?
  • 这应该是不合逻辑的。但重要的是我需要先检查而不消耗任何令牌(请参阅上面的编辑),一切都会对你很清楚。
  • 断言非常强大的后期编辑。它指出 IsEof 只有在格式化提取 int 会成功时才返回 false。你确定这是你的意思吗?如果是这样,您不能使用原始 istream 执行此操作;您将需要某种结构化缓存,以便您可以读取和缓存下一个 int。或者,您需要一种方法来放回在解析 int 时读取的所有字符,而 std::istream 并不能保证这总是可行的。
  • 这个int 只是一个例子,无论下一个令牌是什么,只要达到EOF,我都希望它能够工作。是的,我正在寻找一个函数,它可以告诉我是否到达流中最后一个标记(即 EOF)之后的位置,而不尝试读取下一个标记,或者至少提前读取它并将其放回原处。这可能吗?
  • 只是为了澄清,你所说的“令牌”到底是什么意思?如果您谈论的是任意复杂的类型,那么-大概-下一个“令牌”可能包含任意多个字符,您将不得不尝试对整个对象进行虚假读取。如果此读取失败,您将不得不将已读取的所有内容存储在缓存中(可能是结构化的,也可能不是),因为您通常无法将其全部推回一个简单的istream

标签: c++ filestream iostream eof


【解决方案1】:

istream 类有一个 eof 位,可以使用 is.eof() 成员进行检查。

编辑:所以您想查看下一个字符是否是 EOF 标记而不将其从流中删除? if (is.peek() == EOF) 可能就是你想要的。请参阅istream::peek 的文档

【讨论】:

  • 这不能按预期方式工作,应该先阅读一些内容首先才能使 eof() 工作。考虑以下代码: while (IsEof(is)) { int something;断言(是 >> 某事); }
【解决方案2】:

那是不可能的。 IsEof 函数应该如何知道您打算读取的下一项是 int?

以下是否也应该不触发任何断言?

 while(!IsEof(in))
 {
    int x;
    double y;
    if( rand() % 2 == 0 )
    {
       assert(in >> x);
    } else {
       assert(in >> y);
    }
 }

也就是说,您可以使用exceptions 方法将“管家”保存在一个地方。

代替

   if(IsEof(is)) Input(is)

试试

   is.exceptions( ifstream::eofbit /* | ifstream::failbit etc. if you like */ )
   try {
     Input(is);
   } catch(const ifstream::failure& ) {
   }

它不会阻止你在“为时已晚”之前阅读,但它确实避免了在所有函数中都需要 if(is >> x) if(is >> y) 等。

【讨论】:

    【解决方案3】:

    正常情况

    if (std::is)
    { 
    }
    

    就够了。还有 .good()、.bad()、.fail() 以获得更准确的信息

    这是一个参考链接:http://www.cplusplus.com/reference/iostream/istream/

    【讨论】:

      【解决方案4】:

      没有 isEof 函数有充分的理由:很难以可用的方式指定。例如,operator>> 通常以跳过空格(取决于标志)开始,而其他一些输入函数能够读取空格。您将如何 isEof() 处理这种情况?是否从跳过空格开始?它是否取决于 operator>> 使用的标志?它会恢复流中的空白吗?

      我的建议是使用标准习语并描述输入故障,而不是试图仅预测它们的一个原因:您仍然需要描述和处理其他原因。

      【讨论】:

        【解决方案5】:

        不,在一般情况下,无法知道下一次读取操作是否会到达 eof。

        如果流连接到键盘,EOF 条件是我将在下一个提示符下键入 Ctrl+Z/Ctrl+D。 IsEof(is) 如何检测到这一点?

        【讨论】:

        • @leden - 不,它们具有相同的界面。这只是它以这种方式工作的一个原因。
        猜你喜欢
        • 2010-11-21
        • 1970-01-01
        • 1970-01-01
        • 2017-08-29
        • 1970-01-01
        • 1970-01-01
        • 2012-06-17
        • 2017-09-12
        • 2016-11-23
        相关资源
        最近更新 更多