• 笔记草稿。


    #include <iostream>
    #include ".. estalS_utinity.h"
    #include <list>
    #include <vector>
    #include "stdio.h"
    #include <map>

    //代理类,可以默认,就可以用对象数组,成员为指针,可以为0.有copy3件套.代理行为,检测0,
    //什么时候需要写继承.感觉应该必须满足一个条件.就是需要多态.如果不需要多态.就算是is a,关系.也没有必要非整出一个基类.
    //只要继承,就会使用指针来表示多态.只要有指针,就必须用代理类.
    //所以只要继承就必须代理.

    using namespace std;


    class vehicle
    {
    public:
    virtual double weight()=0;
    virtual void start()=0;
    };

    class bike:public vehicle
    {
    public:
    double weight();
    void start();
    };

    class bus:public vehicle
    {
    public:
    double weight();
    void start();
    };

    class car:public vehicle
    {
    public:
    double weight();
    void start();
    };

    double bike::weight()
    {
    return 200;
    }
    void bike::start()
    {

    }

    double bus::weight()
    {
    return 2000;
    }
    void bus::start()
    {

    }


    double car::weight()
    {
    return 400;
    }
    void car::start()
    {

    }

    class pm
    {
    public:
    pm(vehicle*);
    vehicle* getP();
    ~pm();
    private:
    pm();
    pm(const pm&);
    pm operator=(const pm&);
    vehicle * pveh;
    };

    pm::pm(vehicle* _p):pveh(_p){}
    pm::~pm(){delete pveh;}
    vehicle* pm::getP(){return pveh;}


    //一,对于单资源(狭义上就是内存,再狭义就是堆内存)的使用和管理.
    //1,资源的建立和托管必须是一个步骤.2)托管对象必须保证和资源同生死.
    //对于栈内存,.bike mybike1; 对于堆内存.bike * mybike2=new bike();
    //第一种,很可靠.
    //第二种,需要显示维护内存,和保护指针变量.所以引出一条款(effect c++),用对象管理资源.
    //而资源管理对象和资源同生死.就必须保证资源建立和对象建立是原子操作.也是另一条款.
    //并且资管,由于资源入对象是原操,那么资管必须负责资源的delete.
    //1)资管必须负责资源的delete.
    //2)负责delete,也就必须考虑资源copy三函数,构造,赋值,析构.
    //3)资管可以没有默认的构造函数,
    //4)可以直接用方法提供只读的资源地址,供外部使用
    //对于第2条.如果是资源地址copy.资管转化为智能指针类.
    //如果是资源copy.提供正确的构造,赋值,析构.
    //如果是禁止资源copy,构造,赋值,析构.设置为private.
    //如果是资源转移.提供正确的构造,赋值,析构.


    //所以最终对于单资源的资源的使用.在c++中有2种比较可靠的方法.
    //1)栈内存, bike mybike1;
    //2)堆内存,pm mypm(new bike());

    //对于多资源的统一使用和管理.
    //基本是对于含有继承关系的对象而言.没有继承关系,谈不上统一管理.
    //那么必须是管理指针.参考上面分析.必须建立对象.
    //那么必须要求资源有默认的构造函数.

    void showWeight(vehicle * _p)
    {
    cout<<_p->weight()<<endl;
    }

    int main()
    {
    //地址copy,使用智能指针类.
    bike mybike1;
    cout<<"**auto p***"<<endl;
    showWeight(&mybike1);

    //地址copy,使用智能指针类.
    cout<<"**copy p***"<<endl;
    pm_copyP<bike> mypm(new bike());
    pm_copyP<bike> mypm2=mypm;
    pm_copyP<bike> mypm3(new bike());
    mypm3=mypm;

    showWeight(mypm.getP());
    showWeight(mypm2.getP());
    showWeight(mypm3.getP());

    //禁止copy值或地址.使用禁止类.
    cout<<"**forbiden***"<<endl;
    pm_forbidP<bike> mypm4(new bike());
    showWeight(mypm4.getP());
    //pm_forbidP<bike> mypm5=mypm4;//禁止复制,赋值.

    //value copy,使用value-copy类.
    cout<<"**copy value***"<<endl;
    pm_copyValue<bike> mypm5(new bike());
    pm_copyValue<bike> mypm6=mypm5;
    pm_copyValue<bike> mypm7(new bike());
    mypm7=mypm5;

    showWeight(mypm5.getP());
    showWeight(mypm6.getP());
    showWeight(mypm7.getP());

    //转移资源所有权, 使用transforP类. 这个和其他有不同.使用指针必须先判断,指针是否已经转移,为0了.
    cout<<"**transforP***"<<endl;
    pm_transforP<bike> mypm8(new bike());
    pm_transforP<bike> mypm9=mypm8;
    pm_transforP<bike> mypm10(new bike());
    mypm10=mypm8;

    if(mypm8.getP()!=0)
    {
    showWeight(mypm8.getP());
    }
    if(mypm9.getP()!=0)
    {
    showWeight(mypm9.getP());
    }
    if(mypm10.getP()!=0)
    {
    showWeight(mypm10.getP());
    }

    // vehicle* allCar[100]={0};
    //
    // bike mybike1;
    // bus mybus1;
    // car mycar1;
    //
    // allCar[0]=&mybike1;//这里是函数内,如果是外部参数,那么会有悬指针问题.所以条款,对象管理资源很必要.
    // allCar[1]=&mybus1;
    // allCar[2]=new car;//这里必须管理内存.
    //
    //
    // for(int i=0;i!=100;++i)
    // {
    // if(allCar[i]!=0)
    // {
    // cout<< allCar[i]->weight()<<endl;
    // }
    // }

    return 0;
    }

    #ifndef LS_UTINITY_H_INCLUDED
    #define LS_UTINITY_H_INCLUDED
    
    #include <iostream>
    #include <list>
    #include <vector>
    
    using namespace std;
    
    //智能指针
    template<typename T>
    class auto_MyP
    {
    public:
        auto_MyP<T>();
        auto_MyP<T>(T const* _p);
        auto_MyP<T>(const auto_MyP&);
        auto_MyP<T>& operator=(const auto_MyP&);
        T* getP()const;
        ~auto_MyP<T>();
        void del();
    private:
    
        int * count_ref;
        const T* autop;
    };
    
    template<typename T>
    auto_MyP<T>::auto_MyP()
    {
        autop=0x0;
        count_ref=new int(1);
    }
    
    template<typename T>
    auto_MyP<T>::auto_MyP(T const* _p)
    {
        cout<<"p con:"<<_p<<endl;
        autop=_p;
        count_ref=new int(1);
    }
    
    
    template<typename T>
    auto_MyP<T>::auto_MyP(const auto_MyP& _lht)
    {
        autop=_lht.autop;
        ++(*_lht.count_ref);
        count_ref=_lht.count_ref;
    }
    
    template<typename T>
    auto_MyP<T>& auto_MyP<T>::operator=(const auto_MyP& _lht)
    {
        if(this!=&_lht)
        {
            del();
            this->autop=_lht.autop;
            *_lht.count_ref=*_lht.count_ref+1;
            this->count_ref=_lht.count_ref;
        }
        return *this;
    }
    
    template<typename T>
    auto_MyP<T>::~auto_MyP()
    {
        del();
    }
    
    template<typename T>
    void auto_MyP<T>:: del()
    {
        cout<<"false del:"<<*(this->count_ref)<<". add"<<autop<<endl;
        *(this->count_ref)=*(this->count_ref)-1;//前后自增加,就是此语句取值是取+1变量,还是把+1给临时变量,取值去取未+1的符号变量.
    
        if(*(this->count_ref)==0)
        {
            cout<<"del:"<<autop<<endl;
            //if(autop!=0x0)
            //{
                delete autop;
            //}
        }
    }
    
    template<typename T>
    T* auto_MyP<T>::getP()const
    {
        return  const_cast<T*>(autop);
    }
    
    
    
    //Merge sort
    template<typename T>
    list<T> mergeSort(const list<T>& source);
    
    template<typename T>
    list<T> mergeSort(const list<T>& source)
    {
        list<T> ret;
    
        if(source.size()==1)
        {
            ret=source;
        }
        else if(source.size()==2)
        {
            typename list<T>::const_iterator firstit=source.begin();
            T firstvalue=*firstit;
            typename list<T>::const_iterator secondit=++firstit;
            T secondvalue=*secondit;
    
            if(firstvalue<=secondvalue)
            {
                ret=source;
            }
            else
            {
                ret.push_back(secondvalue);
                ret.push_back(firstvalue);
            }
    
        }
        else
        {
            unsigned int count_list=source.size();
            unsigned int modN= count_list%2;
            unsigned int subret=count_list/2;
    
            typename list<T>::const_iterator it=source.begin();
    
            list<T> leftS;
            list<T> rightS;
    
            for(int i=0;i!=subret+modN;++i)
            {
                leftS.push_back(*it);
                ++it;
            }
    
            for(int i=0;i!=subret;++i)
            {
                rightS.push_back(*it);
                ++it;
            }
    
            leftS=mergeSort(leftS);//lefts 传递const 引用,效率和安全,不会改动.返回对象.lefts被copy赋值函数处理.
            rightS=mergeSort(rightS);
    
            typename list<T>::const_iterator lefttop=leftS.begin();
            typename list<T>::const_iterator righttop=rightS.begin();
    
            while(lefttop!=leftS.end() || righttop!=rightS.end())
            {
                // check each top
                if(*lefttop<=*righttop)
                {
                    ret.push_back(*lefttop);
                    ++lefttop;
                }
                else
                {
                    ret.push_back(*righttop);
                    ++righttop;
                }
            }
            if(lefttop!=leftS.end())
            {
                //push no process data
                for(lefttop;lefttop!=leftS.end();++lefttop)
                {
                    ret.push_back(*lefttop);
                }
            }
            else if(righttop!=rightS.end())
            {
                for(righttop;righttop!=rightS.end();++righttop)
                {
                    ret.push_back(*righttop);
                }
            }
            return ret;
        }
    
    
    
        return ret;
    }
    
    
    //
    template<typename T>
    void quickSort(vector<T>& source, int startIndex, int endIndex)
    {
        if(startIndex<endIndex)
        {
            int centerIndex=startIndex;
            for( int i=startIndex+1;i!=endIndex+1;++i)
            {
                if(source[i]<source[centerIndex])
                {
                    T tempT=source[i];
                    for( int j=i-1;j!=centerIndex-1;--j)
                    {
                        source[j+1]=source[j];
                    }
                    source[centerIndex]=tempT;
                    ++centerIndex;
                }
            }
            quickSort(source,startIndex,centerIndex-1);
            quickSort(source,centerIndex+1,endIndex);
        }
    }
    
    
    template<typename T>
    int centerFind(const vector<T>& source,const T& finder)
    {
        int ret=-2;
        int startIndex=0;
        int endIndex=source.size()-1;
        int CenterIndex=startIndex+(endIndex-startIndex)/2;
    
        while(ret==-2)
        {
            if(CenterIndex==startIndex&&startIndex==endIndex)//1个数
            {
                if(source[CenterIndex]==finder)
                {
                    ret=CenterIndex;
                }
                else
                {
                    ret=-1;
                }
            }
            else
            {
                if(source[CenterIndex]==finder)
                {
                    ret=CenterIndex;
                }
                else if(source[CenterIndex]>finder)
                {
                    endIndex=CenterIndex-1;
                    CenterIndex=startIndex+(endIndex-startIndex)/2;
                    if(startIndex>endIndex)
                    {
                        ret=-2;
                    }
                }
                else
                {
                    startIndex=CenterIndex+1;
                    CenterIndex=startIndex+(endIndex-startIndex)/2;
                    if(startIndex>endIndex)
                    {
                        ret=-2;
                    }
                }
            }
        }
        return ret;
    }
    
    template<typename T>
    class pm_copyP{
    public:
        pm_copyP(T* _p);
        pm_copyP(const pm_copyP&);
        pm_copyP& operator=(const pm_copyP&);
        ~pm_copyP();
        T* getP();
    private:
        pm_copyP();
        T* myp;
        int * count_ref;
        del();
    };
    
    template<typename T>
    pm_copyP<T>::pm_copyP(T* _p):myp(_p),count_ref(new int(1)){}
    
    template<typename T>
    pm_copyP<T>::pm_copyP(const pm_copyP& _pm)
    {
        myp=_pm.myp;
        count_ref=_pm.count_ref;
        ++(*count_ref);
    }
    
    template<typename T>
    pm_copyP<T>& pm_copyP<T>::operator=(const pm_copyP& _pm)
    {
        if(&_pm!=this)
        {
            del();
            myp=_pm.myp;
            count_ref=_pm.count_ref;
            ++(*count_ref);
        }
        return *this;
    }
    
    template<typename T>
    pm_copyP<T>::~pm_copyP()
    {
        del();
    }
    
    template<typename T>
    pm_copyP<T>::del()
    {
        --(*count_ref);
        if(*count_ref==0)
        {
            delete myp;
            delete count_ref;
        }
    }
    
    template<typename T>
    T* pm_copyP<T>::getP()
    {
        return myp;
    }
    
    
    template<typename T>
    class pm_forbidP{
    public:
        pm_forbidP(T* _p);
        ~pm_forbidP();
        T* getP();
    private:
        T* myp;
        pm_forbidP();
        pm_forbidP(const pm_forbidP&);
        pm_forbidP& operator=(const pm_forbidP&);
    };
    
    
    template<typename T>
    pm_forbidP<T>::pm_forbidP(T* _p):myp(_p){}
    
    
    template<typename T>
    T* pm_forbidP<T>::getP()
    {
        return myp;
    }
    
    template<typename T>
    pm_forbidP<T>::~pm_forbidP()
    {
        delete myp;
    }
    
    
    template<typename T>
    class pm_copyValue{
    public:
        pm_copyValue(T* _p);
        pm_copyValue(const pm_copyValue&);
        pm_copyValue& operator=(const pm_copyValue&);
        ~pm_copyValue();
        T* getP();
    private:
        T* myp;
        void del();
        pm_copyValue();
    };
    
    template<typename T>
    pm_copyValue<T>::pm_copyValue(T* _p):myp(_p){}
    
    template<typename T>
    pm_copyValue<T>::pm_copyValue(const pm_copyValue& _pm):myp(new T(*_pm.myp)){}
    
    template<typename T>
    pm_copyValue<T>& pm_copyValue<T>::operator=(const pm_copyValue& _pm)
    {
        if(&_pm!=this)
        {
            del();
            myp=new T(*_pm.myp);
        }
        return *this;
    }
    
    template<typename T>
    pm_copyValue<T>::~pm_copyValue()
    {
        del();
    }
    
    template<typename T>
    void pm_copyValue<T>::del()
    {
        delete myp;
    }
    
    template<typename T>
    T* pm_copyValue<T>::getP()
    {
        return myp;
    }
    
    
    
    template<typename T>
    class pm_transforP{
    public:
        pm_transforP(T* _p);
        pm_transforP(pm_transforP&);
        pm_transforP& operator=(pm_transforP&);
        ~pm_transforP();
        T* getP();
    private:
        T* myp;
        void del();
        pm_transforP();
    };
    
    template<typename T>
    pm_transforP<T>::pm_transforP(T* _p):myp(_p){}
    
    template<typename T>
    pm_transforP<T>::pm_transforP(pm_transforP& _pm):myp(_pm.myp)
    {
        _pm.myp=0;//const 怎么可以修改.
    }
    
    
    template<typename T>
    pm_transforP<T>& pm_transforP<T>::operator=(pm_transforP& _pm)
    {
        if(this!=&_pm)
        {
            del();
            myp=_pm.myp;
            _pm.myp=0;//const 怎么可以修改.
        }
        return *this;
    }
    
    template<typename T>
    pm_transforP<T>::~pm_transforP()
    {
        del();
    }
    
    template<typename T>
    void pm_transforP<T>::del()
    {
        if(myp!=0)
        {
            delete myp;
        }
    }
    
    template<typename T>
    T* pm_transforP<T>::getP()
    {
        return myp;
    }
    
    #endif // LS_UTINITY_H_INCLUDED



    关于异常:

    #include <iostream>
    #include <stdexcept>
    
    using namespace std;
    //c++,实在经验不足.感觉只能是,使用某些函数,又不想每次都检测是否返回正确.那么抛出错误.程序结束.
    //感觉还不如返回错误代码呢.
    
    int dev(int a,int b);
    
    int main()
    {
        int result=0;
        try
        {
            result=dev(3,1);
        }
        catch(exception &e)
        {
            //提示错误,保存关键数据,程序退出
            cout<<e.what()<<endl;
            return -1;
        }
        cout<<result<<endl;
    
    
        return 0;
    }
    
    int dev(int a,int b)
    {
        if(b==0)
        {
            throw runtime_error("b is zero");
        }
        else if(b==1)
        {
            throw logic_error("b can not be 1");
        }
        else
        {
            return a/b;
        }
        return 0;
    }

     关于类的数据成员和参数问题。以及const。

    1)类的data member.
    如果是内置类型或类的值类型,语义就是局部数据,const语义就是,在类内,一个局部常量.
    如果是内置类型或类的指针或引用类型,语义就是局部的指针,指向外部数据,const语义就是,在类内,不可通过此指针修改外部数据.
    如果是内置类型或类的智能指针类型.语义就是局部数据,但里面有指针指向外部数据.const语义就是,在类内,不可通过此局部数据中的指针修改外部数据.
    (可以完全代替第二种,只是size为8,而第2中size是4(32system)).
    如果是内置类型或类的智能指针的指针或引用类型.语义就是很大概率是你想的的太复杂了.请退化为第3种.智能指针就是为了自动释放内存.
    再保存它的指针,又把问题解决方案变成了问题本身.餐巾纸的作用就是为了吃饭时,让衣服更干净.为了方便拿东西.又套一个外套,还不如拿掉餐巾纸.
    但是构造函数的参数应该使用 智能指针的reference,这个时候智能指针当成一般类处理.智能指针本质就是一个类了.

    总结:
    值还是智能指针(指针),还是引用.
    从数据库讲,

    一个字段不是另一个表的key。那么就是值。否则就是引用。如果表不存在这个字读。那么就是用方法返回数据(查询其他表)

    const还是非const?
    可修改用非const.否则用const.
    对于智能指针,指针不可修改用 const shared_ptr<T>,指针所指的数据不可修改用shared_ptr<const T>.

    从数据库讲。如果一个字段设置了触发器,字段是只读了。那么类中。一定要是const。


    2)类的constructor的参数.
    如果参数是内置类型或类的值类型,语义就是会创建一个原数据的副本,压入函数体.const语义就是,此参数的数据不可修改.但可以赋值给const或非const.
    如果参数是内置类型或类的指针或引用类型,语义就是引用原数据,压入原数据的指针到函数体.const语义就是此地址的指向不可修改.
    如果参数是内置类型或类的智能指针类型.语义就是会创建一个原数据(包含一个指针)的副本,压入函数体.const语义就是,此参数的数据不可修改.也就是里面的地址的指向不可修改.

    时钟周期
     
           时钟周期也称为振荡周期,定义为时钟脉冲的倒数(时钟周期就是单片机外接晶振的倒数,例如12M的晶振,它的时钟周期就是1/12us),是计算机中的最基本的、最小的时间单位。
           在一个时钟周期内,CPU仅完成一个最基本的动作。时钟脉冲是计算机的基本工作脉冲,控制着计算机的工作节奏。时钟频率越高,工作速度就越快。
     
           8051单片机把一个时钟周期定义为一个节拍(用P表示),二个节拍定义为一个状态周期(用S表示)。

    机器周期
     
           计算机中,常把一条指令的执行过程划分为若干个阶段,每一个阶段完成一项工作。每一项工作称为一个基本操作,完成一个基本操作所需要的时间称为机器周期。8051系列单片机的一个机器周期由6个S周期(状态周期)组成。 一个S周期=2个节拍(P),所以8051单片机的一个机器周期=6个状态周期=12个时钟周期。
     
           例如外接24M晶振的单片机,他的一个机器周期=12/24M 秒;

    指令周期
     

        执行一条指令所需要的时间,一般由若干个机器周期组成。指令不同,所需的机器周期也不同。

    int main(void)
    {
    char buf[10];
    int n = read(STDIN_FILENO, buf, 10);
    write(STDOUT_FILENO, buf, n);
    return 0;
    }

    输入字符,回车后。。。。。

    少于等于10个ok。大于10个。后续的字符,和回车键都还在标准输出中,会认为用户敲入了命令。

     关于开发整体流程。

    //对于开发的流程,个人倾向,先建模,后建表.再实际建立class.
    //因为先建立表,可以更快理清类之前细节.因为建类的时候需要考虑实际数据的存放问题.
    //建立类的时候,发现问题.也可以修改表.
    //而建立好类,不满足表,改类就麻烦.
    //再次.表的话更直观,可以先不考虑细节.从整体掌握模型的数据流是否正确.
    //甚至,类中犯的错误的设计,在表中就不太会出现.如员工,和职务.表明显会有好几个.一个员工表,几个不同职务表.
    //而类,可能会设计为一个类.建模错误,会导致表设计不符合表设计范式.
    //但是设计表的时候也可以考虑一下类.是否需要多一个表,来表现包含关系.或继承关系.

    再一次卡在设计流程上了。

    继续卡在无数据库设计上。

    有数据库设计,数据存放问题不用考虑。而无数据库,放在那里,用 vector 对象还是指针,总是感觉设计不好。用vector或智能指针。

    应该还是基于分析后。关系型数据设计开路(好理解,也很熟悉),数据存放问题的话。去掉表的外键,放入外键所在的表。用vector直接存放对象。,vector自己离开作用域会自动析构。析构会调用成员的析构函数并释放堆空间。完美啊。

    可以先省去内部中其他类的集合。从上往下设计下来就好,下级设计好了。再返回上级,使用下级的初始化函数,来修改上级的初始化函数或其它初始化的地方。

    这样设计了数据的流向后,再从面向对象的思维,设计行为。来给数据流向取个名字。

    对象间的数据存放问题。

    1)如果原本数据成员都不多。那么偏向一方(其中有确定数据属于的那方)。

    2)用map存储数据。类方法提供对map的真删改,查, 类本身或管理类提供逻辑,调用增删改,特别注意逻辑中含删除的操作。

    单个数据直接放栈,如果太大用智能指针。如果是不确定的多个数据或者多个大数据。用vector就好了。甚至单个大数据也可以用vector,vector自己离开作用域会自动析构。析构会调用成员的析构函数并释放堆空间。完美啊。

    定义参数值用全局const。但如果是状态返回值或者作为参数可以用enum.这样就可以限定返回的数据范围。但是枚举不能设定数据类型。比如int_8,所以在网络编程需要固定长度的时候又很尴尬。

    模型设计的一点想法,

    看了下网狐。有个设计,类之间的包含关系 ,不放指针,或智能指针。

    直接放一个key.

    所以设计的时候,

    1.可以先设计一个对象,包含属性和方法。

    2.再设计一个管理类,包含一个当前key 的最大小(根据情况,是先进先出,还是先进后出)值。 用int 记录。

    一般可以用int ,取int最大值为默认值,表示下次插入的key。插入的时候用这个做key.并·--,  删除的时候,看看要删除的是不是等于 key-1.如果是,++。 所以用map的key,来当前数据库的外键。

    好处是避免了指针的坏处。指针可能有移动操作,也比较危险。而用 key,自然的多。终于解决了这个疑问。

    封装的一个含义就是类的某个或几个数据是状态数据。他的改变只由行为(方法)来改变。并提供只读的查看。

    服务端和客户端同步开发。

    客户端的初始化行为放入main中(之后可以由网络模块发送消息,获得消息,并回调这些方法)。

    客户端的动作逻辑封装成方法(之后由网络模块发送消息,获得消息,并回调这些方法)

    服务端是一个完备的系统,应该是一个可以自检,自运行的系统。客户端只是通过发送消息,改变服务端的自运行的过程中的状态值。

    c#

    RoomInfo selectroom = rooms.Where(s => s.room_id == (SByte)this.comboBox1.SelectedValue).Single();

    where 相当于里面一个bool函数。where里面已经回调了()里面的函数。并根据bool值来决定是否加入结果集合。

    c++ get .set 生成器。

    List<string> inputcode = new List<string>();
                List<string> outputcode = new List<string>();
    
                string className = this.textBox3.Text.Trim();
    
                inputcode = this.textBox1.Text.Split(new string[] {"
    "}, StringSplitOptions.RemoveEmptyEntries).ToList();
    
                for(int i=0;i<inputcode.Count;++i)
                {
                    
                    string[] eachline=inputcode[i].Split(new string[] {" ",";"}, StringSplitOptions.RemoveEmptyEntries);
    
                    if(eachline.Count()==2)
                    {
                        string type=eachline[0];
                        string name=eachline[1];
    
                        this.textBox2.Text+=type+" "+className+"::Get"+name+"()"+System.Environment.NewLine;
                        this.textBox2.Text+="{"+System.Environment.NewLine;
                        this.textBox2.Text += "   " + "return " + name + ";" +System.Environment.NewLine;
                        this.textBox2.Text+="}"+System.Environment.NewLine;
    
                        this.textBox2.Text+="void "+className+"::Set"+name+"("+type+" _"+name+")"+System.Environment.NewLine;
                        this.textBox2.Text+="{"+System.Environment.NewLine;
                        this.textBox2.Text += "   " + name + "=_" + name + ";" + System.Environment.NewLine;
                        this.textBox2.Text+="}"+System.Environment.NewLine;
    
                        this.textBox2.Text=this.textBox2.Text.Replace("std::","");
    
    
                    }
    
                }

    目的:有时候有些情况比较复杂,写完了代码。也没法确定是否完全正确。画图感觉比较复杂,只能靠测试。这个时候使用状态机分析法。就能比较好。
    步骤:先写出初始行为,和输入行为,以及输入行为对应的猜想的动作,通过猜想的动作,对状态的更改,判断状态是否合理,来验证行为是否正确。
    每次集合中所有状态和行为一一匹配。有新状态。就保存。
    之后每次用新状态和所有行为一一匹配。直到没有新状态为止。

    初始状态: r_ok,s_ok,e_in;

    输入行为和对应猜想动作()
    1)recv_again. r_ok
    2)recv_close. r_close,cancel event
    3)recv_error. del
    4)send_ok. s_ok ,1)close:yes,block:yes=>s_ok 2)close:yes,block:no => s_ok 3) colse:no,block:yes=>s_ok. e_in. 4)close:no,block:no=>s_ok
    5)send_block. s_block,mod e_out
    6)send_err. del


    初始状态: 下和所有输入行为产生的新状态
    1:r_ok,s_ok,e_in;

    1-1)=>
    1-2)=>r_close,s_ok
    1-3)=>del
    1-4)=>r_ok,s_ok,e_in
    1-5)=>r_ok,s_block,e_out
    1-6)=>del
    状态应该正确。所以猜想行为暂时正确。
    在用得到的新状态,和所有行为一一匹配
    1:r_close,s_ok
    2:r_ok,s_block,e_out

    1-1)=>不可能会存在的行为
    1-2)=>不可能会存在的行为
    1-3)=>不可能会存在的行为
    1-4)=>
    1-5)=>r_close,s_block, e_out
    1-6)=>del

    2-1)=>不可能会存在的行为
    2-2)=>不可能会存在的行为
    2-3)=>不可能会存在的行为
    2-4)=>
    2-5)=>
    2-6)=>del

    又得到1种新状态。所有状态是2×2×2.现在只有4种。
    在用得到的新状态,和所有行为一一匹配
    1:r_close,s_block, e_out
    1-1)=>不可能会存在的行为
    1-2)=>不可能会存在的行为
    1-3)=>不可能会存在的行为
    1-4)=>
    1-5)=>
    1-6)=>del


    无任何新状态。估算下是否正确
    估算下,还有剩下4种是什么情况。
    1:r_ok,s_ok,e_in;
    2:r_ok,s_block,e_out
    3:r_close,s_ok
    4:r_close,s_block, e_out
    哦。因为s_ 和e_只能组合成2种。
    所以就是4种。
    所以我们得到了全部状态。再验证一下猜想行为就好了。
    虽然很烦琐,但是可以验证遗漏的情况。

    测试epoll的时候,客户端可以线程10个内。但是开多点socket ,100左右。这样简陋的环境。也可以测试高流量,模拟高并发。注意看服务的发送和接受是否相同大小,如果是echo测试。

    还要看客户端的接受。是否有重传现象。如果客户端接收的明显比服务端发送的多。

    如何测试epoll的代码效率。

    可以简单点。客户端开1000个socket.200毫毛休息一次。说明1秒有5000条信息处理。每条信息64B。发送速度就是300/kB.

    服务端,每条信息的处理休息1毫秒。说明1秒处理1000条。但是测试还是不准。所以可以调整下。用netstat 命令查看。使得接受数据越来越多为好。说明程序处理慢。

    这样就可以开始优化了。单线程可以优化批量发送,批量处理。

    多线程就可以开始队列,新线程处理。多线程的一般特征是网路是没有问题的。接受快,发送快。因为单独线程再处理io。但是如果程序差,那么内存会原来越小。因为网络的数据全部拉到内存中去了。但是又处理不过来。

  • 相关阅读:
    阿里在线笔试总结
    JAVA断言使用
    小心人员中的薄弱点
    Ubuntu 12.04.4 LTS下linphone-android编译记录
    Java基础:异常的限制
    Java基础:小知识点
    js正则表达式中和\
    Maven管理下Struts、Hibernate编译过程中配置文件缺失导致的“No result defined for action”和getSession()发生“NullPointerException”的解决办法
    Java基础:final关键字
    Java基础:复用类
  • 原文地址:https://www.cnblogs.com/lsfv/p/6042403.html
Copyright © 2020-2023  润新知