Erik Jackson
Erik Jackson

Reputation: 1

Storing Cartesian points in a vector and outputting distance

Im having trouble writing my main for a class I created. I created a class called CartesianPoints which I want to use to construct my main with. I have the general structure of my main created but am struggling with the some technical stuff..

Heres what im looking for:

here is my header for 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

here is my main so far

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 

Upvotes: 0

Views: 629

Answers (1)

Francis Cugler
Francis Cugler

Reputation: 7905

You are on the right path, but there are a few things that I do see a concern with.

  • In your class I don't see where you are using <iostream> I think you can omit it.

  • You are using using namespace std. It is preferred to just scope out the namespace std::.

  • About your constructor:

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

Here you have two default values, there are two options here:

  • Declare this constructor as explicit

    explicit CartesianPoint( int x = 1, int y = 1 ) { SetPoint( x, y ); }
    
  • Declare a default and user defined constructors

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

Note - The third constructor my require overloads for the SetPoint function to accept by reference, however if you continue reading below you will see what I've done with your class.

Personally I think the 2nd choice is the better of the two. If you choose to use a constructor with 2 parameters and both have default values and you are not declaring the constructor as explicit; you will run into trouble.

This is why I preferably choose to use the 2nd option of declaring both a default constructor and a user defined constructor. This gives you the flexibility to do any of the following:

{
     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.
}

Now there is something else with the constructor: you are calling a member function to set the point (x,y) This is not really needed. Class's have a member initializer list; use them! You are also using member functions SetX() and SetY() in your member function SetPoint() the extra calls are not needed.


Personally I would write your class as such:

#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;
}

EDIT - I made a change to the validateCoordinateValue I first changed it's name to just validate for several reasons:

  • 1st: It is a private method to the function and it isn't exposed as part of its public interface.
  • 2nd: It is shorter and easier to type as well as read.
  • 3rd: When using it in the class just as validate() it is already self explanatory of what the function does. Compare the two:
    • myX = validateCoordinateValue( x );
    • myX = validate( x );

Then I also added in an overload of the function to accept pass by reference as well. The reference version does the work, the pass by value function just simply returns and calls the reference version.

Upvotes: 1

Related Questions