fgets
сохраняет завершающий символ новой строки, что приводит к имени файла несуществующего файла. Также состояние потока обновляется только после чтения. Если я заменю тело while
на следующий код, у меня это сработает:
cout << filename;
size_t len = strlen(filename);
// chop off trailing newline
if (len > 1 && filename[len - 1] == '\n') filename[len - 1] = 0;
singlefile.open(filename, ifstream::in);
while ( getline(singlefile, progline) )
{
cout << progline << endl;
}
singlefile.close();
Если вы действительно хотите перебирать список файлов, я бы использовал Boost.Filesystem , который имеет приятный интерфейс C ++, работает для всех имен файлов (даже для тех, у которых есть символы новой строки) и независимый от платформы.
Если это на самом деле только пример, а ваша фактическая команда не find
, есть еще место для упрощения. Вот предложение, которое использует Boost.Iostreams , чтобы избавиться от большинства вызовов функций C (было бы здорово иметь чтение источника устройства из стандартного вывода процесса, но Boost.Iostreams этого не хватает):
#include <cstdio>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>
#include <stdio.h>
#include <boost/noncopyable.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
using namespace std;
namespace io = boost::iostreams;
class Popen: private boost::noncopyable {
public:
explicit Popen(const char* command):
m_stream(popen(command, "r")) {
if (!m_stream) throw runtime_error("popen failed");
}
~Popen() {
pclose(m_stream);
}
FILE* stream() const {
return m_stream;
}
private:
FILE* m_stream;
};
int main() {
Popen pipe_wrapper("find `pwd` -name \"*.cpp\"");
io::file_descriptor_source pipe_device(fileno(pipe_wrapper.stream()), io::never_close_handle);
io::stream<io::file_descriptor_source> pipe_stream(pipe_device, 0x1000, 0x1000);
string filename;
while (getline(pipe_stream, filename)) {
cout << filename << endl;
ifstream file_stream(filename.c_str(), ifstream::in);
string progline;
while (getline(file_stream, progline)) {
cout << progline << endl;
}
}
}