从字符串流递增字数
Incrementing word count from a stringstream
我还在学习C++,我想出了一个很难理解的表达方式。
基本上,它将 cin 输入到 istringstream,然后对其进行处理以将单个单词及其计数(出现次数)保存在地图容器"单词"中
代码
std::map<string, int> words;
std::istream_iterator<string> begin(cin);
std::istream_iterator<string> end;
while(begin != end )
words[*begin++]++;
如果有人可以为我解释 while 循环的代码?我知道最终结果,只是想知道它到底是如何做到的。谢谢!
关于std::istream_iterator<T>
:此类型提供了一个迭代器接口来流式传输I/O。 在这里,begin
和 end
是迭代器(您可以将它们视为 string
s 的"虚拟"容器中的迭代器,在 cin
的输入中表示)。
因为begin
是用cin
初始化的,所以它将成为我所说的"活动"迭代器:它将在第一次被取消引用时读取cin
(如*begin
),并在每次前递增或递增后(begin++
)后第一次读取
由于end
没有用任何东西初始化,所以它变成了一个特殊的"结束标记"迭代器,而不是一个活动的迭代器。 此特殊迭代器值的唯一目的是成为活动迭代器在到达文件末尾后可以进行比较的内容。
这样,从文件中读取一系列T
(在本例中为 string
)可以硬塞到容器的普通迭代器遍历中:)
[编辑:澄清operator[]()
的行为。
关于std::map<string, int>
:你可以把map看作是一种非常通用的数组类型,除了小整数之外,还可以用其他东西来索引——在这种情况下,是字符串。 std::map<K, T>
类型重载operator[]()
返回对由 key 参数标识的现有元素的引用,并具有附加功能(通常很有用,因为它在这里)功能,如果映射中不存在具有该键的元素,它将添加默认值(0 表示 int
),并将返回对此全新元素的引用。
- *开始 - 获取迭代器值
- *begin++ - 然后递增迭代器
- words[*begin++] - 将步骤 1 中的值传递给 map [] 运算符,这意味着通过键获取值。
- 单词[*begin++]++ - 递增该值。
对于来自 cin 的所有字符串,我们在映射中搜索一个 int 并递增它。似乎我们计算相等的字符串。
只需将其分解为多行,如果您在理解压缩的单行代码时遇到困难,请保存中间结果。
std::map<std::string, int> words;
std::istream_iterator<std::string> begin(std::cin);
//default constructor creates an end of stream iterator
std::istream_iterator<std::string> end_of_stream;
while(begin != end_of_stream ){
std::string from_cin = *begin; //reads from std::cin
int &count_ref = words[from_cin]; //can create a new entry
count_ref++; //increment value in the map
begin++; //advance the stream_iterator
}
有关确切语义的相关参考页面是
isstream_iterator构造函数
isstream_iterator运算符 *
地图运算符 []
std::map 中的下标运算符的行为方式如下。如果没有与键对应的元素,则创建该元素并将其初始化为零。否则,它返回对值类型的引用。
所以在你的代码表达式中
words[*begin++]
返回类型为 value_type 的现有值,该值为 int,对应于等于 *begin 的字符串对象,或者返回 0,因为新对象是使用键 *begin 创建的。之后,返回值递增。
words[*begin++]++;
也许简单地引用C++标准会更好
T& operator[](const key_type& x); 1 效果:如果没有键 等效于映射中的 x,将 value_type(x, T()) 插入到映射中。 2 要求:key_type应是可复制的,mapped_type 是默认可构造的。 3 返回:对mapped_type的引用 对应于 *this 中的 x。 4 复杂度:对数。