我应该尝试返回阵列,还是有更好的解决方案?

Jek*_*owl 4 c++ arrays

一个问题设置 ++的人学习C是

写一个简短的程序来模拟从塔上掉下来的球.首先,应该要求用户以米为单位的塔的初始高度.假设正常重力(9.8 m/s2),并且球没有初始速度.让程序在0,1,2,3,4和5秒后输出球高于地面的高度.球不应该在地下(高度0).

在开始使用C++之前,我有一个合理的,但主要是自学成才的Java知识.所以看看这个问题似乎应该分成两部分

  • 输入类
  • 输出类
  • 计算课
  • 物理常数类(问题设定者推荐)
  • 控制器('main')类

输入类将询问用户的起始高度,该起始高度将传递给控制器​​.控制器会给计算类提供这个和几秒钟(5),这将创建一个结果数组并将其返回给控制器.控制器会将结果数组交给输出类,然后将它们打印到控制台.

我将实际代码放在底部,但可能不需要.

您可能已经看到问题,尝试返回一个数组.我不问如何避开这个问题,有解决方法在这里这里.我问,问题是设计糟糕的结果吗?我的程序是否应该以不同的方式构建,出于性能,维护或样式的原因,我不会尝试返回像对象一样数组

这是代码(与尝试返回数组不同);

main.cpp中

/*
 * Just the main class, call other classes and passes variables around
 */
#include <iostream>
#include "dropSim.h"
using namespace std;

int main()
{
    double height = getHeight();
    int seconds = 5;
    double* results = calculateResults(height, seconds);
    outputResults(results);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

getHeight.cpp

/*
 *  Asks the user for a height from which to start the experiment
 *  SI units
 */
#include <iostream>
using namespace std;

double getHeight()
{
    cout << "What height should the experiment start at; ";
    double height;
    cin >> height;
    return height;
}
Run Code Online (Sandbox Code Playgroud)

calculateResults.cpp

/*
 * given the initial height and the physical constants, the position of the ball
 * is calculated at integer number seconds, beginning at 0
 */

#include "constants.h"
#include <cmath>
#include <iostream>
using namespace std;

double getPosition(double height, double time);

double* calculateResults(double height, int seconds)
{

    double positions[seconds + 1];
    for(int t = 0; t < seconds + 1; t++)
    {
        positions[t] = getPosition(height, t);
    }
    return positions;
}

double getPosition(double height, double time)
{
    double position = height - 0.5*constants::gravity*pow(static_cast<double>(time), 2);
    if( position < 0) position = 0;
    //Commented code is for testing
    //cout << position << endl;
    return position;
}
Run Code Online (Sandbox Code Playgroud)

outputResults.cpp

/*
 *      Takes the array of results and prints them in an appropriate format
 */


#include <iostream>
#include <string>
#include <sstream>

using namespace std;

void outputResults(double* results){
    string outputText = "";
    //The commented code is to test the output method
    //Which is working
    //double results1[] = {1,2,3,4,5};
    //int numResults = sizeof(results1)/sizeof(results1[0]);
    int numResults = sizeof(results)/sizeof(results[0]);
    //cout << numResults; //= 0 ... Oh
    for(int t = 0; t < numResults; t++)
    {
        ostringstream line;
        line << "After " << t << " seconds the height of the object is " << results[t] << "\r";
        outputText.append(line.str());

    }
    cout << outputText;
}
Run Code Online (Sandbox Code Playgroud)

最后是几个标题; dropSim.h

/*
 * dropSim.h
 */

#ifndef DROPSIM_H_
#define DROPSIM_H_

double getHeight();

double* calculateResults(double height, int seconds);

void outputResults(double* results);

#endif /* DROPSIM_H_ */
Run Code Online (Sandbox Code Playgroud)

constants.h

/*
 *      Contains physical constants relevant to simulation.
 *      SI units
 */

#ifndef CONSTANTS_H_
#define CONSTANTS_H_

namespace constants
{
    const double gravity(9.81);
}

#endif /* CONSTANTS_H_ */
Run Code Online (Sandbox Code Playgroud)

Jer*_*fin 6

我会说你过度设计了一个解决一个小问题的大解决方案,但要回答你的具体问题:

我的程序是否应该以不同的方式构建,出于性能,维护或样式的原因,我不会尝试返回像对象一样的数组?

返回类似数组的对象很好.但这并不意味着返回一个数组,也不意味着分配原始内存new.

并且它也不限于返回值.当你开始使用C++时,最好不要忘记它有内置数组.大多数情况下,您应该使用std::vectorstd::array(或其他线性集合std::deque).

内置阵列通常应被视为专用项目,主要包括与C的兼容性,而不是日常使用.

但是,值得考虑以与标准库中的算法相同的方式编写计算.这意味着编写代码以接收到目标的迭代器,并将其输出写入迭代器指定的位置.

我可能将高度和时间一起打包为一组输入参数,并且具有基于以下内容生成输出的函数:

struct params {
    double height;
    int seconds;
};

template <class OutIt>
void calc_pos(params const &p, OutIt output) { 
    for (int i=0; i<p.seconds; i++) {
        *output = get_position(p.height, i);
        ++output;
    }
}
Run Code Online (Sandbox Code Playgroud)

与标准库的其余部分一起使用时更加清晰:

std::vector<double> results;

calc_pos(inputs, std::back_inserter(results));
Run Code Online (Sandbox Code Playgroud)

如果你愿意,你可以更进一步 - 标准库有很多可以帮助解决这个问题.您calc_pos只需使用连续的时间值重复调用另一个函数.你可以(例如)std::iota用来生成连续的时间,然后std::transform用来生成输出:

std::vector<int> times(6);

std::iota(times.begin(), times.end(), 0);

std::vector<double> distances;

std::transform(times.begin(), times.end(), compute_distance);
Run Code Online (Sandbox Code Playgroud)

这计算了distances在给定时间段之后下降的距离而不是地面以上的高度,但是给定初始高度,计算两者之间的差异是非常微不足道的:

double initial_height = 5;

std::vector<double> heights;

std::transform(distances.begin(), distances.end(), 
    std::back_inserter(heights),
    [=](double v) { return max(initial_height-v, 0); });
Run Code Online (Sandbox Code Playgroud)

至少就目前而言,这不会试图计算球撞击地面时的弹跳 - 它只是假设球在撞击地面时立即停止.