• 实现动态大数结构


      大数结构是一种常见的数据结构,在C++当中,我们常用vector来动态实现。除此之外,我们也可以仿照vector的思路,自己实现内存的动态分配,当内存容量达到上限时,用C-api realloc进行内存的重新分配。

    #define REQUIRE2(p, q) assert((p) || (q))
    #define REQUIRE1(p) assert(p)
    #define INITSIZE 24

      先定义了几个宏,前两个是对表达式的判断,INITSIZE是动态大数结构的初始阈值,当超过了这个阈值之后,便发生扩容。

    public:
            BigNum(const BigNum& other) : sign(other.sign), p(other.p) {}
            BigNum() {
                p = static_cast<char *>(malloc(INITSIZE));
                REQUIRE1(p);
            }
            BigNum(BigNum&& other) : sign(other.sign), p(other.p) {}
            ~BigNum() {
                free(p);
            }
    
            BigNum& operator=(const BigNum& other) = default;
            bool operator==(const BigNum& other) const = default;

      构造析构......注意析构要释放内存,防止发生内存泄漏。

    void init() {
                sign = getchar();
                REQUIRE2(sign == '+', sign == '-');
                
                char c;
                char *start = p;
                while ((c = getchar()) != ' ' && c != '\n' && c != '\t' && c != '\r') {
                    REQUIRE1(isdigit(c));
                    if (start - p >= threshold - 1) {
                        void *mem = realloc(p, threshold << 1);
                        REQUIRE1(mem);
                        p = static_cast<char *>(mem);
                        start = p + threshold - 1;
                        threshold <<= 1;
                    }
                    *start = c;
                    ++start;
                }
                start = nullptr;
            }

      这是关键的一部分,通过getchar函数,使得从键盘上动态读取字符,并且维护一个指针start,这样就可以实时统计大数结构当中的容量。在这里,前面定义的宏就派上用场了,需要严格检查读入的字符是否为数字(第一个读入的字符必须是+或者-符号)。

    friend std::ostream& operator<<(std::ostream& os, const BigNum& big) {
                os << big.sign << big.p;
                return os;
            }

      重载输出函数。

    private:
            char sign;
            char *p;
            std::size_t threshold = INITSIZE;

      在内部,维护了三个成员,分别是数的符号,指向初始内存位置的指针与阈值(阈值每次发生扩容时会乘2)。

     

      完整代码如下

    #define REQUIRE2(p, q) assert((p) || (q))
    #define REQUIRE1(p) assert(p)
    #define INITSIZE 24
    
    class BigNum {
        public:
            BigNum(const BigNum& other) : sign(other.sign), p(other.p) {}
            BigNum() {
                p = static_cast<char *>(malloc(INITSIZE));
                REQUIRE1(p);
            }
            BigNum(BigNum&& other) : sign(other.sign), p(other.p) {}
            ~BigNum() {
                free(p);
            }
    
            BigNum& operator=(const BigNum& other) = default;
            bool operator==(const BigNum& other) const = default;
    
            void init() {
                sign = getchar();
                REQUIRE2(sign == '+', sign == '-');
                
                char c;
                char *start = p;
                while ((c = getchar()) != ' ' && c != '\n' && c != '\t' && c != '\r') {
                    REQUIRE1(isdigit(c));
                    if (start - p >= threshold - 1) {
                        void *mem = realloc(p, threshold << 1);
                        REQUIRE1(mem);
                        p = static_cast<char *>(mem);
                        start = p + threshold - 1;
                        threshold <<= 1;
                    }
                    *start = c;
                    ++start;
                }
                start = nullptr;
            }
    
            friend std::ostream& operator<<(std::ostream& os, const BigNum& big) {
                os << big.sign << big.p;
                return os;
            }
    
        private:
            char sign;
            char *p;
            std::size_t threshold = INITSIZE;
    };

     

  • 相关阅读:
    大数据运维之MySQL备份及恢复
    【已解决】将一个2708行64列的在GPU上的张量z0矩阵保存下来,格式为csv
    封装了一个中间放大效果的iOS轮播视图
    torch-sparse安装错误; windows上面jps没有namenode;如何下载spark
    synchronized修饰类的注意事项
    值得苦练的100道Python经典练手题,(附详细答案)
    树莓派4b+mcp2515实现CAN总线通讯和系统编程(一.配置树莓派CAN总线接口)
    (续)SSM整合之springmvc笔记(RESTful之HiddenHttpMethodFilter源码解析)(P147)了解
    知识点14:cache的伪共享以及如何避免
    网络编程基础知识拾遗:用大白话解释什么是交换机、路由器、光猫、IP地址和子网掩码、公网和内网IP、端口和域名
  • 原文地址:https://www.cnblogs.com/ChebyshevTST/p/17793346.html