简单的 istream_iterator 问题

2022-01-20 00:00:00 复制 c++ istream-iterator

我是 C++ 新手,如果这是一个愚蠢的问题,我很抱歉.我似乎无法弄清楚为什么这不起作用.它复制到第一个向量中,并且似乎跳过了第二个复制调用.

I am new to C++, sorry if this is a silly question. I cannot seem to figure out why this does not work. It copies into the first vector, and seems to skip past the second copy call.

#include <iostream>
#include <vector>
#include <iterator>

using namespace std;

int main ()
{
    vector<int> first;
    vector<int> second;

    copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(first));
    cin.clear();
    copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(second)); 
    return 0;
}

我想使用复制函数将 istream_iterator 输入读入任意数量的向量(每个向量一次调用复制).换句话说:我希望能够在控制台中输入1 2 3 4 5 ctrl+d"并将 1,2,3,4,5 输入到第一个向量中.然后在控制台中输入6 7 8 9 10 ctrl+d"并将 6,7,8,9,10 输入到第二个向量中.

I want to use the copy function to read istream_iterator input into any number of vectors(one call to copy per vector). In other words: I want to be able to enter "1 2 3 4 5 ctrl+d" into the console and have 1,2,3,4,5 entered into the first vector. Then enter "6 7 8 9 10 ctrl+d" into the console and have 6,7,8,9,10 entered into the second vector.

问题是,在我将一些输入输入到第一个向量并按下 control+d 后,cin 的 istream_iterator 仍然等于 istream_iterator(),无论 cin 的失败状态如何.这会导致每次对复制"的后续调用都失败(因为 istream_iteratorcin 已经等于程序解释为 eof 的 istream_iterator()).所以我的问题是:我需要做什么来重置"迭代器以及 cin 流?cin.clear() 确实清除了所有失败位.然而 istream_iterator(cin) 仍然等于 istream_iterator() 无论如何.据我了解,绑定到流的 istream_iterators 仅应在流处于失败状态时等于默认的 istream_iterator 值.我错过了什么?

The problem is that after I enter some input into the first vector and press control+d the istream_iterator for cin remains equal to istream_iterator(), regardless of cin's fail state. This causes every subsequent call to "copy" to fail (because istream_iteratorcin is already equal to istream_iterator() which the program interprets as eof). So my question is: What do I need to do to "reset" the iterator along with the cin stream? cin.clear() is indeed clearing all the fail bits. However the istream_iterator(cin) is still equal to istream_iterator() regardless. From what I understand, istream_iterators that are bound to a stream should only be equal to the default istream_iterator value when the stream is in a fail state. What am I missing?

推荐答案

istream_iterator 是一个输入迭代器,这意味着你只能解引用每个迭代器值一次.您实际上是在从流中阅读,并且没有寻找或返回.因此,一旦您到达流的末尾,就没有更多的输入,并且第二个范围是空的.

The istream_iterator is an input iterator, which means you can only dereference each iterator value once. You are literally reading from a stream, and there's no seeking or going back. So once you hit the end-of-stream, there's nothing more to input and the second range is empty.

为什么不直接说 vector<int>second(first); 复制?

Why not just say vector<int> second(first); to make a copy?

更新:在您澄清问题后,这里有一个新答案:您误解了 stdin 的工作原理.只有 一个 输入.Ctrl-D 不是 C++ 固有的;相反,这是您平台的约定,当您发出 Ctrl-D 信号时,您的平台将终止输入缓冲区.之后,输入的文件"就完成了,不能再往里面写数据了.

Update: After you clarified the question, here's a new answer: You're misunderstanding how stdin works. There is only one input. Ctrl-D isn't anything inherent to C++; rather, it is a convention of your platform, and your platform will terminate the input buffer when you signal Ctrl-D. After that, the input "file" is finished, and no further data can be written to it.

不过,您的方法有点不正统.通常,您只需逐行读取,用 Enter 分隔,然后标记每一行.使用字符串流,你会得到非常相似的代码:

Your approach is a bit unorthodox, though. Usually, you would just read line by line, separated by Enter, and tokenize each line. Using string streams, you get very similar code:

std::string line;
std::vector<int> first, second;

// Read line 1
if (std::getline(std::cin, line))
{
  std::istringstream iss(line);
  std::copy(std::istream_iterator<int>(iss), std::istream_iterator<int>(), std::back_inserter(first));
}
else { /* error */ }

// Read line 2
if (std::getline(std::cin, line))
{
  std::istringstream iss(line);
  std::copy(std::istream_iterator<int>(iss), std::istream_iterator<int>(), std::back_inserter(second));
}
else { /* error */ }

相关文章