sfj*_*jac 20 c++ algorithm stl c++11
我希望以下内容可以buf_iter指向角色n字符开始后的点.相反,它指向最后一个字符读取.为什么是这样?也就是说,如果我在copy_n之前和之后进行in_stream.tellg(),它们的区别不n在于(n-1).如果我用n字符读取字符in_stream.read,那么该位置将被提前n.
std::istreambuf_iterator<char> buf_iter(in_stream);
std::copy_n(buf_iter, n, sym.begin());
Run Code Online (Sandbox Code Playgroud)
我已经查看了实现,它显然是故意这样做的,跳过最后的增量.
这里的另一篇文章提到,当迭代器连接起来时,从迭代器开始递增cin会导致读取次数过多而导致读取次数过多operator++().这听起来像是一个问题cin- 为什么不进行读取operator*()?
标准是否在任何地方指定了它?我见过的文档没有提到from迭代器会发生什么,我看到两个不同的页面提供了"可能正确的实现",它们执行每个行为:
template< class InputIt, class Size, class OutputIt>
OutputIt copy_n(InputIt first, Size count, OutputIt result)
{
if (count > 0) {
*result++ = *first;
for (Size i = 1; i < count; ++i) {
*result++ = *++first;
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
template<class InputIterator, class Size, class OutputIterator>
OutputIterator copy_n (InputIterator first, Size n, OutputIterator result)
{
while (n>0) {
*result = *first;
++result; ++first;
--n;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
两者都读取并导致结果中的相同内容.但是,第一个只会增加"第一个"迭代器的n-1次数,第二次会增加它的n次数.
是什么赋予了?我如何编写可移植代码?我可以使用tellg然后seekg然后我可能只是手动循环(呃!).
请注意,我不是在调用之后尝试从迭代器中读取copy_n,而是在调用之后我想从底层流中读取copy_n,而问题是copy_n指向的字节远离我预期的位置.现在我要带着一些有点可怕但显然便携的东西:
auto pos = in_stream.tellg();
std::istreambuf_iterator<char> buf_iter(in_stream);
std::copy_n(buf_iter, cl, sym.begin());
in_stream.seekg(pos + cl);
uint64_t foo;
in_stream.read(reinterpret_cast<char *>(&foo), 8);
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果不清楚,我试图避免将数据复制到缓冲区然后再次进入字符串sym.
@DaveS:摆脱我的具体问题,这是一个简单的程序,由于输入迭代器在最后时间没有递增这一事实,因此无法输出我期望的结果:
#include <algorithm>
#include <string>
#include <iostream>
#include <fstream>
int main(int argc, const char * argv[])
{
std::ifstream in("numbers.txt");
std::istreambuf_iterator<char> in_iter(in);
std::ostreambuf_iterator<char> out_iter(std::cout);
std::copy_n(in_iter, 3, out_iter);
std::cout << std::endl;
std::copy_n(in_iter, 3, out_iter);
std::cout << std::endl;
std::copy_n(in_iter, 3, out_iter);
std::cout << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输入文件就是 "0123456789\n"
我越来越:
012
234
456
Run Code Online (Sandbox Code Playgroud)
由于副作用istreambuf_iterator::operator++(),如果copy_n实现增加输入迭代器n时间,则会产生不同的结果.
@aschepler:需要捕获本地参数,但我会用它:
std::generate_n(sym.begin(), cl, [&in_stream](){ return in_stream.get(); });
Run Code Online (Sandbox Code Playgroud)
n3797 [algorithms.general]/12
在运营商的算法的描述
+和-用于一些为它们不具有要定义的迭代器的类别.在这些情况下,语义与.的语义a+n相同Run Code Online (Sandbox Code Playgroud)X tmp = a; advance(tmp, n); return tmp;和那个
b-a是一样的Run Code Online (Sandbox Code Playgroud)return distance(a, b);
[alg.modifying.operations]
Run Code Online (Sandbox Code Playgroud)template<class InputIterator, class Size, class OutputIterator> OutputIterator copy_n(InputIterator first, Size n, OutputIterator result);5 效果:对于每个非负整数i <n,执行
*(result + i) = *(first + i).6 返回:
result + n.7 复杂性:完全
n分配.
我不确定它是否适用于InputIterators(没有多通道),因为它不会修改原始迭代器,但总是会推进原始迭代器的副本.它似乎也没有效率.
[input.iterators] /表107 - 输入迭代器要求(除Iterator外)
表达式:
++r
返回类型:X&
pre:r是dereferencable.
post:r是可解除引用的,或者r是过去的结尾.
post:r不再要求任何前一个值的副本可以解除引用或属于==.
据我所见,a中
Run Code Online (Sandbox Code Playgroud)X tmp = a; advance(tmp, n); return tmp;
因此不再需要增量.
相关缺陷报告:LWG 2173
许多std::copy_n实现增加n-1次的原因是由于与之的交互istream_iterator以及通常如何实现.
例如,如果您有一个包含整数的输入文件
std::vector<int> buffer(2);
std::istream_iterator<int> itr(stream); // Assume that stream is an ifstream of the file
std::copy_n(itr, 2, buffer.begin());
Run Code Online (Sandbox Code Playgroud)
因为istream_iterator指定读取增量(和任何构造或第一个取消引用),如果std::copy_n输入迭代器增加2次,您实际上将读取文件中的3个值.当内部的局部迭代器copy_n超出范围时,第三个值将被丢弃.
istreambuf_iterator没有相同的交互,因为它实际上并不像大多数istream_iterators那样将流中的值复制到本地副本中,但copy_n仍然以这种方式运行.
编辑:如果copy-N增加N次(cplusplus.com描述,似乎不正确),则丢失数据的示例.注意,这实际上仅适用于istream_iterators在增量上读取和删除其基础数据的其他迭代器.
std::istream_iterator<int> itr(stream); // Reads 1st value
while(n > 0) // N = 2 loop start
{
*result = *first;
++result; ++first; // Reads 2nd value
--n; // N: 1
// N = 1 loop start
*result = *first;
++result; ++first; // Reads 3rd value
--n; // N :0
// Loop exit
}
return result;
Run Code Online (Sandbox Code Playgroud)
源迭代器不通过引用获取。因此,它的副本会增加 n 次,但参数保持不变。
十分之九,这就是你想要的。
至于专门在 InputIterators 上递增的副作用,我认为正式地,输入迭代器应在每次读取时“递增”(不递增的重复读取不会产生相同的值)。因此,只需将增量设置为无操作即可。
| 归档时间: |
|
| 查看次数: |
1275 次 |
| 最近记录: |