狂自私

导航

C++ primer plus 练习题:11.9.1 修改程序清单11.5,使之将一系列连续的随机漫步者位置写入到文件中。

1、修改程序清单11.5,使之将一系列连续的随机漫步者位置写入到文件中。对于每个位置,用步号进行标示。另外,让该程序将初始条件(目标距离和步长)以及结果小结写入到该文件中。该文件的内容与下面类似:

 

 

 custom_input.h

#pragma once
#ifndef CUSTOM_INPUT_H_
#define CUSTOM_INPUT_H_
namespace MY_IN {
    /*
    * 专用于输入double类型的变量;处理用户输入,确保用户输入的是合法数字;对于数字和字符混合的输入,数字在前的读取数字,后续的字符丢弃;若是字符在前,则要求重新输入
    * 返回int值EXIT_SUCCESS
    * result_int:用于存放用户输入的整型数字,double*指针,对应的存放空间必须在调用之前分配好;
    * hint_str:const char*指针,用于提示输入的字符串的地址,用于提示用户的输入,字符串建议在结尾处添加换行符;
    * error_message:在用户输入错误的情况下,提示用户的信息字符串的地址,可以为空,为空则不提示,字符串建议在结尾处添加换行符
    */
    int in_double(double* result_int, const char* hint_str, const char* error_message = {});
    /*
    * 处理用户输入,只处理char字符数组;
    * result_str:char*指针,用于存放用户输入的字符,对应的存放空间必须在调用之前分配好;
    * len:无符号整型,用于指定result_str最多能存储多少个字符(不包括NULL),也就是说,若是result_str能存放10个字符,那么len最多只能传递9;len的最大允许范围为0~(UINT_MAX-1)
    * hint_str:const char*指针,提示字符串的地址,用于提示用户的输入,字符串建议在结尾处添加换行符;
    * error_message:const char*指针,在用户输入错误的情况下(长度过长,或者输入为空),提示用户的信息字符串的地址,可以为空,为空则不提示,字符串建议在结尾处添加换行符
    * 输入成功会返回EXIT_SUCCESS
    * 在len的值等于UINT_MAX时会返回EXIT_FAILURE
    */
    int in_charArray(char* result_str, unsigned int len, const char* hint_str, const char* error_message = {});
    /*
    * in_uint:处理用户输入,确保用户输入的是正整数;
    * result_int:用于存放用户输入的整型数字,unsigned int*指针,对应的存放空间必须在调用之前分配好;
    * hint_str:const char*指针,提示字符串的地址,用于提示用户的输入,字符串建议在结尾处添加换行符;
    * error_message:const char*指针,在用户输入错误的情况下,提示用户的信息字符串的地址,可以为空,为空则不提示,字符串建议在结尾处添加换行符
    */
    int in_uint(unsigned int* result_int, const char* hint_str, const char* error_message = {});
    /*
    * in_int:处理用户输入,确保用户输入的是整数;
    * result_int:用于存放用户输入的整型数字,int*指针,对应的存放空间必须在调用之前分配好;
    * hint_str:const char*指针,提示字符串的地址,用于提示用户的输入,字符串建议在结尾处添加换行符;
    * error_message:const char*指针,在用户输入错误的情况下,提示用户的信息字符串的地址,可以为空,为空则不提示,字符串建议在结尾处添加换行符
    */
    int in_int(int* result_int, const char* hint_str, const char* error_message = {});
}

#endif // !CUSTOM_INPUT_H_

 

custom_input.cpp

#include "custom_input.h"
#include <iostream>
#include <string>
namespace MY_IN {
    int in_double(double* result_int, const char* hint_str, const char* error_message) {
        double a;
        while (true)
        {
            std::cout << hint_str;

            if (std::cin >> a) {
                std::cin.get();     //cin不处理回车符
                *result_int = a;
                break;
            }
            else {
                if (nullptr != error_message) {
                    std::cout << error_message;
                }
                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');//清除输入缓冲区的当前行
                //numeric_limits:numeric_limits 类模板提供查询各种算术类型属性的标准化方式(例如 int 类型的最大可能值是 std::numeric_limits<int>::max() )。
                //  通过 numeric_limits 模板的特化提供此信息。
                //streamsize:类型 std::streamsize 是用于表示 I/O 操作中转移字符数或 I/O 缓冲区的大小,是有符号整数类型。
            }
        }
        return EXIT_SUCCESS;
    }
    int in_charArray(char* result_str, unsigned int len, const char* hint_str, const char* error_message) {
        std::string a;
        if (UINT_MAX == len) {
            std::cout << "参数len的值为UINT_MAX!";
            return EXIT_FAILURE;
        }
        while (true)
        {
            std::cout << hint_str;

            if (std::getline(std::cin, a)) {
                if (a.size() <= len) {
                    const char* b = a.c_str();
                    strncpy_s(result_str, len + 1, b, len);
                    /*
                    * errno_t strncpy_s(   char *strDest,   size_t numberOfElements,   const char *strSource,   size_t count);
                    * 函数在内部处理的时候,会因为要保留NULL字符,将numberOfElements减去1,就是说,numberOfElements最小值应该为2,否则就会触发参数无效异常
                    */
                    *(result_str + len) = NULL;
                    break;
                }
                else {
                    if (nullptr == error_message) {
                        std::cout << "你输入的字符串太长了,超过了" << len << "。重新输入。" << std::endl;
                        a = "";
                    }
                    else {
                        std::cout << error_message;
                        a = "";
                    }

                }
            }
            else {
                //对于输入字符类型,这个应该是有点多余的。
                std::cin.clear();
                //std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');//清除输入缓冲区的当前行 ,但是若是输入缓冲区为空,就会阻塞,等待缓冲区有值才会执行。
                //numeric_limits:numeric_limits 类模板提供查询各种算术类型属性的标准化方式(例如 int 类型的最大可能值是 std::numeric_limits<int>::max() )。
                //  通过 numeric_limits 模板的特化提供此信息。
                //streamsize:类型 std::streamsize 是用于表示 I/O 操作中转移字符数或 I/O 缓冲区的大小,是有符号整数类型。
            }
        }
        return EXIT_SUCCESS;
    }
    int in_uint(unsigned int* result_int, const char* hint_str, const char* error_message) {
        long long a;
        while (true)
        {
            std::cout << hint_str;

            if (std::cin >> a) {
                std::cin.get();     //cin不处理回车符
                if (a >= 0 && a <= UINT_MAX) {
                    *result_int = static_cast<unsigned int>(a);
                    break;
                }
            }
            else {
                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');//清除输入缓冲区的当前行
                //numeric_limits:numeric_limits 类模板提供查询各种算术类型属性的标准化方式(例如 int 类型的最大可能值是 std::numeric_limits<int>::max() )。
                //  通过 numeric_limits 模板的特化提供此信息。
                //streamsize:类型 std::streamsize 是用于表示 I/O 操作中转移字符数或 I/O 缓冲区的大小,是有符号整数类型。
            }
            if (nullptr == error_message) {
                std::cout << error_message;
            }
            else {
                std::cout << "请输入正整数!\n";
            }
        }
        return EXIT_SUCCESS;
    }
    int in_int(int* result_int, const char* hint_str, const char* error_message) {
        int a;
        while (true)
        {
            std::cout << hint_str;

            if (std::cin >> a) {
                *result_int = a;
                std::cin.get();     //cin不处理回车符
                break;
            }
            else {
                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');//清除输入缓冲区的当前行
                //numeric_limits:numeric_limits 类模板提供查询各种算术类型属性的标准化方式(例如 int 类型的最大可能值是 std::numeric_limits<int>::max() )。
                //  通过 numeric_limits 模板的特化提供此信息。
                //streamsize:类型 std::streamsize 是用于表示 I/O 操作中转移字符数或 I/O 缓冲区的大小,是有符号整数类型。
            }
            if (nullptr == error_message) {
                std::cout << error_message;
            }
        }
        return EXIT_SUCCESS;
    }
}

 

Vector.h

#pragma once
#ifndef VETOR_H_
#define VETOR_H_
#include <iostream>

namespace VECTOR {
    enum class Mode { RECT = 0, POL = 1 };

    class Vector
    {
    public:
        Vector();
        ~Vector() {};
        Vector(double n1, double n2, Mode form = Mode::RECT);
        void reset(double n1, double n2, Mode form = Mode::RECT);
        double xcal()const { return this->x; };
        double yval()const { return this->y; }
        double magval()const { return this->mag; }
        double angval()const { return this->ang; }
        void polar_mode();
        void rect_mode();
        Vector operator+(const Vector& b)const;
        Vector operator-(const Vector& b)const;
        Vector operator*(double d)const;
        Vector operator-()const;    //负号

        friend Vector operator*(double d, const Vector& v);
        friend std::ostream& operator<<(std::ostream& os, const Vector& v);        

        operator double()const;
    private:
        double x{}, y{}, mag{}, ang{};
        Mode mode{};

        void set_mag();
        void set_ang();
        void set_x();
        void set_y();
    };
}
#endif // !VETOR_H_

 

Vector.cpp

#include "Vector.h"
#include <cmath>
using std::qsort;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;

namespace VECTOR {
    const double Rad_to_deg = 45.0 / atan(1.0);

    void Vector::set_mag() {
        //卧槽,勾股定理?
        this->mag = sqrt(this->x * this->x + this->y * this->y);
    }
    void Vector::set_ang() {
        if ((!(this->x < 0) && !(this->x > 0)) && (!(this->y < 0) && !(this->y > 0))) {
            //就是说x和y都要为0的时候
            this->ang = 0.0;
        }
        else {
            this->ang = atan2(this->y, this->x);
        }
    }
    void Vector::set_x() {
        this->x = this->mag * cos(ang);
    }
    void Vector::set_y() {
        this->y = this->mag * sin(ang);
    }
    Vector::Vector() {
        this->x = this->y = this->ang = this->mag = 0;
        mode = Mode::RECT;
    }
    Vector::Vector(double n1, double n2, Mode form) {
        this->mode = form;
        if (form == Mode::RECT) {
            this->x = n1;
            this->y = n2;
            this->set_mag();
            this->set_ang();
        }
        else if (form == Mode::POL) {
            this->mag = n1;
            this->ang = n2;
            this->set_x();
            this->set_y();
        }
        else {
            cout << "Vector中没有第三种模式--\n将设置为0";
            this->x = this->y = this->ang = this->mag = 0;
            mode = Mode::RECT;
        }
    }
    void Vector::reset(double n1, double n2, Mode form) {
        this->mode = form;
        if (form == Mode::RECT) {
            this->x = n1;
            this->y = n2;
            this->set_mag();
            this->set_ang();
        }
        else if (form == Mode::POL) {
            this->mag = n1;
            this->ang = n2;
            this->set_x();
            this->set_y();
        }
        else {
            cout << "Vector中没有第三种模式--\n将设置为0";
            this->x = this->y = this->ang = this->mag;
            mode = Mode::RECT;
        }
    }
    void Vector::polar_mode() {
        this->mode = Mode::POL;
    }
    void Vector::rect_mode() {
        this->mode = Mode::RECT;
    }
    Vector Vector::operator+(const Vector& b)const {
        return Vector(this->x + b.x, this->y + b.y);
        /*Vector sum;
        sum.x = this->x + b.x;
        sum.y = this->y + b.y;
        sum.set_ang();
        sum.set_mag();
        return sum;*/
    }
    Vector Vector::operator-(const Vector& b)const {
        return Vector(this->x - b.x, this->y - b.y);
    }
    Vector Vector::operator-()const {
        return Vector(-this->x, -this->y);
    }
    std::ostream& operator<<(std::ostream& os, const Vector& v) {
        if (v.mode == VECTOR::Mode::RECT) {
            os << "(x,y)={" << v.x << "," << v.y << ")";
        }
        else if (v.mode == VECTOR::Mode::POL) {
            os << "(m,a)=(" << v.mag << "," << v.ang * VECTOR::Rad_to_deg << ")";
        }
        else {
            os << "vector没有第三种模式!";
        }
        return os;
    }
    Vector Vector::operator*(double d)const {
        return Vector(d * this->x, d * this->y);
    }
    Vector operator*(double d, const Vector& v) {
        return v * d;
    }
    Vector::operator double()const {
        return this->mag;
    }
}

 

main.cpp

#include <string>
#include<iostream>
#include "Vector.h"
#include "custom_input.h"
#include<ctime>
#include<cstdlib>
#include<fstream>

int main(void) {
    srand(static_cast<unsigned long>(time(0)));    //设置随机数种子
    double direction{};
    VECTOR::Vector result{ 0.0, 0.0 }, step{};
    unsigned long steps{};
    double target{}, dstep{20};
    std::string isQuit;
    std::ofstream ofd{};
    ofd.open(R"(.\随机漫步者结果.txt)",std::ios_base::out);

    do {
        MY_IN::in_double(&target, "输入目标的距离:\n");
        ofd << "目标距离:" << target << ";每一步的距离:" << dstep << "\n";
        while (result.magval() < target) {
            direction = rand() % 360;
            step.reset(dstep, direction, VECTOR::Mode::POL);
            result = result + step;
            ofd << steps << ":" << result << '\n';
            steps++;
        }
        ofd << "移动到目标距离共走了" << steps << "步\n";
        ofd << result << std::endl << "或者:\n";
        result.polar_mode();
        ofd << result << "\n平均每步走的距离:" << target / steps << '\n';
        result.rect_mode();
        steps = {};
        result.reset(0.0, 0.0);
        std::cout << "是否继续,是请输入y,否请输入q:\n";
        std::getline(std::cin, isQuit);
    } while (isQuit[0] != 'q' && isQuit[0] != 'Q');

    ofd.close();

    return EXIT_SUCCESS;
}

结果:

 

posted on 2022-04-18 18:13  狂自私  阅读(38)  评论(0编辑  收藏  举报