【问题标题】:How to read lines from a file as well as from std::cin?如何从文件以及 std::cin 中读取行?
【发布时间】:2021-10-21 00:37:03
【问题描述】:

我正在编写一个程序,它从文件中获取要使用的文本行,用户将其名称作为参数传递,例如program <name of the file>。但如果未提供名称,则从std::cin 动态获取输入。我试过的:

  1. 重定向缓冲区(为什么会导致段错误)
if (argc == 2) {
    std::ifstream ifs(argv[1]);
    if (!ifs)
        std::cerr << "couldn't open " << argv[1] << " for reading" << '\n';
    std::cin.rdbuf(ifs.rdbuf());
}

for (;;) {
    std::string line;
    if (!std::getline(std::cin, line)) // Here the segfault happens 
        break;
  1. 创建一个变量,其中存储了输入源
std::ifstream ifs;
if (argc == 2) {
    ifs.open(argv[1]);
    if (!ifs)
        std::cerr << "couldn't open " << argv[1] << " for reading" << '\n';
} else
    ifs = std::cin;  // Doesn't work because of the different types

for (;;) {
    std::string line;
    if (!std::getline(ifs, line))
        break;

现在我正在考虑对文件结构/描述符做一些事情。怎么办?

UPD:我希望能够在程序的主循环中更新输入源(见下文)。

【问题讨论】:

  • 将您的代码写入一个接受ostream&amp; 并输出到该函数的函数中。然后,您可以将您希望使用的流传递给该函数。
  • 编写一个接受std::istream &amp; 并从该流中读取的函数。如果您的程序需要从std::cin 读取,则将std::cin 传递给该函数。如果您的程序需要从文件中读取,则将该文件作为 std::ifstream 打开并将该流传递给您的函数。

标签: c++


【解决方案1】:

第一个示例中的段错误是由于指针悬空造成的;在你调用std::cin.rdbuf(ifs.rdbuf()) 之后,ifs 被销毁。 您应该按照@NathanOliver 的建议做,并编写一个采用istream&amp; 的函数:

#include <iostream>
#include <fstream>
#include <string>

void foo(std::istream& stream) {
  std::string line;
  while (std::getline(stream, line)) {
    // do work
  }
}

int main(int argc, char* argv[]) {
  if (argc == 2) {
    std::ifstream file(argv[1]);
    foo(file);
  } else {
    foo(std::cin);
  }
}

【讨论】:

  • 您不能使用:foo(std::ifstream(argv[1]));,因为这会创建一个不会绑定到非 const 左值引用(即std::istream&amp;)的临时变量。因此,您应该创建一个本地自动变量,然后您可以将其作为对函数的引用传递。
  • 最好在一行中进行读取和测试。更喜欢使用while(std::getline())
  • 已为您修复 :-)
  • 谢谢,我同样实现了我当前的解决方案。但是如果我想在foo 函数中更新我的输入源怎么办?不递归怎么办?
  • @nuts_eater:您必须使用参考以外的其他东西(即看起来像参考但允许您更改它所指内容的东西)。看看std::ref
猜你喜欢
  • 2021-02-28
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 2013-07-31
  • 2011-11-27
  • 2013-04-01
  • 2016-12-03
相关资源
最近更新 更多