Решение с if
является более или менее стандартным решением, когда
имеем дело с argv
:
if ( argc == 1 ) {
process( std::cin );
} else {
for ( int i = 1; i != argc; ++ i ) {
std::ifstream in( argv[i] );
if ( in.is_open() ) {
process( in );
} else {
std::cerr << "cannot open " << argv[i] << std::endl;
}
}
Однако это не относится к вашему делу, поскольку ваша главная задача -
получить строку, а не "обрабатывать" аргументы имени файла.
В своем собственном коде я использую написанное мной MultiFileInputStream
, которое
принимает список имен файлов в конструкторе и возвращает EOF только когда
последний был прочитан: если список пуст, он читает std::cin
. это
обеспечивает элегантное и простое решение вашей проблемы:
MultiFileInputStream in(
std::vector<std::string>( argv + 1, argv + argc ) );
std::string const input = slurp( in );
Этот класс стоит написать, так как он обычно полезен, если вы часто
писать Unix-подобные утилиты. Это определенно не тривиально, однако,
и может быть много работы, если это разовая необходимость.
Более общее решение основано на том факте, что вы можете позвонить
неконстантный член функции на временной, и тот факт, что большинство
функции-члены std::istream
возвращают std::istream&
& mdash;
не константная ссылка, которая затем будет привязана к неконстантной ссылке. Так
Вы всегда можете написать что-то вроде:
std::string const input = slurp(
use_stdin
? std::cin.ignore( 0 )
: std::ifstream( argv[1] ).ignore( 0 ) );
Однако я бы посчитал это чем-то вроде взлома, и он имеет более общий характер.
проблема в том, что вы не можете проверить, открыт ли (вызывается конструктором
std::ifstream
работал.
В целом, хотя я понимаю, чего вы пытаетесь достичь, я
Я думаю, вы обнаружите, что IO почти всегда будет исключением.
Вы не можете прочитать int
, не определив его сначала, и вы не можете
читать строку, не определив сначала std::string
. согласен
что это не так элегантно, как могло бы быть, но затем, код, который правильно
обрабатывает ошибки редко так элегантно, как хотелось бы. (Одно решение
здесь было бы извлечь из std::ifstream
, чтобы бросить исключение, если
открытое не сработало; все, что вам нужно, это конструктор, который проверен на
is_open()
в теле конструктора.)