2009-12-16 2 views
4

Я пишу в Microsoft Visual C++, и я хотел бы, чтобы моя программа либо читала стандартный ввод, либо файл, используя istream_iterator. Googling the internets не показал, насколько просто я думаю, что это должно быть. Так, например, я могу написать это довольно легко и читать из стандартного ввода:Использование istream_iterator и чтение из стандартного ввода или файла

#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, и продолжать рассказывать о моем веселом пути?

ответ

10

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

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); 
    } 
} 
1

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

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

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

+0

Это попытка привязать значение r к неконстантной ссылке и является незаконной в C++. –

+0

@Alex: Если один операнд может быть неявно преобразован в ссылку на другой тип, результатом будет lvalue. http://www.open-std.org/jtc1/sc22/wg21/docs/wp/html/nov97-2/expr.html#expr.cond –

+0

Вы, кажется, правы - VC 2008 компилирует это без проблем , Похож на ошибку VC 2005. –

0

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

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

Я не проверял это, хотя. Это то, что вам нужно?

1

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

istream_iterator<string> my_it((argc == 2) ? ifstream(argv[1]) : cin); 

Однако, что вона 't работает, потому что он создает временный объект 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, может быть, Саттер или Александреску?

+0

Это также пытается привязать значение r к неконстантной ссылке. VC++ говорит: 'Неконстантная ссылка может быть привязана только к lvalue' –