Давайте посмотрим: код, который вы опубликовали, работает нормально, и вы хотите, чтобы мы сказали вам, что не так с кодом, который вы не опубликовали.Это довольно сложно.
Тем не менее, код, который вы разместили, вероятно, не будет работать правильно.std::istream::eof
может надежно использоваться только после сбоя входа (или какой-либо другой операции);в опубликованном вами коде он почти наверняка будет ложным, независимо от того.
Кроме того: нет необходимости динамически выделять ifstream
;фактически практически нет случаев, когда динамическое распределение ifstream
является подходящим.И вы не проверяете, что открытия были успешными.
Если вы хотите прочитать два файла, один за другим, самый простой способ - использовать два цикла, один за другим (вызывая общую функцию дляобработка данных).Если по какой-то причине это не подходит, я бы использовал пользовательский streambuf, который принимает список имен файлов в конструкторе и переходит к следующему, когда достигает одного конца файла, возвращая EOF
только когда он достигконец всех файлов.(Единственное осложнение в этом состоит в том, что делать в случае сбоя одного из open
. Я делаю это достаточно часто, чтобы он был частью моего набора инструментов, и использую функцию обратного вызова для обработки сбоя.Вы можете просто жестко написать код в любом удобном для вас месте.)
В качестве быстрого примера:
// We define our own streambuf, deriving from std::streambuf
// (All istream and ostream delegate to a streambuf for the
// actual data transfer; we'll use an instance of this to
// initialize the istream we're going to read from.)
class MultiFileInputStreambuf : public std::streambuf
{
// The list of files we will process
std::vector<std::string> m_filenames;
// And our current position in the list (actually
// one past the current position, since we increment
// it when we open the file).
std::vector<std::string>::const_iterator m_current;
// Rather than create a new filebuf for each file, we'll
// reuse this one, closing any previously open file, and
// opening a new file, as needed.
std::filebuf m_streambuf;
protected:
// This is part of the protocol for streambuf. The base
// class will call this function anytime it needs to
// get a character, and there aren't any in the buffer.
// This function can set up a buffer, if it wants, but
// in this case, the buffering is handled by the filebuf,
// so it's likely not worth the bother. (But this depends
// on the cost of virtual functions---without a buffer,
// each character read will require a virtual function call
// to get here.
//
// The protocol is to return the next character, or EOF if
// there isn't one.
virtual int underflow()
{
// Get one character from the current streambuf.
int result = m_streambuf.sgetc();
// As long as 1) the current streambuf is at end of file,
// and 2) there are more files to read, open the next file
// and try to get a character from it.
while ( result == EOF && m_current != m_filenames.eof() ) {
m_streambuf.close();
m_streambuf.open( m_current->c_str(), std::ios::in );
if ( !m_streambuf.is_open() )
// Error handling here...
++ m_current;
result = m_streambuf.sgetc();
}
// We've either gotten a character from the (now) current
// streambuf, or there are no more files, and we'll return
// the EOF from our last attempt at reading.
return result;
}
public:
// Use a template and two iterators to initialize the list
// of files from any STL sequence whose elements can be
// implicitly converted to std::string.
template<typename ForwardIterator>
MultiFileInputStreambuf(ForwardIterator begin, ForwardIterator end)
: m_filenames(begin, end)
, m_current(m_filenames.begin())
{
}
};