本文介绍了在读取文件时查找文件结尾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  c>   EOF ,无论这个
导致输入失败还是失败!因此,如果你读取一个 int ,并且
流包含123或换行符,将设置
eofbit (因为流必须提前读取,知道
int ends);如果流包含123 \\\
,则不会设置 eofbit 。
但是,在这两种情况下,输入成功, failbit 将不会被
设置。



要读取这些位,有以下函数(作为代码,因为I
不知道如何获取表格否则):

  eof():返回eofbit 
bad():返回badbit
fail():返回failbit || badbit
good():returns!failbit&& !badbit&& !eofbit

operator!():返回fail()
operator void *():返回fail()? NULL:this
(通常---所有保证的是!fail()返回非null。)


b $ b

给定:第一个检查必须总是 fail()或
运算符之一(基于 fail )。一旦 fail()返回true,我们
可以使用其他函数来确定原因:

  if(fin.bad()){
//严重的问题,磁盘读取错误等。
} else if(fin.eof()){
//文件结尾:没有数据要读。
} else {
//格式化错误:类似abc的int
}

实际上,任何其他使用都是错误的(和任何使用 good()
是一个错误—我为什么该功能存在)。


void graph::fillTable()
{
  ifstream fin;
  char X;
  int slot=0;

  fin.open("data.txt");

  while(fin.good()){

  fin>>Gtable[slot].Name;
  fin>>Gtable[slot].Out;
  cout<<Gtable[slot].Name<<endl;
  for(int i=0; i<=Gtable[slot].Out-1;i++)
    {
      **//cant get here**
    fin>>X;
    cout<<X<<endl;
    Gtable[slot].AdjacentOnes.addFront(X);
    }
  slot++;
  }
 fin.close();
}

That's my code, basically it does exactly what I want it to but it keeps reading when the file is not good anymore. It'll input and output all the things I'm looking for, and then when the file is at an end, fin.good() apparently isn't returning false. Here is the text file.

A 2 B F

B 2 C G

C 1 H

H 2 G I

I 3 A G E

F 2 I E

and here is the output

A
B
F
B
C
G
C
H
H
G
I
I
A
G
E
F
I
E

Segmentation fault

-

Here's is Gtable's type.

struct Gvertex:public slist
  {
    char Name;
    int VisitNum;
    int Out;
    slist AdjacentOnes;
    //linked list from slist
  };

I'm expecting it to stop after outputting 'E' which is the last char in the file. The program never gets into the for loop again after reading the last char. I can't figure out why the while isn't breaking.

解决方案

Your condition in the while loop is wrong. ios::eof() isn'tpredictive; it will only be set once the stream has attempted(internally) to read beyond end of file. You have to check after each
input.

The classical way of handling your case would be to define a >>function for GTable, along the lines of:

std::istream&
operator>>( std::istream& source, GTable& dest )
{
    std::string line;
    while ( std::getline( source, line ) && line.empty() ) {
    }
    if ( source ) {
        std::istringstream tmp( line );
        std::string name;
        int count;
        if ( !(tmp >> name >> count) ) {
            source.setstate( std::ios::failbit );
        } else {
            std::vector< char > adjactentOnes;
            char ch;
            while ( tmp >> ch ) {
                adjactentOnes.push_back( ch );
            }
            if ( !tmp.eof() || adjactentOnes.size() != count ) {
                source.setstate( std::ios::failbit );
            } else {
                dest.Name = name;
                dest.Out = count;
                for ( int i = 0; i < count; ++ i ) {
                    dest.AdjacentOnes.addFront( adjactentOnes[ i ] );
                }
            }
        }
    }
    return source;
}

(This was written rather hastily. In real code, I'd almost certainlyfactor the inner loop out into a separate function.)

Note that:

  • We read line by line, in order to verify the format (and to allowresynchronization in case of error).

  • We set failbit in the source stream in case of an input error.

  • We skip empty lines (since your input apparently contains them).

  • We do not modify the target element until we are sure that the inputis correct.

One we have this, it is easy to loop over all of the elements:

int slot = 0;
while ( slot < GTable.size() && fin >> GTable[ slot ] ) {
    ++ slot;
}
if ( slot != GTable.size )
    //  ... error ...

EDIT:

I'll point this out explicitly, because the other people responding seemto have missed it: it is absolutely imperative to ensure that you havethe place to read into before attempting the read.

EDIT 2:

Given the number of wrong answers this question is receiving, I wouldlike to stress:

  • Any use of fin.eof() before the input is known to fail is wrong.

  • Any use of fin.good(), period, is wrong.

  • Any use of one of the values read before having tested that the inputhas succeeded is wrong. (This doesn't prevent things like fin >> a >>b, as long as neither a or b are used before the success istested.)

  • Any attempt to read into Gtable[slot] without ensuring that slotis in bounds is wrong.

With regards to eof() and good():

The base class of istream and ostream defines three“error” bits: failbit, badbit and eofbit. It'simportant to understand when these are set: badbit is set in case of anon-recoverable hardward error (practically never, in fact, since mostimplementations can't or don't detect such errors); and failbit is set inany other case the input fails—either no data available (end offile), or a format error ("abc" when inputting an int, etc.).eofbit is set anytime the streambuf returns EOF, whether thiscauses the input to fail or not! Thus, if you read an int, and thestream contains "123", without trailing white space or newline,eofbit will be set (since the stream must read ahead to know where theint ends); if the stream contains "123\n", eofbit will not be set.In both cases, however, the input succeeds, and failbit will not beset.

To read these bits, there are the following functions (as code, since Idon't know how to get a table otherwise):

eof():   returns eofbit
bad():   returns badbit
fail():  returns failbit || badbit
good():  returns !failbit && !badbit && !eofbit

operator!():      returns fail()
operator void*(): returns fail() ? NULL : this
    (typically---all that's guaranteed is that !fail() returns non-null.)

Given this: the first check must always be fail() or one of theoperator (which are based on fail). Once fail() returns true, wecan use the other functions to determine why:

if ( fin.bad() ) {
    //  Serious problem, disk read error or such.
} else if ( fin.eof() ) {
    //  End of file: there was no data there to read.
} else {
    //  Formatting error: something like "abc" for an int
}

Practically speaking, any other use is an error (and any use of good()is an error—don't ask me why the function is there).

这篇关于在读取文件时查找文件结尾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

查看更多