C++:string模拟实现(下)

news2025/1/11 12:46:23

目录

一.引言

二.string类的容量操作接口

三.string类的字符串修改操作接口

1.两个插入字符的重载函数:

2.在string字符串末尾追加内容的接口

3.在指定位置pos删除n个字符的接口

四.string类字符串的字符和子串查找接口

五.全局定义的string类字符串比较运算符重载

     六.全局用于string类的流插入和流提取运算符重载


一.引言

书接上回string的模拟实现(上):http://t.csdn.cn/Lphxv

  •  关于函数代码复用的编程思维

在编写复杂的项目时,应尽可能在编写函数模块时复用已经编写好的函数,而且复用函数应遵循同源复用的原则:

这种同源复用的编程思维可以带来诸多好处:

  1. 可以使代码看起来更简洁美观,可读性大大增强
  2. 同源复用相当于划定了一个错误池(比如上图中的函数1),整个复用链只要有一个地方出错,我们都可以一步一步追溯查错直到复用链的源头去修改代码,从而提高了代码的可维护性。

模拟string类的类域代码总览:

#include<iostream>
#include<cstring>
#include <assert.h>
using std :: ostream;
using std :: istream;
using std::cout;
using std::cin;
using std::endl;
//只要不涉及寻址,一定要注意编译器的顺序编译机制

namespace mystring
{



    class string
    {
        public:
            typedef char * iterator;                   //string类的迭代器宏定义
            typedef const char* const_iterator;



            string(const char* nstr);                  //类中四个重要的默认成员函数
            string(const string& nstr);
            ~string();
            string& operator=(string nstr);

            
            void push_back (const char& c);            //在字符串末尾追加字符的功能接口
            void append(const char * str);             //在字符串末尾追加字符串的功能接口
            string& operator+=(char c);                //在字符串末尾追加字符的功能接口
            string& operator+=(const char * str);      //在字符串末尾追加字符串的功能接口
            string& insert (size_t pos , char c);      //pos位置插入一个字符
            string& insert (size_t , const char *str); //pos位置插入一个字符串
            string& erase(size_t pos, size_t n);       //pos位置删除n个字符




            void reserve (size_t newcapacity);         //扩容接口
            void resize(size_t newsize,const char c);  //调整有效字符个数的接口(多出的有效 
                                                       //字符用c填补)










            void copyswap(string &nstr);               //复用交换函数的接口
            iterator begin();                          //string类用于获取迭代器的接口
            iterator end();
            const_iterator begin()const;
            const_iterator end()const;
            const char * C_str()const;                 //用于返回C类型字符串的函数
            char & operator[](int pos);                //用于返回pos下标字符的引用的[]重载
            const char & operator[](int pos) const;     
            size_t size() const;                       //获取有效字符个数size和容量的接口
            size_t capacity() const;
            size_t find(char c,size_t pos =0);         //从第pos个位置查找字符串中第一 
                                                       //个出现c字符的位置
            size_t find(const char * str , size_t pos =0);  //从第pos个位置查找字符串中第一 
                                                            //个出现子串str的位置






        private:
            char * _str;
            size_t _size;
            size_t _capacity;
    };

二.string类的容量操作接口

void reserve (size_t newcapacity);         //扩容接口
void resize(size_t newsize,const char c);  //调整有效字符个数的接口(多出的有效字符用c填补)
  • void reserve (size_t newcapacity);扩容接口(只扩容,不缩容)
    void mystring::string::reserve (size_t newcapacity) //扩容接口
    {
        if(newcapacity > _capacity)
        {
            char * tem = new char[newcapacity+1]; // 重新申请堆空间调整容量,+1是为了保存'\0'
            strcpy(tem,_str);                     // 原空间字符串拷贝新空间
            delete[]_str;                         // 释放原空间
            _str = tem;
            _capacity = newcapacity;
        }
    }

  • void resize(size_t newsize,const char c);

    void mystring::string::resize(size_t newsize,const char c = '\0') 
    {
        if(newsize > _capacity)         //调整有效数字个数前检查是否需要扩容
        {
            reserve(newsize);           //复用扩容接口
        }
        while(newsize > _size)          //如果有效字符个数增大,多余有效字符容量补上c字符
        {
            _str[_size] = c;
            _size ++;
        }
        _size = newsize;
        _str[_size]='\0';
    }

注意:

  1. 形参char c最好给上'\0'作为缺省值
  2. string的字符串末尾(最后一个有效字符的后一个空间)要补上'\0'以兼容C的字符串

三.string类的字符串修改操作接口

1.两个插入字符的重载函数:

 string& insert (size_t pos , char c);      //pos位置插入一个字符
 string& insert (size_t , const char *str); //pos位置插入一个字符串
  • pos位置插入一个字符:string& insert (size_t pos , char c);      
    string& mystring::string::insert (size_t pos , char c)    //pos位置插入一个字符
    {
        assert(pos <= _size);
        if(_size == _capacity)
        {
            reserve(0==_capacity? 4 : 2*_capacity);
        }
        for(int i=_size+1;i>=pos+1 ; i--)    //将pos位置后的所有字符向后移一位
        {                                                                    
            _str[i]=_str[i-1];
        }
        _str[pos]=c;
        _size ++;
        return (*this);
    }

注意:

  1. 扩容时要判断当前容量是否为零,若不为0则按两倍增长的方式扩容
  2. for循环的判断条件中pos是无符号数,表达式进行比较时左边的 i 会发生隐式类型转换转换为无符号数,因此不能让 i 减为-1(-1的补码全为1,换算为无符号数是32位整数的最大值),否则循环会跑死。

  • pos位置插入一个字符串 :string& insert (size_t , const char *str); 
    string& mystring::string::insert (size_t pos, const char *str) //pos位置插入一个字符串
    {
        assert(pos <= _size);
        size_t len = strlen(str);                       //求出待插入的字符串的字符个数
        if(len+_size > _capacity)                       //插入字符串前检查是否要扩容
        {
            reserve(len+_size);
        }
        for(int i = _size+len;i>=pos+len;i--)           //将pos+len后面的字符向后移动len位
        {                                               //(\0 也被移动了)
            _str[i]= _str[i-len];
        }
        for(int i=pos;i<len+pos;i++)                    //将待插入字符串拷贝到pos位置
        {
            _str[i]=str[i-pos];
        }
        _size = len+_size;
        return (*this);
    }

2.在string字符串末尾追加内容的接口

  • 在字符串末尾追加字符的功能接口:void push_back (const char& c); 

通过复用insert即可实现:

    void mystring::string::push_back (const char& c)
    {
        insert(_size,c);
    }

  • 在字符串末尾追加字符串的功能接口:void append(const char * str);     

通过复用insert即可实现:

    void mystring::string::append(const char * str)
    {
        insert(_size,str);
    }

  •   在字符串末尾追加字符的运算符重载:string& operator+=(char c);                

通过复用push_back即可实现:

    string& mystring::string::operator+=(char c)            //在字符串末尾追加字符的功能接口
    {
        push_back(c);
        return (*this);
    }

  • 在字符串末尾追加字符串的运算符重载:string& operator+=(const char * str);      

通过复用append即可实现:

    string& mystring::string::operator+=(const char * str) //在字符串末尾追加字符串的功能接口
    {
        append(str);
        return (*this);
    }

3.在指定位置pos删除n个字符的接口

  •  在pos位置删除n个字符:string& erase(size_t pos, size_t n); 

   删除pos位置后的字符分两种情况讨论

  1.  pos位置后的字符全部删除
  2.  pos位置后的n个字符被删除

STL中规定当n等于-1(string中宏定义为npos)时,删除pos位置后的全部字符

    string& mystring::string::erase(size_t pos=0 , size_t n = -1)      //pos位置删除n个字符
    {
        assert(pos<_size);
        if(n>=_size-pos || -1 == n)                 //删除pos位置后的所有字符
        {
            _size = pos;
            _str[pos]='\0';
            return (*this);
        }
        else
        {                                           //删除pos位置后的n个字符
            for(int i= pos + n ; i<= _size ; i++)   //将pos+n位置后的字符往前挪n位(包括\0)
            {
                _str[i-n]=_str[i];
            }
            _size = _size -n;
            return (*this);
        }
    }

四.string类字符串的字符和子串查找接口

//从第pos个位置查找字符串中查找第一个出现c字符的位置
size_t find(char c,size_t pos =0);


//从第pos个位置查找字符串中第一个出现子串str的位置
size_t find(const char * str , size_t pos =0);
 
                                                            
    size_t mystring::string::find(char c,size_t pos)                  
    {
        assert(pos < _size);
        int i=0;
        for(i=pos;i<_size;i++)
        {
            if(c==_str[i])
            {
                return i;
            }
        }
        return -1;
    }
    size_t mystring::string::find(const char * str, size_t pos)
    {
        assert(pos < _size);
        const char * strpos = strstr(_str+pos,str);
        if(nullptr == strpos)
        {
            return -1;
        }
        return strpos - _str;        //指针相减得到字串出现的位置
    }

五.全局定义的string类字符串比较运算符重载

  • 重载>运算符
bool operator>(const mystring :: string& str1 , const mystring :: string& str2)
{
    int ch1 = 0;
    int ch2 = 0;
    while(ch1<str1.size() && ch2 < str2.size())
    {
        if(str1[ch1] > str2[ch2])
        {
            return true;
        }
        else if(str1[ch1]<str2[ch2])
        {
            return false;
        }
        else
        {
            ch1++;
            ch2++;
        }
    }
    return ch1==str1.size()? false : true;
}

注意:

当while循环结束函数还没有返回时,ch1和ch2的可能值有三种情况:

  1. ch1 == str1.size()      ch2 ! = str2.size()    返回false
  2. ch1 ! = str2.size()      ch2 == str2.size()    返回true
  3. ch1 == str1.size()      ch2  == str2.size()   返回false

  • 重载==运算符
bool operator==(const mystring :: string& str1 , const mystring :: string& str2)
{
    int ch1 =0;
    int ch2 =0;
    while(ch1<str1.size() && ch2 < str2.size())
    {
        if(str1[ch1]!= str2[ch2])
        {
            return false;
        }
        else
        {
            ch1++;
            ch2++;
        }
    }
    return ch1==ch2? true : false;
}

  • 其余的比较运算符重载可以通过复用实现
bool operator>=(const mystring :: string& str1 , const mystring :: string& str2)
{
    return (str1 > str2) || (str1 == str2);
}
bool operator<(const mystring :: string& str1 , const mystring :: string& str2)
{
    return !(str1 >= str2);
}
bool operator<=(const mystring :: string& str1 , const mystring :: string& str2)
{
    return !(str1 > str2);
}

六.全局用于string类的流插入和流提取运算符重载

std :: ostream & operator<<(std :: ostream& cout , const mystring :: string& str )
{
    int i =0;
    for(i=0;i<str.size();i++)
    {
        cout << str[i];
    }
    return cout;
}
std :: istream & operator>>(std::istream & cin , mystring :: string & str)
{
    char ch = cin.get();
    while(ch != '\n')
    {
        str += ch ;
        ch = cin.get();
    }
    return cin;
}

模拟实现代码:

#include<iostream>
#include<cstring>
#include <assert.h>
using std :: ostream;
using std :: istream;
using std::cout;
using std::cin;
using std::endl;
//只要不涉及寻址,一定要注意编译器的顺序编译机制

namespace mystring
{



    class string
    {
        public:
            typedef char * iterator; 
            typedef const char* const_iterator;



            string(const char* nstr);                  //类中四个重要的默认成员函数
            string(const string& nstr);
            ~string();
            string& operator=(string nstr);

            
            void push_back (const char& c);            //在字符串末尾追加字符的功能接口
            void append(const char * str);             //在字符串末尾追加字符串的功能接口
            string& operator+=(char c);                //在字符串末尾追加字符的功能接口
            string& operator+=(const char * str);      //在字符串末尾追加字符串的功能接口
            string& insert (size_t pos , char c);      //pos位置插入一个字符
            string& insert (size_t , const char *str); //pos位置插入一个字符串
            string& erase(size_t pos, size_t n);       //pos位置删除n个字符




            void reserve (size_t newcapacity);         //扩容接口
            void resize(size_t newsize,const char c);  //调整有效数字个数的接口(多出的有效 
                                                       //字符用c填补)




            void copyswap(string &nstr);               //复用交换函数的接口
            iterator begin();                          //string类用于获取迭代器的接口
            iterator end();
            const_iterator begin()const;
            const_iterator end()const;
            const char * C_str()const;                 //用于返回C类型字符串的函数
            char & operator[](int pos);                //用于返回pos下标字符的引用的[]重载
            const char & operator[](int pos) const;     
            size_t size() const;                       //获取有效字符个数size和容量的接口
            size_t capacity() const;
            size_t find(char c,size_t pos =0);         //从第pos个位置查找字符串中第一个出 
                                                       //现c字符的位置
            size_t find(const char * str , size_t pos =0);  //从第pos个位置查找字符串中第一 
                                                            //个出现子串str的位置






        private:
            char * _str;
            size_t _size;
            size_t _capacity;
    };

    
    
    template <typename T>
    void myswap (T& e1 , T&e2)
    {
        T tem = e1;
        e1 = e2;
        e2 =tem;
    }
    void mystring::string::copyswap(string & nstr)
    {
        myswap(_str,nstr._str);
        myswap(_size,nstr._size);
        myswap(_capacity,nstr._capacity);
    }
    const char * mystring::string::C_str() const
    {
        return _str;
    }
    

    mystring::string::string(const char* nstr = "")  //缺省值用于构造空字符串(会完成'\0'的 
                                         //拷贝)(注意缺省参数只能写在声明和定义其中一个之中)
    :_size(strlen(nstr))                             //strlen函数中有关于空指针的断言,所以 
                                                     //构造函数中无须进行空指针判断
    ,_capacity (_size)
    {                          
        _str = new char[_capacity+1];                // +1是为了保存'\0'(不计入容量和有效字 
                           //符),同时保证_str不为空指针(对象只要创建出来就一定维护一块堆空间)
        strcpy(_str,nstr);
    }
    // mystring::string::string(const string& nstr)  //非复用式写法
    // :_size(nstr._size)
    // ,_capacity(nstr._capacity)
    // {
    //     _str = new char[_capacity+1];             // +1是为了保存'\0'(不计入容量和有效 
                                                     //字符),同时保证_str不为空指针
    //     strcpy(_str,nstr._str);
    // }
    mystring::string::string(const string& nstr)     //复用构造函数完成拷贝构造
    :_str (nullptr)                                  //防止tem中_str作为野指针被释放
    ,_size(0)
    ,_capacity(0)
    {
        string tem(nstr._str);                       //拷贝构造拷贝的是不含'\0'的有效字符
        this->copyswap(tem);                         //为了方便阅读加上this指针
    }


    // string& mystring::string::operator=(const string& nstr)
    // {
    //     if(this != &nstr)                             //判断重载操作数是否为同一个对象
    //     {
    //         char * tem = new char[nstr._capacity+1];  // +1是为了保存'\0'(不计入容量和 
                                                         //有效字符)
    //         strcpy(tem,nstr._str);
    //         delete[] _str;
    //         _str = tem;
    //         _size = nstr._size;
    //         _capacity = nstr._capacity;
    //     }
    //     return *this;
    // }
    string& mystring::string::operator=(string nstr)     //与直接交换对象作对比
    {
        copyswap(nstr);
        return (*this);
    }
    mystring::string::~string()
    {
        if(_str)
        {
            delete[] _str;
            _str=nullptr;
        }
        _size=0;
        _capacity=0;
    }




    mystring::string::iterator mystring::string:: begin()
    {
        return _str;
    }
    mystring::string::iterator mystring::string::end()
    {
        return _str+_size; 
    }
    mystring::string::const_iterator mystring::string::begin()const
    {
        return _str;
    }
    mystring::string::const_iterator mystring::string::end()const
    {
        return _str+_size;
    }




    char &  mystring::string::operator[](int pos)
    {
        assert(pos<_size);                                 //越界报警
        return _str[pos];
    }
    const char &  mystring::string::operator[](int pos) const
    {
        assert(pos<_size);
        return _str[pos];
    }


    size_t mystring::string::size() const
    {
        return _size;
    }
    size_t mystring::string::capacity() const
    {
        return _size;
    }






    void mystring::string::reserve (size_t newcapacity)             //扩容接口
    {
        if(newcapacity > _capacity)
        {
            char * tem = new char[newcapacity+1];                   // +1是为了保存'\0'
            strcpy(tem,_str);
            delete[]_str;
            _str = tem;
            _capacity = newcapacity;
        }
    }
    void mystring::string::resize(size_t newsize,const char c = '\0') //调整有效数字个数的 
                                                             //接口(多出的有效字符用c填补)
    {
        if(newsize > _capacity)
        {
            reserve(newsize);
        }
        while(newsize > _size)
        {
            _str[_size] = c;
            _size ++;
        }
        _size = newsize;
        _str[_size]='\0';
    }









    // void mystring::string::push_back (const char& c)             //在字符串末尾追加字符 
                                                                    //的功能接口
    // {
    //     if(_size == _capacity)                                   //检查是否需要增容
    //     {
    //         reserve((0==_capacity? 4 : 2*_capacity));            //注意增容前判断容量是 
                              //否为零,为了减少后续可能的增容次数,这里按照两倍扩大的方式增容
    //     }
    //     _str[_size]=c;
    //     _size++;
    //     _str[_size]='\0';                                        //记得在末尾有效字符后 
                                                                    //面补上'\0'
    // }

    void mystring::string::push_back (const char& c)
    {
        insert(_size,c);
    }
    // void mystring::string::append(const char * str)
    // {
    //     size_t temsize = strlen(str)+_size;
    //     if(temsize > _capacity)
    //     {
    //         reserve(temsize);
    //     }
    //     strcpy(_str + _size , str);                              //追加字符串
    //     _size = temsize;
    // }
    void mystring::string::append(const char * str)
    {
        insert(_size,str);
    }
    string& mystring::string::operator+=(char c)           //在字符串末尾追加字符的功能接口
    {
        push_back(c);
        return (*this);
    }
    string& mystring::string::operator+=(const char * str) //在字符串末尾追加字符串的功能接口
    {
        append(str);
        return (*this);
    }

    string& mystring::string::insert (size_t pos , char c)      //pos位置插入一个字符
    {
        assert(pos <= _size);
        if(_size == _capacity)
        {
            reserve(0==_capacity? 4 : 2*_capacity);
        }
        for(int i=_size+1;i>=pos+1 ; i--)                     //注意细节:隐式类型转换
        {
            _str[i]=_str[i-1];
        }
        _str[pos]=c;
        _size ++;
        return (*this);
    }
    string& mystring::string::insert (size_t pos, const char *str) //pos位置插入一个字符串
    {
        assert(pos <= _size);
        size_t len = strlen(str);
        if(len+_size > _capacity)
        {
            reserve(len+_size);
        }
        for(int i = _size+len;i>=pos+len;i--)
        {
            _str[i]= _str[i-len];
        }
        for(int i=pos;i<len+pos;i++)
        {
            _str[i]=str[i-pos];
        }
        _size = len+_size;
        return (*this);
    }
    string& mystring::string::erase(size_t pos=0 , size_t n = -1)     //pos位置删除n个字符
    {
        assert(pos<_size);
        if(n>=_size-pos || -1 == n)
        {
            _size = pos;
            _str[pos]='\0';
            return (*this);
        }
        else
        {
            for(int i= pos + n ; i<= _size ; i++)
            {
                _str[i-n]=_str[i];
            }
            _size = _size -n;
            return (*this);
        }
    }














    size_t mystring::string::find(char c,size_t pos)    //查找字符串中第一个出现c字符的位置
    {
        assert(pos < _size);
        int i=0;
        for(i=pos;i<_size;i++)
        {
            if(c==_str[i])
            {
                return i;
            }
        }
        return -1;
    }
    size_t mystring::string::find(const char * str, size_t pos)
    {
        assert(pos < _size);
        const char * strpos = strstr(_str+pos,str);
        if(nullptr == strpos)
        {
            return -1;
        }
        return strpos - _str;
    }


}


//  str1  abc
//  str2  ab

//全局的stream对象的比较运算符重载
bool operator>(const mystring :: string& str1 , const mystring :: string& str2)
{
    int ch1 = 0;
    int ch2 = 0;
    while(ch1<str1.size() && ch2 < str2.size())
    {
        if(str1[ch1] > str2[ch2])
        {
            return true;
        }
        else if(str1[ch1]<str2[ch2])
        {
            return false;
        }
        else
        {
            ch1++;
            ch2++;
        }
    }
    return ch1==str1.size()? false : true;
}

bool operator==(const mystring :: string& str1 , const mystring :: string& str2)
{
    int ch1 =0;
    int ch2 =0;
    while(ch1<str1.size() && ch2 < str2.size())
    {
        if(str1[ch1]!= str2[ch2])
        {
            return false;
        }
        else
        {
            ch1++;
            ch2++;
        }
    }
    return ch1==ch2? true : false;
}
bool operator>=(const mystring :: string& str1 , const mystring :: string& str2)
{
    return (str1 > str2) || (str1 == str2);
}
bool operator<(const mystring :: string& str1 , const mystring :: string& str2)
{
    return !(str1 >= str2);
}
bool operator<=(const mystring :: string& str1 , const mystring :: string& str2)
{
    return !(str1 > str2);
}




//全局的stream对象的流插入,流提取运算符重载
std :: ostream & operator<<(std :: ostream& cout , const mystring :: string& str )
{
    int i =0;
    for(i=0;i<str.size();i++)
    {
        cout << str[i];
    }
    return cout;
}
std :: istream & operator>>(std::istream & cin , mystring :: string & str)
{
    char ch = cin.get();
    while(ch != '\n')
    {
        str += ch ;
        ch = cin.get();
    }
    return cin;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/193966.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SSM项目-小说网站

目录 设计目标 需求分析 网站主页 用户注册 1、需求分析 2、数据库设计 3、生成验证码 4、数据加密 1、MD5 2、BCrypt加密 5、数据交换格式 用户登录 找回密码 新用户注册 邮件发送 检测登录状态 书架功能 查看书架 添加书籍进入书架 删除书架上的书籍 获…

kafka在zookeeper中存储结构

1、存储结构图 2、ZooKeeper命令 ZooKeeper -server host:port cmd args stat path [watch] set path data [version] ls path [watch] delquota [-n|-b] path ls2 path [watch] setAcl path acl setquota -n|-b val…

Verticle-align

1.verticle-align的官方解释及所产生的疑问 1.1 vertical-align的官方解释 vertical-align会影响 行内块级元素 在一个 行盒 中垂直方向的位置 【这里有重点词汇&#xff0c;一个行盒&#xff0c;行内块元素&#xff0c;为什么不包括块元素呢&#xff0c;因为块元素是独占一行…

TOP10:餐饮店设计排行榜(2023年最新排名)

随着我国经济不断的高速发展&#xff0c;自13年以来&#xff0c;大众化餐饮市场呈现良好发展趋势&#xff0c;已由13年的2.64万亿增长到3.96万亿&#xff0c;增长率为10.7%&#xff0c;预计2017年到2022年增长速度为9.9%&#xff0c;达到6.28万亿。其中中餐主题餐饮占比维持在8…

JVM 基础 - Java 类加载机制

Java 类加载机制类加载器的分类类加载机制类加载器的分类 如果有必要&#xff0c;我们还可以加入自定义的类加载器。因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件&#xff0c;因此如果编写了自己的ClassLoader&#xff0c;便可以做到如下几点&…

django-rest-framework框架总结之View视图之APIView、GenericAPIView、视图集ViewSet

APIView APIView 是 REST framework 提供的所有视图的基类&#xff0c;继承自Django的View父类。支持认证、限流、授权等功能。 rest_framework.views.APIViewAPIView 与 View 的不同之处在于&#xff1a; 传入到视图方法中的是 REST framework 的 Request 对象&#xff0c;…

Linux gcc和gdb的使用

gcc/g编译器的使用 gcc如何使用 语法&#xff1a; gcc [选项] 编译文件 功能&#xff1a; 用于编译C语言程序&#xff0c;编译C程序使用g。 选项&#xff1a; 指令说明-E只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面-S编译到汇编语言不进行汇编和链接…

python设计模式-单例模式,工厂模式

单例模式 单例模式将类的实例化限制为一个对象。 它是一种创建模式&#xff0c;只涉及创建方法和指定对象的一个类。 它提供了创建实例的全局访问点。 如何实现一个单例类&#xff1f; 下面的程序演示了单例类的实现&#xff0c;并多次打印创建的实例。 class Singleton:_…

动态规划(详细解释)

日升时奋斗&#xff0c;日落时自省 目录 1、Fibonacci 2、字符串分割 3、三角矩阵 4、路径总数 5、最小路径和 6、背包问题 7、回文串分割 8、编辑距离 9、不同子序列 10、总结 DP定义&#xff1a; 动态规划是分治思想的延伸&#xff0c;通俗一点来说就是大事化小&a…

高密度 ARM 服务器如何引领“数智时代”发展,打通“智变质变”正循环

并行计算 | 多样性计算 | ARM架构 深度学习 | 高性能计算 | ARM服务器 如今随着算力、高性能计算的快速发展&#xff0c;数字经济已经成为全球经济增长的主引擎。数字经济的快速发展&#xff0c;使得深度学习、数据分析、数据挖掘等技术迅猛发展起来。伴随国家政策东数西算的…

无痕埋点在Android中的实现

无痕埋点在Android中的实现 目标 解决手动打点效率低下问题自动化埋点 本篇技术实现主要是运行是代理&#xff0c;不涉及到插桩技术&#xff0c;不引入插件&#xff0c;对业务影响点最小 技术难点 1. 如何拦截到所有的view的点击事件 view有个setAccessibilityDelegate方…

Day02-带你走进数据分析的世界

文章目录Day02-带你走进数据分析的世界数据分析正在影响我们的工作、生活数据分析和你想象中的一样吗我们应该具备的数据分析能力Day02-带你走进数据分析的世界 数据分析正在影响我们的工作、生活 随着全球经济数字化转型的发展&#xff0c;各行各业都积累了大量的数据。 具有…

微信小程序做全局登录弹窗

需求&#xff1a;在任意需要弹出登录的页面&#xff0c;后台返回需要登录状态码&#xff0c;弹出登录弹窗进行登录&#xff0c;并刷新当前页面 过程&#xff1a;因为微信小程序无法封装一个全局组件通过方法全局调用。因此只能封装一个公共组件&#xff0c;在需要弹窗的页面注册…

Spark入门指南

文章目录什么是SparkSpark学习路线Spark入门指南什么是Spark Apache Spark 是一个开源集群运算框架&#xff0c;最初是由加州大学伯克利分校 AMP 实验室所开发。相对于 Hadoop 的 MapReduce 会在运行完工作后将中间数据存放到磁盘中&#xff0c;Spark 使用了存储器内存运算技术…

SpringMVC之请求与响应

目录 一&#xff1a;设置请求映射路径 1. 环境准备 二&#xff1a;问题分析 三&#xff1a;设置映射路径 四&#xff1a;请求参数 一&#xff1a;设置请求映射路径 1. 环境准备 创建一个Web的Maven项目 pom.xml添加Spring依赖 <?xml version"1.0" encodi…

基于Android的电子影院系统

需求信息&#xff1a; 客户端&#xff1a; 1&#xff1a;用户注册登录&#xff1a;通过手机号码、用户名称以及密码完成用户的注册和登录 2&#xff1a;影院信息&#xff1a;用户可以查看发布的影院信息以及查看影院具体反映的电影信息以及可以查看电影的宣传片&#xff1b; 3&…

Linux - Linux命令大全

阅读前可参考 https://blog.csdn.net/MinggeQingchun/article/details/128547426 一、Linux系统管理 &#xff08;一&#xff09;查看Linux系统版本 1、查看Linux内核版本 1、cat /proc/version&#xff1a;Linux查看当前操作系统版本信息 2、uname -a&#xff1a;Linux查看…

STM32--SPI、I2C、CAND等常用通信外设总线概括

1. SPI SPI是串行外设接口&#xff08; Serial Peripheral Interface&#xff09;的缩写。 SPI&#xff0c;是一种高速的&#xff08;之前做学传输比特115200 112k, 而SPI传输速度为10Mbps&#xff09;&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在芯片的管…

Allegro如何改变线宽操作指导

Allegro如何改变线宽操作指导 用Allegro做pcb设计的时候,改变走线线宽是非常常用的功能,如下图 线宽目前是12mil,需要把线宽改成15mil 具体操作如下 选择Edit选择Change

摆脱银行询证函的烦恼,契约锁推出银行询证函数字化解决方案

近日&#xff0c;中国财政部会同银保监会印发“财会[2022]39号文件”&#xff0c;明确要加快推进银行函证数字化建设。鼓励具备条件的会计师事务所和银行通过银行函证平台&#xff08;包括第三方函证平台和银行自建函证平台&#xff09;开展数字化函证&#xff0c;有效提升函证…