一个问题设置 ++的人学习C是
写一个简短的程序来模拟从塔上掉下来的球.首先,应该要求用户以米为单位的塔的初始高度.假设正常重力(9.8 m/s2),并且球没有初始速度.让程序在0,1,2,3,4和5秒后输出球高于地面的高度.球不应该在地下(高度0).
在开始使用C++之前,我有一个合理的,但主要是自学成才的Java知识.所以看看这个问题似乎应该分成两部分
输入类将询问用户的起始高度,该起始高度将传递给控制器.控制器会给计算类提供这个和几秒钟(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)
我会说你过度设计了一个解决一个小问题的大解决方案,但要回答你的具体问题:
我的程序是否应该以不同的方式构建,出于性能,维护或样式的原因,我不会尝试返回像对象一样的数组?
返回类似数组的对象很好.但这并不意味着返回一个数组,也不意味着分配原始内存new.
并且它也不限于返回值.当你开始使用C++时,最好不要忘记它有内置数组.大多数情况下,您应该使用std::vector或std::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)
至少就目前而言,这不会试图计算球撞击地面时的弹跳 - 它只是假设球在撞击地面时立即停止.