使用istream_iterator从标准输入或文件中读取数据

7

我正在使用Microsoft Visual C++编写程序,希望程序能够使用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)检查可以让我使用文件流或标准输入初始化我的输入流迭代器,并继续进行下去呢?

4个回答

14

在构造迭代器之后,您可以对其进行赋值:

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,无需担心输入的来源。


这尝试将一个r-value绑定到非const引用上,在C++中是不合法的。 - Alex Budovski
@Alex:如果一个操作数可以隐式转换为另一种类型的引用,则结果是一个左值。http://www.open-std.org/jtc1/sc22/wg21/docs/wp/html/nov97-2/expr.html#expr.cond - Drew Dormann
你似乎是正确的 - VC 2008 可以编译这个没有问题。看起来是 VC 2005 的一个 bug。 - Alex Budovski

1
乍一看,最简单的解决方案是使用三元运算符?:,如下所示:
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上,也许是Sutter或Alexandrescu?

这也试图将一个rvalue绑定到一个非const引用上。VC++说:“非const引用只能绑定到lvalue”。 - Alex Budovski

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

我还没有测试过这个,不过这是你想要的吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接