【问题标题】:Using istream_iterator and reading from standard input or file使用 istream_iterator 并从标准输入或文件中读取
【发布时间】:2009-12-16 02:04:34
【问题描述】:

我正在使用 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) 检查让我使用文件流或标准输入初始化输入流迭代器并继续我的快乐方式?

【问题讨论】:

    标签: c++ file stdin istream-iterator


    【解决方案1】:

    你可以在构造它之后给它赋值:

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

    【讨论】:

      【解决方案2】:

      乍一看,最简单的解决方案是像这样使用三元运算符?:

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

      但是,这并不完全有效,因为它构造了一个临时的 ifstream 对象,该对象将在语句结束时被销毁。因此,您需要一种有条件地创建ifstream 并在for 循环之后有条件地销毁它的方法。 std::auto_ptr&lt;&gt; 符合要求。因此:

      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&amp;

      我之前在网上看到过这个问题,由一位 C++ 大师介绍过。不幸的是,我不记得确切的地点,或由谁!我想是在 DDJ 上,也许是 Sutter 或 Alexandrescu?

      【讨论】:

      • 这也尝试将右值绑定到非常量引用。 VC++ 说:A non-const reference may only be bound to an lvalue
      【解决方案3】:

      这个小 sn-p 将为您提供 istream input,它可以是文件或 std::cin。

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

      您现在可以使用input 而不必担心输入来自哪个来源。

      【讨论】:

      • 这试图将一个右值绑定到一个非常量引用,并且在 C++ 中是非法的。
      • @Alex:如果一个操作数可以隐式转换为对另一种类型的引用,则结果是一个左值。 open-std.org/jtc1/sc22/wg21/docs/wp/html/nov97-2/…
      • 你似乎是正确的——VC 2008 编译这个没有问题。看起来像 VC 2005 的错误。
      【解决方案4】:

      你的意思是这样的吗:(使用指针)

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

      不过,我还没有测试过。这就是你所追求的吗?

      【讨论】:

        猜你喜欢
        • 2011-03-30
        • 1970-01-01
        • 2014-05-27
        • 2013-03-18
        • 2016-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多