从标准输入或文件中读取

7

当我尝试编译代码时

istream in;
if (argc==1)
        in=cin;
else
{
        ifstream ifn(argv[1]);
        in=ifn;
}

gcc报错,提示operator=是私有的。是否有办法根据条件设置istream的不同值?

4个回答

5
您可以使用指针来表示in,例如:
istream *in;
ifstream ifn;

if (argc==1) {
     in=&cin;
} else {
     ifn.open(argv[1]);
     in=&ifn;
}

4

所以,它不是抱怨"没有适当的构造函数可用"吗?无论如何,您可以按以下方式修改它。

void Read(istream& is)
{
    string line;
    while (getline(is, line))
        cout << line;
}

int main(int argc, char* argv[])
{
    if (argc == 1)
        Read(cin);
    else
    {
        ifstream in("sample.txt");
        Read(in);
    }
}

2
你应该解释为什么这样做,而不只是发布一些代码。流对象不能被复制或分配,因此通常我们将流作为非const引用传递,因为我们传递的IO对象意图从中读取或写入数据。 - Alexandros Gezerlis

4

您可以将cin的streambuf替换为另一个,在某些程序中,这比传递istreams而不直接引用cin的一般策略更简单。

int main(int argc, char* argv[]) {
  ifstream input;
  streambuf* orig_cin = 0;
  if (argc >= 2) {
    input.open(argv[1]);
    if (!input) return 1;
    orig_cin = cin.rdbuf(input.rdbuf());
    cin.tie(0); // tied to cout by default
  }

  try {
    // normal program using cin
  }
  catch (...) {
    if (orig_cin) cin.rdbuf(orig_cin);
    throw;
  }

  return 0;
}

即使在控制流离开main函数后使用cin是非常罕见的,上述try-catch语句可以避免未定义行为,如果你的程序可能会这样做的话。

为什么在将cin绑定到文件后,需要将其与cout关联起来,而在catch块中却不需要? - m42a
@m42a 它与 cout 解除了绑定。但我同意我们可能想要重新绑定它。 - Alex Jasmin
@m42a:绑定影响刷新(在cin从stdin读取之前,它会刷新cout),但在此处“重定向”cin时不需要。在大多数情况下,在控制权离开main后从cin读取将是逻辑错误,但至少如果您恢复streambuf,则可以避免未定义的行为(ifstream的filebuf将被销毁)。如果您想要,可以使用cin.tie(&cout) - Roger Pate

1

您无法以这种方式影响流。但是,使用指向 istream 的指针可以实现您想要的目标。

#include <fstream>
#include <istream>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
  istream *in;
  // Must be declared here for scope reasons
  ifstream ifn;

  // No argument, use cin
  if (argc == 1) in = &cin;
  // Argument given, open the file and use it
  else {
    ifn.open(argv[1]);
    in = &ifn;
  }
  return 0;

  // You can now use 'in'
  // ...
}

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