Используя istream_iterator и читающий из стандартного входа или файла

Я пишу в 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 и продолжить о моем веселом пути?

6
задан chrisaycock 21 November 2014 в 17:33
поделиться

4 ответа

Вы можете назначить итератору после его создания:

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);
   }
}
13
ответ дан 8 December 2019 в 16:03
поделиться

На первый взгляд, самым простым решением было бы использовать тернарный оператор ?: следующим образом:

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, может быть, Саттер или Александреску?

1
ответ дан 8 December 2019 в 16:03
поделиться

Этот небольшой фрагмент даст вам istream input , который может быть либо файлом, либо std :: cin.

std::ifstream filestream;
if ( use_file )
    filestream.open( ... );
std::istream &input = use_file ? filestream : std::cin;

Теперь вы можете использовать input ], не беспокоясь о том, из какого источника поступает вход.

1
ответ дан 8 December 2019 в 16:03
поделиться

Вы имеете в виду что-то вроде этого: (используя указатели)

#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;
}

Я не тестировал это. Это то, что вам нужно?

0
ответ дан 8 December 2019 в 16:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: