学习C ++的人的问题set是
写一个简短的程序来模拟从塔上掉下来的球。首先,应该要求用户以米为单位的塔的初始高度。假设正常重力(9.8 m / s2),并且球没有初始速度。让程序在0,1,2,3,4和5秒后输出球高于地面的高度。球不应该在地下(高度0)。
在开始使用C ++之前,我有一个合理但主要是自学成才的Java知识。所以看问题似乎应该分成
输入类会询问用户一个起始高度,该起始高度将传递给控制器。控制器会向计算类提供此秒和数秒(5),这将创建结果数组并将其返回给控制器。控制器会将结果数组交给输出类,然后将它们打印到控制台。
我会将实际代码放在底部,但可能不需要它。
您可能已经看到问题,尝试返回一个数组。我没有问如何解决这个问题,有一个解决方法here和here。我问,问题是设计糟糕的结果?出于性能,维护或样式的原因,我的程序应该采用不同的结构,以便我不会尝试返回像对象这样的数组吗?
这是代码(与尝试返回数组不同);
的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;
}
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;
}
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;
}
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;
}
最后是几个标题; 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_ */
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_ */
答案 0 :(得分:7)
我会说你过度设计了一个解决一个小问题的大解决方案,但要回答你的具体问题:
我的程序是否应该以不同的方式构建,出于性能,维护或样式的原因,这样我就不会尝试返回像对象一样的数组?
返回类似数组的对象很好。但这并不意味着返回一个数组,也不意味着用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;
}
}
与标准库的其余部分一起使用时更加清晰:
std::vector<double> results;
calc_pos(inputs, std::back_inserter(results));
如果你愿意,你可以更进一步 - 标准库有很多可以帮助解决这个问题。你的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);
这计算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); });
至少就目前来说,这不会试图计算球撞击地面时的弹跳 - 它只是假设球在撞击地面时会立即停止。
答案 1 :(得分:3)
您应该摆脱自我分配double *
并使用std::vector<double>
代替。它不难学习,也是现代C ++的基本步骤
答案 2 :(得分:1)
这就是我解决问题的方法:
#include <cmath>
#include <iostream>
#include <iomanip>
using std::cin;
using std::cout;
using std::endl;
using std::sqrt;
using std::fixed;
using std::setprecision;
using std::max;
using std::setw;
static const double g = 9.81;
class Calculator {
public:
Calculator(double inh) : h(inh)
{
}
void DoWork() const {
double tmax = sqrt(h / ( g / 2));
for (double t=0.0; t<tmax; t+=1.0) {
GenerateOutput(t);
}
GenerateOutput(tmax);
}
private:
void GenerateOutput(double t) const {
double x = g * t * t / 2;
double hremaining = max(h - x, 0.0);
cout << fixed << setprecision(2) << setw(10) << t;
cout << setw(10) << hremaining << endl;
}
double h;
};
int main() {
double h(0.0);
cout << "Enter height in meters: ";
cin >> h;
if (h > 0.0) {
const Calculator calc(h);
calc.DoWork();
} else {
return 1;
}
return 0;
}