我必须创建Iterator类,在向量中迭代序列以完成任务,但是在task中使用了基于范围的for循环,例如:
for (T element: sequence) {
std::cout << element << " ";
std::cin >> numToGenerate;
sequence.generateNext(numToGenerate);
}
因此,我应该创建自己的Sequence和Iterator类,它们可以完成任务,但我不知道如何执行end()迭代器。
这是到目前为止的代码:
template<typename T, typename Generator>
class Sequence
{
std::vector<T> elements;
Generator generator;
public:
class Iterator
{
public:
int index;
std::vector<T>& elements;
Iterator(int index, std::vector<T>& elements) : index(index), elements(elements) {};
void operator++()
{
this->index++;
}
T operator*()
{
return this->elements[this->index];
}
bool operator!= ( Iterator other)
{
return this->index != other.index;
}
};
void generateNext(int numToGenerate)
{
for (int i = 0; i < numToGenerate; i++)
{
T next = generator();
elements.push_back(next);
}
}
Iterator begin()
{
return Iterator(0, elements);
}
Iterator end()
{
//??????????
}
};
答案 0 :(得分:1)
您可以创建结束迭代器,该迭代器指向向量中最后一个元素之外的某个位置,就像'std :: vector的迭代器一样。
Iterator end()
{
return Iterator(elements.size(), elements);
}
作为替代方案,您可以只使用std::vector::iterator
,并为其创建包装器begin
和end
方法。
答案 1 :(得分:0)
我不得不说,我觉得你的动机值得怀疑。为什么要 遍历元素时将元素推到末尾?
您的generateNext
不依赖于索引。无论您使用什么索引,都必须一直推到最后(这意味着Generator
必须记住它已经产生了什么元素,即保留一个索引,这不是序列应该做的吗?)。
假设您的循环是书面形式,则只有在用户多次键入0
直到序列结束时,循环才能结束。将元素插入序列的自然方法是您在generateNext
中实现的方法。我不知道为什么要干预序列以进行迭代。
无论如何,如果对end
迭代器进行特殊比较(为了简洁起见,我省略了Generator
),循环就可以正常工作了:
#include <iostream>
#include <vector>
template<typename T>
struct Sequence {
std::vector<T> elements;
struct Iterator {
int index;
std::vector<T>& elements;
bool isEnd;
Iterator(int index, std::vector<T>& elements,bool isEnd=false)
: index(index), elements(elements) {};
void operator++() { this->index++; }
T operator*() { return this->elements[this->index]; }
bool operator!= (const Iterator& other) {
if (other.isEnd) return index != elements.size();
return this->index != other.index;
}
};
void generateNext(int numToGenerate) {
static int counter = 0;
for (int i = 0; i < numToGenerate; i++) { elements.push_back(counter+i); }
counter += numToGenerate + 100;
}
Iterator begin() { return Iterator(0, elements); }
Iterator end() { return Iterator(0,elements,true); }
};
现在您可以使用基于范围的for循环了:
int main() {
Sequence<int> s;
s.generateNext(5);
for (auto element : s) {
if (element <3) s.generateNext(3);
}
for (auto element : s) { std::cout << element << " ";}
}
输出:
0 1 2 3 4 105 106 107 208 209 210 311 312 313
请注意,我特别选择了“生成器”,以便您可以看到循环中何处生成数字。这真的是您想要的吗?让我再问一遍:为什么您会以这种方式生成序列?考虑如何填充向量:
first iteration: 0 1 2 3 4 105 106 107
^--------------------this one would be printed in your loop
second iteration: 0 1 2 3 4 105 106 107 208 209 210
^
third iteration: 0 1 2 3 4 105 106 107 208 209 210 311 312 313
^
and then some more iterations where we dont add elements to eventually reach the end
底线:我强烈建议您重新考虑您的设计。 for
循环通常表示您事先知道必须执行多少次迭代。使用迭代器通常有助于独立于容器类型,但实际上在循环内部您确实使用了容器而不是迭代器。 end
迭代器通常是“脆弱的”,因为如果您推送某些内容,那么即使没有重新分配,end
之前的内容现在也不再可用。
TL; DR:改为使用while循环,类似以下内容:
sequence s;
generator g;
while (g.has_more()) s.push_back(g());
答案 2 :(得分:0)
include <iostream>
#include "Sequence.h"
class IntegersGenerator {
int last;
public:
IntegersGenerator() : last(0) {}
int operator()() {
return this->last++;
}
};
class FibonacciGenerator{
int last;
int current;
public:
FibonacciGenerator() : last(0), current(0) {}
int operator()() {
if (this->current == 0 && this->last == 0) {
this->last = 1;
return 0;
}
int next = this->last + this->current;
this->last = this->current;
this->current = next;
return next;
}
};
template<typename T, typename Generator>
void readGenerateWrite() {
Sequence<T, Generator> sequence;
int numToGenerate;
std::cin >> numToGenerate;
sequence.generateNext(numToGenerate);
for (T element : sequence) {
std::cout << element << " ";
std::cin >> numToGenerate;
sequence.generateNext(numToGenerate);
}
}
int main() {
char generatorType;
std::cin >> generatorType;
if (generatorType == 'i') {
readGenerateWrite<int, IntegersGenerator>();
}
else if (generatorType == 'f') {
readGenerateWrite<int, FibonacciGenerator>();
}
return 0;
}
这是任务提供给我的代码,我无法更改。
和示例:
输入:
我
3 1 1 0 2 0 0 0
输出:0 1 2 3 4 5 6
答案 3 :(得分:0)
本周我的任务完全相同,您的代码对我有很大帮助。您可能已经解决了任务,但是我发现end()返回什么无关紧要-它可以与begin()相同或可以成功编译的任何东西。任务的关键是运算符!=的重载,因此它将在每个周期获取新的向量大小。我通过比较变量索引和大小来做到这一点。
bool operator!= ( Iterator other)
{
return this->index != elements.size();
}