Python-like range

题目描述

实现类似 Python 中的 range 函数。

具体而言,range(start, stop, step = 1); 生成一个范围;这个范围内的元素都是整数;从 start(含)开始,stop(不含)结束,每个元素之间以 step 为差递增。比如 for(int i : range(0, 5)) /*...*/ 会让 i 在每次循环中取值为 0, 1, 2, 3, 4。

本题目只要求 range 函数能在基于范围的 for 循环中工作,不做更多要求。

关于输入

关于输出

见样例输出

练习目标

  • 了解“基于范围的 for 循环”的工作原理:通过 begin end 和迭代器来确定范围及范围元素;
  • 尝试自己编写一个范围。

我们期望同学们定义的是“抽象”的范围概念,即在“迭代器”的迭代中实现步进递增。有的同学使用“动态数组”的做法,在构造范围时将所有元素填充好,随后返回数组的范围定义。这样做是满足题目要求的,但是不好:如果这道题改成到 INT_MAX 的范围并由循环体决定何时 break,那么实现生成“动态数组”的做法就会超时、超内存。

参考答案

#include <iostream>

class IotaSentinel {
private:
    int value;
    friend class IotaIterator;

public:
    IotaSentinel(int value) : value{value} {}
};

class IotaIterator {
private:
    int value, step;

public:
    IotaIterator(int value, int step) : value{value}, step{step} {}
    int operator*() const {
        return value;
    }
    IotaIterator& operator++() {
        value += step;
        return *this;
    }
    bool operator!=(const IotaSentinel& rhs) {
        if (step > 0) {
            return value < rhs.value;
        } else {
            return value > rhs.value;
        }
    }
};

class IotaRange {
    int start, stop, step;

public:
    IotaRange(int start, int stop, int step) : start{start}, stop{stop}, step{step} {}
    IotaIterator begin() const {
        return IotaIterator(start, step);
    }
    IotaSentinel end() const {
        return IotaSentinel(stop);
    }
};

IotaRange range(int start, int stop, int step = 1) {
    return IotaRange(start, stop, step);
}

int main() {
    for (int i : range(0, 10)) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    for (int i : range(1, 20, 2)) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    for (int i : range(10, 0, -3)) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    for (int i : range(10, 0)) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
}

// 请不要使用任何标准库容器。
#if defined(_GLIBCXX_VECTOR) || defined(_GLIBCXX_DEQUE) || defined(_GLIBCXX_FORWARD_LIST) || \
    defined(_GLIBCXX_LIST)
#error Do not use standard library containers.
#endif

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 



























#include <iostream>

class IotaRange {
    int* data;
    int size;

public:
    IotaRange(int start, int stop, int step) {
        size = 1 + (stop - start - 1) / step;
        if (size <= 0) {
            size = 0;
        }
        data = new int[size];
        for (int i = 0; i < size; i++) {
            data[i] = start + i * step;
        }
    }
    int* begin() {
        return data;
    }
    int* end() {
        return data + size;
    }
    ~IotaRange() {
        delete[] data;
    }
};

IotaRange range(int start, int stop, int step = 1) {
    return IotaRange(start, stop, step);
}

int main() {
    for (int i : range(0, 10)) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    for (int i : range(1, 20, 2)) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    for (int i : range(10, 0, -3)) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    for (int i : range(10, 0)) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
}

// 请不要使用任何标准库容器。
#if defined(_GLIBCXX_VECTOR) || defined(_GLIBCXX_DEQUE) || defined(_GLIBCXX_FORWARD_LIST) || \
    defined(_GLIBCXX_LIST)
#error Do not use standard library containers.
#endif