从Getline的字符缓冲区中分离EOF



我使用getline从输入文件中获取缓冲区中的字符。在读取一行之后,我循环遍历所有字符并在映射上执行查找(用于一些进一步的操作)。问题是,一旦有效字符结束,我的程序从输入流中获取eof,并尝试在映射中查找它。

我试着检查inputStream.eof()eofbit,看看当我到达流的末尾时,但问题是,一旦我完成最后的getline(),这两者都会被设置,所以我不能用它来确定EOF字符位于输入缓冲区中的位置。

我如何在输入缓冲区中识别EOF字符,并避免在映射中查找它?

while(fileInput) {
fileInput.getline(charBuf,charBufSize);
  for(int i=0; i<=charBufSize ;i++) {
    char* currentChar = &(charBuf[i]);
    // do something with currentChar,
    // which I proceed to do by dereferencing currentChar when I need to access
    // the actual character.
  }
}

c++中没有可以检查的EOF字符。你要做的是得到一个字符的数目,并使用它来知道文件结束的地方。您可以使用istream::gcount()获取此计数。

你的代码中有几个问题。

我假设你已经声明了

char charBuf[256];
size_t charBufSize = 256;
  1. 第一个问题是您丢弃了第一行输入。从文件中逐行读取的惯用用法是:

    while( fileInput.getLine(charBuf, charBufSize) ) {
      for (...) {  // your for loop is wrong, but I'll get to that in a second
      }
    }
    

    如果您真的想在开始循环之前丢弃第一行,请使用

    fileInput.getLine(charBuf, charBufSize); // this first line will be ignored
    while( fileInput.getLine(charBuf, charBufSize) ) {
      for (...) {  // your for loop is wrong, but I'll get to that in a second
      }
    }
    
  2. charBufSize包含可以读取的最大数据量,而不是实际读取的数据量。所以如果你只读入,比如说,12个字符,那么你不仅要在字符13上执行映射查找,还会尝试处理字符14到256。为了避免这种情况,将循环改为:

    for (int i=0; i < fileInput.gcount(); ++i ) {
      char* currentChar = &(charBuf[i]);
      // do something with currentChar,
      // which I proceed to do by dereferencing currentChar when I need to access
      // the actual character.
    }
    
  3. 您正在使用<=而不是<

  4. 整个char* currentChar = &(charBuf[i]);的事情有点不寻常。在代码中,我从你的问题中编辑了出来(这样你问的基本输入问题就会更清楚),似乎你正确地使用了它,但似乎你可以很容易地声明char currentChar = charBuf[i];做了一些小的改变,以避免在你使用它的地方取消引用currentChar

在charBuf中没有"EOF字符"。即使在EOF字符作为一个概念存在的系统上(例如MS-DOS和Windows), istream::getline()也不会将其存储在charBuf.

所发布的代码中一个明显的错误是循环中的越界访问:i<=charBufSize应该是i<charBufSize,但是为了只处理由istream::getline获得的字符,您应该使用fileInput.gcount()来找出实际写入charBuf:

的字符数量。
// assuming char charBuf[charBufSize];
fileInput.getline(charBuf, charBufSize);
for(int i=0; i<fileInput.gcount()-1; i++) // -1 if you don't want to process ''
{

或者直接使用字符串

// assuming std::string charBuf;
getline(fileInput, charBuf);
for(int i=0; i<charBuf.size(); i++)
{

如果您想逐行读取,那么使用标准的getline习惯用法:

std::string line;
while (std::getline(inputFile, line))
{
    // process line
}

如果您想要读取未格式化的("二进制")输入,请使用readgcount:

std::array<char, 4096> buf;
std::streamsize n;
while (true)
{
    inputFile.read(buf.data(), buf.size());
    if ((n = inputFile.gcount()) == 0) { break; }
    // process [buf, buf + n)
}

最新更新