Я пишу в Microsoft Visual C++, и я хотел бы, чтобы моя программа или читала из стандартного входа или файла с помощью istream_iterator
. Поиск с помощью Google Интернета не показал, как простой я думаю, что это должно быть. Так, например, я могу записать это довольно легко и читать из стандартного входа:
#include <iostream>
#include <string>
#include <iterator>
using namespace std;
int main()
{
istream_iterator<string> my_it(cin);
for (; my_it != istream_iterator<string>(); my_it++)
printf("%s\n", (*my_it).c_str());
}
Или я могу записать это и читать из файла:
#include <iostream>
#include <string>
#include <iterator>
#include <fstream>
using namespace std;
int main(int argc, char** argv)
{
ifstream file(argv[1]);
istream_iterator<string> my_it(file);
for (; my_it != istream_iterator<string>(); my_it++)
printf("%s\n", (*my_it).c_str());
}
Но как я комбинирую эти два так, чтобы простое (argc == 2)
проверка позволяет мне инициализировать свой входной потоковый итератор или с потоком файла или с stdin и продолжить о моем веселом пути?
Вы можете назначить итератору после его создания:
int main(int argc, char** argv)
{
ifstream file;
istream_iterator<string> my_it;
if(argc == 2) {
file.open(argv[1]);
my_it = istream_iterator<string>(file);
} else {
my_it = istream_iterator<string>(cin);
}
}
На первый взгляд, самым простым решением было бы использовать тернарный оператор ?:
следующим образом:
istream_iterator<string> my_it( (argc == 2) ? ifstream(argv[1]) : cin );
Однако это не совсем сработает, потому что он создает временный объект ifstream
, который будет уничтожен в конце оператора. Итак, вам нужен способ условного создания ifstream
и условного его уничтожения после цикла for
. std :: auto_ptr <>
отвечает всем требованиям. Таким образом:
auto_ptr<ifstream> file((argc == 2) ? new ifstream(argv[1]) : NULL);
istream_iterator<string> my_it( (argc == 2) : *file : cin);
for (; my_it != istream_iterator<string>(); my_it++)
printf("%s\n", (*my_it).c_str());
Другим, вероятно, более чистым решением было бы переместить итерацию в отдельную функцию, которая принимает istream &
.
Я видел эту проблему раньше в сети, ее описал один из великих разработчиков C ++ . К сожалению, точно не помню, где и кем! Я думаю, это было на DDJ, может быть, Саттер или Александреску?
Этот небольшой фрагмент даст вам istream input
, который может быть либо файлом, либо std :: cin.
std::ifstream filestream;
if ( use_file )
filestream.open( ... );
std::istream &input = use_file ? filestream : std::cin;
Теперь вы можете использовать input
], не беспокоясь о том, из какого источника поступает вход.
Вы имеете в виду что-то вроде этого: (используя указатели)
#include <iostream>
#include <string>
#include <iterator>
#include <fstream>
using namespace std;
int main(int argc, char** argv)
{
istream_iterator<string>* my_it = NULL;
if (argc == 2)
{
ifstream file(argv[1]);
my_it = new istream_iterator<string>(file);
}
else
{
my_it = new istream_iterator<string>(cin);
}
...
delete my_it;
}
Я не тестировал это. Это то, что вам нужно?