流错误指示器如何影响以下输入代码? [英] How a stream error indicator affects following input code?

查看:16
本文介绍了流错误指示器如何影响以下输入代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每个流都有一个错误指示器,用于记录是否发生了读/写错误".

Each stream has "an error indicator that records whether a read/write error has occurred".

它通常很少由各种函数设置:fgetc(), fflush(), fseek(), ....

It is set, usually rarely, by various functions: fgetc(), fflush(), fseek(), ....

被各种函数清除:rewind(), clearerr(), fopen(), ....

int ferror(FILE *stream) 报告状态.

当且仅当为 stream 设置了错误指示符时,ferror 函数返回非零值.

The ferror function returns nonzero if and only if the error indicator is set for stream.

<小时>

在这种情况下,肯定是发生了输入错误.

if (!ferror(istream)) {
  int ch = fgetc(istream);
  if (ch == EOF && ferror(istream)) {
    puts("Input error just occurred");
  }
}

<小时>

深入探索fgetc()fgetc() 不返回EOF,因为错误指示器被设置, 但因为如果发生读取错误"或文件尾相关原因1.通常,一旦发生错误(例如串行流上的奇偶校验错误),代码不会在不清除错误的情况下继续读取,但要考虑继续读取时会发生什么.


Exploring fgetc() deeper, fgetc() does not return EOF because the error indicator was set, but because "If a read error occurs" or end-of-file related reasons1. Usually once an error occurs (e. g. parity error on a serial stream), code does not continue reading without clearing the error, yet consider what happens when it does continue.

我看到 8 种情况:错误指示器fgetc() 之前设置/清除,fgetc() 返回 EOF 与否,后面的 ferror() 可能为真,也可能为假.

I see 8 situations: the error indicator set/clear prior to fgetc(), fgetc() returns EOF or not, and a following ferror() could be true or not.

int e1 = !!ferror(istream);
int eof = fgetc(istream) == EOF;
int e2 = !!ferror(istream);

假设没有 UB,8 种情况中有 5 种是可能的,而不是 3 种意外的吗?特别是 在设置错误指示器的情况下是否可能进行有效输入? 2

Assuming no UB, are 5 of the 8 possible and not the 3 unexpected ones? especially is valid input possible with error indicator set? 2

e1 eof e2  
0  0   0   Normal reading of valid data    
0  0   1   Unexpected
0  1   0   End-of-file
0  1   1   Input error
1  0   0   Unexpected
1  0   1   Normal reading of valid data with error indicator set!
1  1   0   Unexpected
1  1   1   Input error or end-of-file

<小时>

在输入操作之前设置错误指示器,事情变得复杂,事先清除它可以简化代码.然而,这可以防止错误指示器积累.


With the error indicator set prior to an input operation, things become complicated and clearing it beforehand simplifies code. Yet that prevents error indicator accumulation.

如果代码没有事先清除错误指示器并且想要检测输入的是否有罕见的输入错误,那么测试似乎是有意义的code>!feof() 而不是 ferror() 来检测.

If codes does not clear the error indicator before hand and wants to detect if a line of input had a rare input error, it seems to make sense to test !feof() and not ferror() to detect.

检查 ferror() 是否可能产生误导? 或者我是否遗漏了关于 错误指示器 的某些内容?

Is checking ferror() potentially misleading? or have I missed something about the error indicator?

char buf[80];
for (int i=0; i<(80-1); i++) {
  int ch = fgetc(stdin);
  if (ch == EOF) {
    if (ferror(stdin)) {
      puts("Input error or (Prior input error and end of file occurred)");  // ambiguous
    } 
    if (feof(stdin)) { 
      puts("End of file occurred");
    } else {
      puts("Input error occurred");  // ferror() test not needed
      i = 0; // ignore prior input
    }
    break;
  }
  if (ch == '
') break;
  buf[i++] = ch; 
}
buf[i] = 0; 

<小时>

类似问题


Similar questions

设置错误指示符的文件操作.这个未回答的中心是在没有测试 fgetc() 返回值的情况下积累错误指示器(答案冒险进入 errno 并制作用户错误标志)和这个试图简单地消除 fgetc() 的歧义.

File operations with error indicator set . This unanswered one centers on accumulating error indicator without testing fgetc() return value (answers venture off into errno and making a user error flag) and this one is trying to simply disambiguate a fgetc().

fgetc():仅检查 EOF 就足够了吗? 没有解决错误指示器 设置在 fgetc() 之前.

fgetc(): Is it enough to just check EOF? does not address error indicator set prior to fgetc().

类似的问题适用于输出和 I/O 流,但这个问题侧重于输入流.

Similar issues apply to output and I/O streams, yet this question focuses on input streams.

1 int fgetc(FILE *stream) 返回

如果设置了流的文件尾指示符,或者如果流位于文件尾,则设置流的文件尾指示符并且 fgetc 函数返回EOF.否则, fgetc 函数返回 stream 指向的输入流中的下一个字符.如果发生读取错误,则设置流的错误指示符并且fgetc 函数返回EOF.C11dr §7.21.7.1 2

If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc function returns EOF. Otherwise, the fgetc function returns the next character from the input stream pointed to by stream. If a read error occurs, the error indicator for the stream is set and the fgetc function returns EOF. C11dr §7.21.7.1 2

2 在案例 0-1-0、1-1-1 上.似乎如果 UCHAR_MAX == UINT_MAX,一个 unsigned char,可以返回并等同于 EOF 并且不是由于文件结束,也不是输入错误.

2 On cases 0-1-0, 1-1-1. Seems if UCHAR_MAX == UINT_MAX, a unsigned char, could be returned and equate to EOF and not be due to end-of-file nor input error.

推荐答案

假设没有 UB,8 个中的 5 个是可能的,而不是 3 个意外的吗?尤其是在设置错误指示器的情况下是否可以进行有效输入?

Assuming no UB, are 5 of the 8 possible and not the 3 unexpected ones? especially is valid input possible with error indicator set?

具体说到标准的规定,我倾向于同意你的分析:

Speaking specifically to the provisions of the standard, I'm inclined to agree with your analysis:

  • 很少指定函数来清除流的错误指示符,fgetc() 不是其中之一.更一般地说,它们都不是数据传输功能.因此,如果在将流呈现给 fgetc() 以供读取之前为该流设置了错误指示符,那么在该函数返回时仍应设置它,尽管有所有其他考虑因素.涵盖这些情况:*

  • Few functions are specified to clear the error indicator of a stream, and fgetc() is not one of them. More generally, none of them are data-transfer functions. Therefore, if the error indicator is set for a stream before that stream is presented to fgetc() for reading, then it should still be set when that function returns, all other considerations notwithstanding. That covers these cases:*

1  0   0   Unexpected
1  1   0   Unexpected
1  1   1   Input error or end-of-file

它也涵盖了关于错误指示器的预期值的这种情况,尽管它没有说明它是否真的会发生:

It also covers this case with respect to the expected value of the error indicator, though it does not speak to whether it can actually happen:

1  0   1   Normal reading of valid data with error indicator set!

  • fgetc() 被指定在每一种情况下返回 EOF.因此,如果 fgetc() 返回除 EOF 之外的任何内容,那么它不会在该调用中设置流的错误(或文件结尾)指示符.涵盖这些情况:

  • fgetc() is specified to return EOF in every situation in which it is specified to set the end-of-file indicator on a stream. Therefore, if fgetc() returns anything other than EOF then it will not, on that call, have set the stream's error (or end-of-file) indicator. That covers these cases:

    0  0   0   Normal reading of valid data    
    0  0   1   Unexpected
    

    另一方面,如果 fgetc() does 返回 EOF 那么流的文件结束指示符或其错误指示符之后应该找到设置.但是标准区分了这些情况,并指定用户可以通过 feof()ferror() 函数来区分它们.涵盖这些情况:*

    On the other hand, if fgetc() does return EOF then either the stream's end-of-file indicator or its error indicator should afterward be found set. But the standard distinguishes between these cases, and specifies that the user can distinguish them via the feof() and ferror() functions. That covers these cases:*

    0  1   0   End-of-file
    0  1   1   Input error
    

  • 最后,我同意fgetc() 的任何行为都不以流错误指示器的初始状态为条件.只要流最初未定位在其末尾,并且最初未设置其文件结束指示符,fgetc 函数将从 stream 指向的输入流中返回下一个字符."这表明,最感兴趣的情况实际上是允许的:

  • Finally, I concur that none of the behavior of fgetc() is conditioned on the initial state of the stream's error indicator. Provided only that the stream is not initially positioned at its end, and its end-of-file indicator is not initially set, "the fgetc function returns the next character from the input stream pointed to by stream." That establishes that this, the case of most interest, is in fact allowed:

    1  0   1   Normal reading of valid data with error indicator set!
    

    然而,抽象中允许的情况并不意味着它可以在实践中观察到.细节似乎未指定,我希望它们取决于为相关流提供服务的驱动程序的实现.完全有可能一旦遇到错误,驱动程序将在后续读取时继续报告错误,直到适当地重置,甚至更长的时间.从 C 的角度来看,这将被解释为每次后续读取时发生的(附加)错误,并且语言规范中没有任何内容可以阻止这一点.甚至不使用清除流错误指示器的函数之一.

    However, that the case is allowed in the abstract does not imply that it can be observed in practice. The details seem unspecified, and I would expect them to depend on the implementation of the driver serving the stream in question. It is entirely possible that having once encountered an error, the driver will continue to report an error on subsequent reads until reset appropriately, and perhaps longer. From the C perspective, that would be interpreted as an (additional) error occurring on each subsequent read, and nothing in the language specifications prevents that. Not even use of one of the functions that clear a stream's error indicator.

    如果代码没有事先清除错误指示器并且想要检测一行输入是否有罕见的输入错误,它似乎使检测 !feof() 而不是 ferror() 检测的意义.

    If codes does not clear the error indicator before hand and wants to detect if a line of input had a rare input error, it seems to make sense to test !feof() and not ferror() to detect.

    检查 ferror() 是否可能产生误导? 或者我是否遗漏了关于 错误指示器 的某些内容?

    Is checking ferror() potentially misleading? or have I missed something about the error indicator?

    我同意,如果一个流的错误指示符最初被设置,它的文件结束指示符没有,并且使用 fgetc() 读取它返回 EOF,然后ferror() 不能有效区分文件结束和错误情况,而 feof() 应该.

    I agree that if a stream's error indicator is initially set, its end-of-file indicator is not, and reading it with fgetc() returns EOF, then ferror() does not usefully distinguish between the end-of-file and error cases whereas feof() should.

    另一方面,在遇到错误后是否可以有用地继续读取给定的流取决于实现,也可能取决于特定情况.即使错误指示符通过 clearerr() 调用清除,这也适用,更不用说错误指示符是否清除.

    On the other hand, whether one can usefully continue to read a given stream after an error has been encountered on it depends on implementation and possibly on specific circumstances. That applies even if the error indicator is cleared via a clearerr() call, not to mention if the error indicator is not cleared.

    * 虽然我同意在 UCHAR_MAX > 的情况下,EOF 存在歧义.INT_MAX,我断言这只是为什么这样的实现会有问题的几个原因之一.因此,作为一个实际问题,我认为这些实现完全是假设性的.

    * Although I agree that there is an ambiguity with respect to EOF in the event that UCHAR_MAX > INT_MAX, I assert that that is just one of several reasons why such an implementation would be problematic. As a practical matter, therefore, I disregard such implementations as entirely hypothetical.

    这篇关于流错误指示器如何影响以下输入代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆