在矢量中存储笛卡尔点并输出距离

时间:2018-04-04 00:00:04

标签: c++ c++11

我在为我创建的课程编写主要课程时遇到了麻烦。我创建了一个名为CartesianPoints的类,我想用它构建我的main。我有我的主要创建的一般结构,但我正在努力与一些技术的东西..

继续寻找的是:

  • 创建一个CartesianPoint对象的空向量,它将作为向量的起点
  • x和y值的限制范围介于10和10之间。 -10。
  • 循环向用户显示他们刚刚输入的点数并询问他们想要输入的内容
  • 上面的循环应该继续,直到触发中断

这是我的CartesianPoints标题

    #ifndef MY_CARTESIAN_POINT_H

    #define MY_CARTESIAN_POINT_H

    #include <iostream>         // cin, cout
    #include <sstream>          // stringstream
    #include <cmath>            // sqrt()
    #include <limits>           // INT_MAX
    #include <stdexcept>        // out_of_range

    using namespace std;


    class CartesianPoint
    {
      public:

        CartesianPoint(int x = 1, int y = 1) { SetPoint(x, y); }


        int GetX() const { return myX; }
        int GetY() const { return myY; } 


        double GetDistanceTo(CartesianPoint pointTo) const; 
        string ToString() const;    


        void SetX(int x) { myX = validateCoordinateValue(x); } 
        void SetY(int y) { myY = validateCoordinateValue(y); } 
        void SetPoint(int x, int y) { SetX(x); SetY(y); }   

        static int GetLimit() { return sharedLimit; }

        static void SetLimit(int limit) { sharedLimit = abs(limit); }

      private: 

        int myX; 
        int myY;  


        static int sharedLimit; 


        int validateCoordinateValue(int value) const;

    };  

    int CartesianPoint::sharedLimit = INT_MAX;    

    double CartesianPoint::GetDistanceTo(CartesianPoint pointTo) const 
    {
        int xDelta = pointTo.myX - myX; 
        int yDelta = pointTo.myY - myY;

        return sqrt((xDelta * xDelta) + (yDelta * yDelta));
    } 

    string CartesianPoint::ToString() const
    {

        stringstream strOut; 

        strOut << "(" << myX << ", " << myY << ")";

        return strOut.str();
    }

    int CartesianPoint::validateCoordinateValue(int value) const
    {

        if((value < -sharedLimit || value > sharedLimit))
        {

            throw out_of_range( "Parameter (" + to_string(value) + ") must be between " 
                + to_string(-sharedLimit) + " and " + to_string(sharedLimit) + ".");
        }
        return value;
    }

    #endif

这是我到目前为止的主要内容

int main()
{

GreetingScreen(); // just a formatting function ive already created 

// while loop that makes will give the option to end the program.
while(/* if myX! =10 and myY!= 10 keep doing this loop */ )
{
    // try catch for errors....
    try
    {
        cout << "Move from point"  /* (0,0)*/ "to where?" << endl;  
        cout << "X: " << endl;
        cin >> x; //point x 
        cout << "Y: " << endl; 
        cin >> y; //point y 


        catch 
        {
            cerr << "could not do this task"; 
        }

    } 
} // ending of while loop 
} // ending of main 

1 个答案:

答案 0 :(得分:1)

你走的是正确的道路,但我确实有一些事情需要关注。

  • 在课堂上,我看不到你在哪里使用<iostream>我认为你可以省略它。

  • 您正在使用using namespace std。最好只是命名空间std::

  • 关于您的构造函数:

    CartesianPoint(int x = 1, int y = 1) { SetPoint(x, y); }
    

这里有两个默认值,这里有两个选项:

  • 将此构造函数声明为explicit

    explicit CartesianPoint( int x = 1, int y = 1 ) { SetPoint( x, y ); }
    
  • 声明默认和用户定义的构造函数

    CartesianPoint() { SetPoint( x, y ); }
    
    CartesianPoint( int x, int y ) { SetPoint( x, y ); } // by value
    
    CartesianPoint( int& x, int& y ) { SetPoint( x, y ); } // by reference
    

注意 - 第三个构造函数我需要重载以使SetPoint函数通过引用接受,但是如果你继续阅读下面的内容,你会看到我对你的课程做了什么。

就我个人而言,我认为2 nd 的选择在两者中更好。如果您选择使用具有2个参数的构造函数,并且两者都具有默认值,并且您没有将构造函数声明为显式;你会遇到麻烦。

这就是为什么我最好选择使用2 nd 选项来声明默认构造函数和用户定义的构造函数。这使您可以灵活地执行以下任何操作:

{
     CartesianPoint p1;  // default constructor called
     CartesianPoint p2( 5, 6 ); // user defined constructor called.
     int x = 5;
     int y = 6;
     CartesianPoint p3( x, y ); // another user defined constructor called.
}

现在构造函数还有其他内容:您正在调用成员函数来设置点(x,y)这不是真正需要的。类有一个成员初始化列表;使用它们!您还在成员函数SetX()中使用成员函数SetY()SetPoint(),不需要额外的调用。

我个人会这样写你的课:

#ifndef MY_CARTESIAN_POINT_H
#define MY_CARTESIAN_POINT_H

// #include <iostream>      // cin, cout
#include <sstream>          // stringstream
#include <cmath>            // sqrt()
#include <limits>           // INT_MAX
#include <stdexcept>        // out_of_range

// using namespace std;

class CartesianPoint {
private:
    int myX;
    int myY;

    static int sharedLimit;
public:

    CartesianPoint() : myX( 0 ), myY( 0 ) {} // I chose 0, but you can choose any default values for (x,y)
    CartesianPoint( int x, int y ) : 
        myX( validate( x ) ), 
        myY( validate( y ) ) {
    }
    CartesianPoint( int& x, int& y ) :
        myX( validate( x ) ),
        myY( validate( y ) ) {
    }

    int GetX() const { return myX; }
    int GetY() const { return myY; } 

    // by value
    void SetX(int x) { myX = validate(x); } 
    void SetY(int y) { myY = validate(y); } 
    void SetPoint(int x, int y) { 
        myX = validate( x );
        myY = validate( y );
    }

    // by reference
    void SetX( int& x ) { myX = validate(x); }
    void SetY( int& y ) { myX = validate(y); }
    void SetPoint( int& x, int& y ) {
        myX = validate( x );
        myY = validate( y );
    }

    double GetDistanceTo(CartesianPoint pointTo) const; 
    string ToString() const;

    static int GetLimit() { return sharedLimit; }
    static void SetLimit(int limit) { sharedLimit = abs(limit); }

  private:
    int validate( int value ) const;   // by value
    int validate( int& value ) const;  // by reference
};  

int CartesianPoint::sharedLimit = INT_MAX;    

double CartesianPoint::GetDistanceTo(CartesianPoint& pointTo) const  {
    int xDelta = pointTo.myX - myX; 
    int yDelta = pointTo.myY - myY;
    return sqrt((xDelta * xDelta) + (yDelta * yDelta));
} 

std::string CartesianPoint::ToString() const {
    std::stringstream strOut;
    strOut << "(" << myX << ", " << myY << ")";
    return strOut.str();
}

int CartesianPoint::validate(int value) const {
    return validate( value );
}

int CartesianPoint::validate( int& value ) const {
    if((value < -sharedLimit || value > sharedLimit)) {
        std::ostringstream stream;
        stream << "Out Of Range: Parameter (" 
               << + ToString(value) 
               << + ") must be between " 
               << + ToString(-sharedLimit) 
               << + " and " 
               << + ToString(sharedLimit) 
               << + '.';                
        throw stream.str();
    }
    return value;
}


#endif

main.cpp

#include <iostream>   
#include "CartesianPoint.h"

int main() {
    try {
        std::vector<CartesianPoint> points; // It's already empty

        while( condition(s) ) {
            // do work
        }

    } catch( std::string& str ) {
        std::cout << str << std::endl;
        return -1;          
    } catch( ... ) {
        std::cout << "Caught some other or unknown exception." << std::endl;
        return -1;
    }

    return 0;
}

编辑 - 我更改了validateCoordinateValue我首先将其名称更改为validate,原因如下:

  • 1 st :它是函数的私有方法,不作为公共接口的一部分公开。
  • 2 nd :它更短更容易打字和阅读。
  • 3 rd :在类validate()中使用它时,它已经自我解释了函数的功能。比较两者:
    • myX = validateCoordinateValue( x );
    • myX = validate( x );

然后我还在函数的重载中添加了接受pass by reference的方法。参考版本完成工作,传递值函数只是简单地返回并调用参考版本。