0

更新:以下の問題を回避するために、私はやった

if (ftell(m_pFile) != m_strLine.size())
    fseek(m_pFile, m_strLine.size(), SEEK_SET);
fpos_t position;
fgetpos(m_pFile, &position);

これにより、ファイルの正しい位置が返されます。ただし、なぜこれが発生しているのかを理解したいですか?


テキストファイルで位置を取得したい。ほとんどのファイルでは、最初の行を読み取り、位置を保存し、他のことを行い、その後位置に戻ります...

m_pFile = Utils::OpenFile(m_strBaseDir + "\\" + Source + "\\" + m_strFile, "r");
m_strLine = Utils::ReadLine(m_pFile);
bEOF = feof(m_pFile) != 0;
if (bEOF)
{
    Utils::CompilerError(m_ErrorCallback, 
        (boost::format("File '%1%' is empty.") % m_strFile).str());
    return false;
}

// Open.
pFileCode = Utils::OpenFile(strGenCode + "\\" + m_strFile, options.c_str());
m_strLine = Utils::Trim(m_strLine);
Utils::WriteLine(pFileCode, m_strLine);

// Store location and start passes.
unsigned int nLineCount = 1;
fpos_t position;
fgetpos(m_pFile, &position);
m_strLine = Utils::ReadLine(m_pFile);
...
fsetpos(m_pFile, &position);
m_strLine = Utils::ReadLine(m_pFile);

提供されたすべてのファイルで、fgetposとのストレージはfsetpos正しく機能します。問題は、私が作成した次のようなファイルにあります

例えば

これは、提供されたファイルとほぼ同じです。問題は、上記のファイルfgetpos(m_pFile, &position);が正しいものを返さないことです (実装固有positionであることは承知しています)。fpos_t position最初の後に 58ReadLineを取得します( 60 から編集) ので、2 行目を読み取ろうとするとposition

fsetpos(m_pFile, &position);
m_strLine = Utils::ReadLine(m_pFile);

私は得る

700で

それ以外の

選択: 関数 ADJEXCL

fgetpos最初の行の終わりの位置を返さないのはなぜですか?


_ノート。Utils.ReadLineメソッドは次のとおりです。

std::string Utils::ReadLine(FILE* file)
{
   if (file == NULL)
      return NULL;
   char buffer[MAX_READLINE];
   if (fgets(buffer, MAX_READLINE, file) != NULL)
   {
      if (buffer != NULL)
      {
         std::string str(buffer);
         Utils::TrimNewLineChar(str);
         return str;
      }
   }
   std::string str(buffer);
   str.clear();
   return str;
}

void Utils::TrimNewLineChar(std::string& s)
{
   if (!s.empty() && s[s.length() - 1] == '\n') 
      s.erase(s.length() - 1);
}

編集。コメントのデバッグの提案に従って、次のコードを追加しました

m_pFile = Utils::OpenFile(m_strBaseDir + "\\" + Source + "\\" + m_strFile, "r");
m_strLine = Utils::ReadLine(m_pFile); 
// Here m-strLine = "          Logic Definition Report Chart Version: New Version 700" (64 chars).
long vv = ftell(m_pFile); // Here vv = 58!?

fpos_t pos;
vv = ftell(m_pFile);
fgetpos(m_pFile, &pos); // pos = 58.
fsetpos(m_pFile, &pos);
m_strLine = Utils::ReadLine(m_pFile);
4

1 に答える 1

1

申し訳ありませんが、あなたの Utils 関数は明らかに無能な人によって書かれています。いくつかの問題は、単にスタイルの問題です。トリミングの場合:

void Utils::TrimNewLineChar(std::string& s)
{
   if (!s.empty() && *s.rbegin() == '\n') 
      s.resize(s.size() - 1); // resize, not erase
}

またはC++ 11で

void Utils::TrimNewLineChar(std::string& s)
{
   if (!s.empty() && s.back() == '\n') 
      s.pop_back();
}

ReadLineさらに悪い場合は、次のように置き換えます。

std::string Utils::ReadLine(FILE* file)
{
   std::string str;
   char buffer[MAX_READLINE];
   if (file != NULL && fgets(buffer, MAX_READLINE, file) != NULL)
   {
      // it is guaranteed that buffer != NULL, since it is an automatic array
      str.assign(buffer);
      Utils::TrimNewLineChar(str);
   }
   // copying buffer into str is useless here
   return str;
}

原作のラストstr(buffer)が特に気になります。改行に達した場合fgets、バッファがいっぱいになった場合、またはファイルの終わりに達した場合、バッファ内で適切に終了した文字列を取得することが保証されます。他の I/O エラーが発生した場合は? 知るか?未定義の動作である可能性があります。

bufferwhen fgetsfailsの値に依存しないことをお勧めします。

于 2014-07-02T14:26:55.103 に答える