用类方法表示矢量
// class.h
#pragma once
#ifndef _CLASS_H_
#define _ClASS_H_
#include<iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode{RECT,POL};//两种表达矢量的方式
private:
double x;
double y;
double mag; //矢量的长度
double ang; //矢量的方向,以角度表示
Mode mode; //设置表达方式的模式
void set_mag();
void set_ang();
void set_x();
void set_y();
public:
Vector();
Vector(double n1, double n2, Mode form = RECT); //默认模式为RECT
void reset(double n1, double n2, Mode form = RECT);
~Vector();
//之所以要设置xval, yval, magval, angval这些函数,而不是将这些值存放在private区域中,就是为了在main函数中可以调用这些函数来获得这些值,若在private空间中则无法访问
double xval() const // xvalue
{
return x;
}
double yval() const //yvalue;
{
return y;
}
double magval() const //magvalue
{
return mag;
}
double angval() const //angvalue
{
return ang;
}
void polar_mode(); //切换为polar mode
void rect_mode(); //切换为rect mode
// 重载运算符:
Vector operator+(const Vector& b)const;
Vector operator-(const Vector& b)const;
Vector operator-()const;
Vector operator*(double n)const;
// 友元函数:
friend Vector operator*(double n, const Vector& a);
friend std::ostream & operator<<(std::ostream& os,const Vector& v);
};
}
#endif
// fuc.cpp
#include"class.h"
#include<cmath> // 使用了 sqrt()求根号值函数,tan() 接受角度值返回斜率值, atan() 接受斜率值返回角度值, sin和cos接受角度值分别返回各自的正弦值和余弦值
using std::cout;
using std::sqrt;
using std::tan;
using std::atan;
using std::cos;
using std::sin;
using std::endl;
namespace VECTOR
{
const double Rad_to_deg = 45 / atan(1.0); // 电脑中一弧度所代表的角度
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if (x == 0 && y == 0)
{
ang = 0.0;
}
else
{
ang = atan2(y, x); // atan2接受两个参数--x和y坐标,更加准确
}
}
void Vector::set_x()
{
x = mag * cos(ang);
}
void Vector::set_y()
{
y = mag * sin(ang);
}
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = RECT; // 默认模式为RECT;
}
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if (mode == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (mode == POL)
{
mag = n1;
ang = n2;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode form)
{
mode = form;
if (mode == RECT) // 根据x和y来设置距离和方向
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (mode == POL) // 根据距离和方向来设置x和y
{
mag = n1;
ang = n2;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0" << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
//析构函数
}
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
Vector Vector::operator+(const Vector& b)const
{
return Vector(x + b.x, y + b.y); // 构造函数在运行时会自动创建一个临时的类对象来进行一系列的赋值,直接return一个构造函数的调用相当于return一个设置好值的类对象
}
Vector Vector::operator-(const Vector& b)const //实现类对象值的相减
{
return Vector(x - b.x, y - b.y);
}
Vector Vector::operator-()const //实现类对象的值变为相反数
{
return Vector(-x, -y);
}
Vector Vector::operator*(double n)const
{
return Vector(x * n, y * n);
}
//友元函数的定义(无需再加上friend,同时也无需再声明是类中的函数)
Vector operator*(double n, const Vector& a)
{
return a * n;
}
std::ostream& operator<<(std::ostream& os, const Vector& v) // 返回值为 ostream& 即 ostream流的一个引用
{
// 因为是友元函数,所以不在类作用域中,不可以直接使用属于类作用域的两个枚举量 RECT 和 POL -- VECTOR::Vector::RECT/POL
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; // os重载 << 运算符的第一个参数,同时也是一个ostream流的引用
}
}
// main.cpp
#include"class.h"
#include<cstdlib> // rand() ,srand(),
#include<ctime> //time()
int main()
{
using namespace std;
using VECTOR::Vector;
srand(time(0)); //提供随机数种子
double directions;
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) //输入数字 -- true 输入字母 -- false
{
cout << "Enter step length: ";
if (!(cin >> dstep)) // 如果输入的不是数字,退出循环
{
break;
}
while (result.magval() < target) //矢量的长度小于目标长度
{
directions = rand() % 360; //通过随机值来设置下次走的方向
step.reset(dstep, directions, Vector::POL); //修改参数 -- 步子的长度,方向,以及表达方式
result = result + step; // 对象的重载相加
steps++; // 记录一共走了多少步
}
cout << "After " << steps << " steps,the subject has the following location: " << endl;
cout << result << endl; // 对象的cout显示在屏幕上 ( >>运算符的重载)
result.polar_mode();
cout << "or\n" << result << endl; // 重载 << 运算符的函数中的返回值为 ostream流的一个引用,所以可以连续使用<<运算符
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~" << endl;
//若输入过程中输入了很多字符,则用下面这几行代码来清除,清除完成后即cin,get()!='\n',再结束程序
cin.clear();
while (cin.get() != '\n')
{
continue;
}
system("pause");
return 0;
}
知识点:
1.#include<cmath> 使用了 sqrt()求根号函数,tan() 接受角度值返回斜率值, atan() 接受斜率值返回角度值, atan2()接受x和y两个参数返回角度值,sin和cos接受角度值分别返回各自的正弦值和余弦值。
2.构造函数在运行时会自动创建一个临时的类对象来进行一系列的赋值,直接return一个构造函数的调用相当于return一个设置好值的类对象
3.实现真随机数:<cstdlib>中的srand()和rand()函数以及<ctime>中的time()函数
srand(time(0))提供随机数种子后,rand()就可以提供随机数
4.之所以要设置xval,yval,magval,angval这些函数,而不是将这些值存放在private区域中,就是为了在main函数中可以调用这些函数来获得这些值,若在private空间中则无法访问