zoukankan      html  css  js  c++  java
  • 酒鬼随机漫步(一个矢量类)

    摘要: 阅读全文

    这是一个定义的一个矢量类, 然后用矢量类模拟一个酒鬼的随机漫步

    问题很简单, 实现也不麻烦, 但是这个小程序却可以呈现出许多语法知识。而且代码风格也不错,因此保存在了这篇博客中。

     

    建议:

           1. 类的声明以及函数的声明放到一个文件夹内, 并且在一些必要的地方加上注释!

       2. 函数的实现放到另一个文件内。

           3. 将程序要具体解决的问题放到另外的一个文件里。(详见代码!)

    好处: 把类的接口和实现细节分离开, 易于更改某个函数的功能。

              把函数的声明和定义分开, 提高代码可读性。

              把类的声明和定义 与 要解决的问题分开, 提高,类的重用性!

                                             定义类(声明类内的函数)

    // vect.h -- Vector class with <<, mode state
    #ifndef VECTOR_H_
    #define VECTOR_H_
    #include <iostream>
    namespace VECTOR
    {
        class Vector
        {
        public:
            enum Mode{RECT, POL};
            // RECT for rectangular, POL for Polar modes
        private:
            double x;        // horizontal value
            double y;        // vertical value
            double mag;      // length of vector in degrees
            double ang;// direction of vector in degrees
               Mode mode;  // private methods for setting values
            void set_mag();
            void set_ang();
            void set_x();
            void set_y();
        public:
            Vector();
            Vector(double n1, double n2, Mode form = RECT);
            void reset(double n1, double n2, Mode form = RECT);
            ~Vector();
            double xval() const {return x; }        // report x value
            double yval() const {return y; }        // report y value
            double magval() const {return mag; }    // report magnitude
            double angval() const {return ang; }    // report angle
            void polar_mode();                      // set mode to POL
            void rect_mode();                       // set mode to RECT
            // operator overloading
            Vector operator+(const Vector & b) const;
            Vector operator-(const Vector & b) const;
            Vector operator-()const;
            Vector operator*(double n) const;
            // friends
            friend Vector operator*(double n, const Vector & a);
            friend std::ostream & operator<<(std::ostream & os, const Vector & v);
        };
    }    // end namespace VECTOR
    #endif

     上面代码涵盖了许多关于类的基础知识:  名称空间与作用域 ,  实现类内部常量的方法,  构造函数, 析构函数, 运算符重载, 友元函数, 关于多种实现方法等。

    PS: 实现类内部常量的方法: (1)枚举类型。 (2) static const int  常量

            运算符重载: 注意操作数的顺序。

                                               

                                                               函数定义

    // vect.cpp -- methods for the Vector class 
    #include <cmath>
    #include "vect.h"  // include <iostream>
    using std::sqrt;
    using std::sin;
    using std::cos;
    using std::atan;
    using std::atan2;
    using std::cout;
    
    namespace VECTOR
    {
        // compute degree in one radian
        const double Rad_to_deg = 45.0/atan(1.0);
        // should be about 57.2957795130823
    
        // private methods
        // calculate magnitude from x and y
        void Vector::set_mag()
        {
            mag = sqrt(x*x + y*y);
        }
    
        void Vector::set_ang()
        {
            if(x == 0.0&& y== 0.0)
                ang = 0.0;
            else 
                ang = atan2(y, x);
        }
    
        //set x from polar coordinate
        void Vector::set_x()
        {
            x = mag*cos(ang);
        }
    
        //set y from polar coodinate
        void Vector::set_y()
        {
            y = mag * sin(ang);
        }
        // public methods
        Vector::Vector() // default constructor
        {
            x = y = mag = ang = 0.0;
            mode = RECT;
        }
    
        // construct vector from rectangular coordinates if form is r
        // (the default) or else from polar coordinates if form is p
        Vector::Vector(double n1, double n2, Mode form)
        {
            mode = form;
            if(form == RECT)
            {
                x = n1;
                y = n2;
                set_mag();
                set_ang();
            }
            else if(form == POL)
            {
                mag = n1;
                ang = n2/Rad_to_deg;
                set_x();
                set_y();
            }
            else
            {
                cout << "Incorrect 3rd argument to Vector() --";
                cout << "vector set to 0.0";
                mode = RECT;
            }
        }
    
        // reset vector from rectangular coodinates if form is
        // RECT (the default) or else form polar coordinates if
        // form is POL
        void Vector::reset(double n1, double n2, Mode form)
        {
            mode = form;
            if(form == RECT)
            {
                x = n1;
                y = n2;
                set_mag();
                set_ang();
            }
            else if (form == POL)
            {
                mag = n1;
                ang = n2/Rad_to_deg;
                set_x();
                set_y();
            }
            else
            {
                cout << "Incorrect 3rd argument to Vector() -- ";
                cout <<"vector set to 0.0
    ";
                x = y = mag = ang = 0.0;
                mode = RECT;
            }
        }
    
        Vector::~Vector() // destructor
        {
        }
    
        void Vector::polar_mode()  //set to polar mode
        {
            mode = POL;
        }
    
        void Vector::rect_mode()// set to rectangular mode
        {
            mode = RECT;
        }
    
        // operator overloading
        // add two Vectors
        Vector Vector::operator+(const Vector & b) const
        {
            return Vector(x + b.x, y + b.y);
        }
    
        //subtract Vector b from a 
        Vector Vector::operator-(const Vector & b) const
        {
            return Vector(x-b.x, y-b.y);
        }
    
        // reverse sign of Vector
        Vector Vector::operator-() const
        {
            return Vector(-x, -y);
        }
    
    // multiply vector by n
        Vector Vector::operator*(double n) const
        {
            return Vector(n*x, n*y);
        }
    
        // friend methods
        // multiply n by Vector a
        Vector operator*(double n, const Vector & a)
        {
            return a * n;
        }
    
        //display rectangular coordinates if mode is RECT
        // else display polar coordinates if mode is POL
        std::ostream & operator<<(std::ostream & os, const Vector & v)
        {
            if (v.mode == Vector::RECT)
                os << "(x,y) = (" << v.x << ", " << v.y << ")";
            else if (v.mode == Vector::POL)
            {
                os << " (m,a) = (" << v.mag << ", "
                    << v.ang*Rad_to_deg << ")"; 
            }
            else
                os << "Vector object mode is invalid";
            return os;
        }
    }  // end namespace VECTOR

                                                               具体解决的问题

    // randwalk.cpp -- using the Vector class
    // compile with the vect.cpp file
    #include <iostream>
    #include <cstdlib> // rand(), srand() pototypes
    #include <ctime>   // time() pototype
    #include "vect.h"
    
    int main()
    {
        using namespace std;
        using VECTOR::Vector;
        srand(time(0));   // seed random-number generator
        double direction;
        Vector step;
        Vector result(0.0, 0.0);
        unsigned long steps = 0;
        double target;
        double dstep;
        cout << "Enter target distance (q to quit): ";
        while(cin >> target)
        {
            cout << "Enter step length: ";
            if(!(cin>>dstep))
                break;
    
            while(result.magval() < target)
            {
                direction = rand()%360;
                step.reset(dstep, direction, Vector::POL);
                result = result + step;
                steps++;
            }
    
            cout << "After " << steps <<" steps, the subject "
                     "has the following location:
    ";
            cout << result <<endl;
            result.polar_mode();
            cout << "or
    " << result << endl;
            cout << "Average outward distance per step = "
                << result.magval()/steps << endl;
            steps = 0;
            result.reset(0.0, 0.0);
            cout << "Enter target distance (q to quit): ";
        }
        cout << "Bye!
    ";
        cin.clear();
        while(cin.get() != '
    ')
            continue;
        return 0;
    }

    二。一个简易的string类。

    锻炼内容:

                拷贝构造函数(深拷贝与浅拷贝)

                重载赋值运算符(深赋值)

                许多的细节与技巧!

    类的声明

    //sting1.h -- fixed and augmented string class definition
    #ifndef STRING1_H_
    #define STRING1_H_
    #include <iostream>
    using std::ostream;
    using std::istream;
    
    class String
    {
    private:
        char * str;                            // pointer ot string
        int len;                            // length of string
        static int num_strings;                // number of objects
        static const int CINLIM = 80;        // cin input limit
    public:
        // construction and other methods
        String(const char * s);             // constructor
        String();                            // default constructor
        String(const String &);                // copy constructor
        ~String();                            // destructor 
        int length() const { return len; }
        // overloaded operator methods
        String & operator=(const String &);
        String & operator=(const char *);
        char & operator[](int i);
        const char & operator[](int i)const;
        // overloaded operator friends
        friend bool operator<(const String &st, const String &st2);
        friend bool operator>(const String &st1, const String &st2);
        friend bool operator==(const String &st, const String &st2);
        friend ostream & operator<<(ostream & os, const String & st);
        friend istream & operator>>(istream & is, String & st);
        //static function
        static int HowMany();
    };
    #endif
    View Code

    类方法的实现。

    // string1.cpp -- String class methods
    #include <cstring>                    // string.h for some
    #include "string1.h"                // includes <iostream>
    using std::cin;
    using std::cout;
    
    // initializing static class member
    int String::num_strings = 0;
    
    // static method
    int String::HowMany()
    {
        return num_strings;
    }
    
    // class methods
    String::String(const char * s)        // construct String from C string
    {
        len = std::strlen(s);             // set size
        str = new char[len + 1];        // allot storage
        std::strcpy(str, s);            // initialize pointer
        num_strings++;                     // set object count
    }
    
    String::String()                    // default constructor
    {
        len = 4;
        str = new char[1];
        str[0] = '';                    // default string
        num_strings++;
    }
    
    String::String(const String & st)
    {
        num_strings++;                     // handle static member update
        len = st.len;                    // same length
        str = new char [len + 1];        // allot space 
        std::strcpy(str, st.str);        // copy string to new location
    }
    
    String::~String()                      // necesserary destructor
    {
        --num_strings;                    // required
        delete [] str;                     // required
    }
    
    // overloaded operator methods
    
        // assign a String to a String
    String & String::operator=(const String & st)
    {
        if(this == &st)
            return *this;
        delete [] str;
        len = st.len;
        str = new char[len + 1];
        std::strcpy(str, st.str);
        return *this;
    }
    
        // assign a C string to a String
    String & String::operator=(const char * s)
    {
        delete [] str;
        len = std::strlen(s);
        str = new char[len + 1];
        std::strcpy(str, s);
        return *this;
    }
    
        // read-write char access for non-const String
    char & String::operator[](int i)
    {
        return str[i];
    }
    
        // read-only char access for const string
    const char & String::operator[](int i) const
    {
        return str[i];
    }
    
    // averloaded operator friends
    
    bool operator<(const String &st1, const String &st2)
    {
        return (std::strcmp(st1.str, st2.str) < 0);
    }
    
    bool operator>(const String &st1, const String &st2)
    {
        return st2 < st1;
    }
    
    bool operator==(const String &st1, const String &st2)
    {
        return (std::strcmp(st1.str, st2.str)==0);
    }
    
        // simple String output
    ostream & operator<<(ostream & os, const String & st)
    {
        os << st.str;
        return os;
    }
    
        // quick and dirty String input
    istream & operator>>(istream & is, String & st)
    {
        char temp[String::CINLIM];
        is.get(temp, String::CINLIM);
        if(is)
            st = temp;
        while (is && is.get() != '
    ')
            continue;
        return is;
    }
    View Code

    main(), 测试String类。

    // saying1.cpp -- using expanded String class 
    // complile with string1.cpp
    #include <iostream>
    #include "string1.h"
    const int MaxLen = 81;
    int main()
    {
        using std::cout;
        using std::cin;
        using std::endl;
        String name;
        cout << "Hi, what's your name?
    >> ";
        cin >> name;
    
        cout << name << ", please enter up to " << ArSize
                << " short sayings <empty line to quit>:
    ";
        String sayings[ArSize];         // array of objects
        char temp[MaxLen]                // temporary string storage
        int i;
        for (i = 0; i < ArSize; i++)
        {
            cout << i + 1 << ": ";
            cin.get(temp, MaxLen);
            while(cin && cin.get()!='
    ')
                continue;
            if(!cin||temp[0] == '')    // empty line?
                break;                    // i not increamented
            else
                sayings[i] = temp;        // overloaded assignment
        }
        int total = i;                     // total # of lines read
    
        if( total > 0)
        {
            cout << "Here are your sayings:
    ";
            for (i = 0; i < total; i++)
                cout << sayings[i][0] << ": " << sayings[i] << endl;
    
            int shortest = 0;
            int first = 0;
            for(i = 1; i < total; i++)
            {
                if(sayings[i].length() < sayings[shortest].length())
                    shortest = i;
                if(sayings[i] < sayings[first])
                    first = i;
            }
            cout << "Shortest saying:
    " << sayings[shortest] << endl;
            cout << "First alphabetically:
    " << sayings[first] << endl;
            cout << "This program used " << String::HowMany()
                    << " String objects. Bye.
    "
        }
        else
            cout << "No input! Bye.
    ";
        return 0;
    }
    View Code

    代码源自: C++ Primer Plus  。 小恪亲自敲写!

    感悟:  如果一部书经久不衰, 一定是有它的理由的! 正如这部书,  内容细致而深刻, 全面而严谨。获益良多!此书有点儿厚,与诸君共勉。

  • 相关阅读:
    @@IDENTITY 存储过程
    ASP.NET的Cookie和Session
    数据格式设置表达式
    DataTable类(MSDN)
    用静态变量代替appliction
    C cgi url 编码解码问题
    C#视频头操作
    c#网页抓取
    c语言字符串分隔
    CGI c 上传文件
  • 原文地址:https://www.cnblogs.com/acm1314/p/4854000.html
Copyright © 2011-2022 走看看