C++计算标准输入的单词数

C++ count the number of words from standard input

看到一段C++代码统计标准输入输入的字数:

#include <iostream>
#include <iterator>
#include <string>
using namespace std;

int main() {
    auto ss {
        istream_iterator<string>{cin}
    };
    cout << distance(ss, {}) << endl;

    return 0;
}

我有几个问题:

  1. auto ss 的类型是什么?
  2. distance(ss, {}) 是做什么的?为什么要计算字数?

我的猜测是:

  1. istream_iterator<string>{cin}将标准输入转换为istream_iterator类型,自动用space分隔(为什么?)。因此 ss 看起来像一个 container,所有单词都是它的元素;
  2. distance(ss, {}) 计算第一个元素与空元素(因此在最后一个元素之外,但为什么呢?)元素之间的距离。

谁能帮我验证一下我对这段奇妙的短代码的猜测?

auto ss 推导出 ssstd::istream_iterator<std::string>,因为这是完整语句构造并分配给 ss.

的内容

istream_iterator 使用指定的 istreamoperator>> to read formatted input of the specified type, where operator>> reads input delimited by whitespace, including space characters, line breaks, etc. So, in this case, istream_iterator<string> is reading std::string values from std::cin 一次一个空格分隔的单词。

istream_iterator 是输入迭代器,默认构造的 istream_iterator 表示 end-of-stream 迭代器。当 istream_iterator 停止读取(到达 EOF、输入错误输入等)时,它的值变为等于 end-of-stream 迭代器。

std::distance() returns the number of elements in a range denoted by a pair of iterators. For a non-random input iterator, like istream_iterator, std::distance() iterates the range one element at a time via the iterator's operator++, counting the number of times it incremented the iterator, until the target iterator is reached. So, in this case, istream_iterator::operator++ 内部从其 istream 中读取一个值,因此 std::distance() 有效地 returns 从 std::cin 到 [=46] 成功读取了多少个单词=]已到达流结束。

因此,您显示的代码大致只是编写以下等效循环的一种算法方式:

int main() {
    string s;
    size_t count = 0;
    while (cin >> s) {
        ++count;
    }
    cout << count << endl;

    return 0;
}
  1. ss 的类型为 std::istream_iterator<std::string>.
  2. std::distance(ss, {}) 计算 std::cin 中第一个以空格分隔的标记到 cin 末尾之间的项目数,有效地返回 std::cin 中以空格分隔的标记数。这是由于 std::istream::operator>>(std::istream&, std::string&) 函数的方式(第二个参数实际上不是 std::string,但我尽量保持简短)。默认构造函数为std::istream_iterator<std::string> returns 任何std::istream_iterator<std::string> 结尾。

对std::cin内容的裁剪实际上是在计算距离的时候偷懒完成的

这确实是一段有趣的代码。