Я тоже новичок в программировании и пытаюсь передать массив структур и «опцию» в функцию. Затем я хочу, чтобы функция могла манипулировать данными в массиве структуры.
struct coordinates{
int x;
int y;
int z;
}COORD;
Параметр option является целым числом, которое указывает, какой частью структуры манипулировать.
Пример этого показан ниже. Функция берет массив структур и составляет 3-х точечную скользящую среднюю от указанной точки данных. У меня проблема в том, что программа, которую я пытаюсь построить, имеет более 50 членов в каждой структуре, поэтому выписывать каждый оператор if на самом деле утомительно. Я спрашиваю, есть ли более элегантное решение ???
#include <iostream>
struct coordinates{
int x;
int y;
int z;
}COORD;
int main() {
COORD points[10];
// Initialising points
for(int i = 0, i < 10, i++){
points[i].x = 1;
points[i].y = 2;
points[i].z = 3;
}
//(struct,startpoint,option)
std::cout << movingaverage(&points,3,1); // Output
}
int movingaverage(COORD *data, int start_point, int option){
if(option == 0) {
// Assigns the "start" value of the sum value.
sum = data[start_point]->x;
sum = sum + data[start_point - 1]->x;
sum = sum + data[start_point + 1]->x;
}
else if(option == 1) {
// Assigns the "start" value of the sum value.
sum = data[start_point]->y;
sum = sum + data[start_point - 1]->y;
sum = sum + data[start_point + 1]->y;
}
else if(option == 2) {
// Assigns the "start" value of the sum value.
sum = data[start_point]->z;
sum = sum + data[start_point - 1]->z;
sum = sum + data[start_point + 1]->z;
}
sum = sum / n;
return sum; //Sum is the moving average
}
Также указатель на членов является возможным решением; в сочетании с функцией шаблона элементы могут быть различного типа. Но да, синтаксис это что-то странное:
#include <iostream>
#include <vector>
using namespace std;
/// calculate the sum of a given structure member in a vector:
template <typename T, typename M>
M membersum(vector<T> array, M (T::*mptr)) {
M sum = 0;
for (int i=0; i<array.size(); i++) {
sum += (array[i].*mptr);
}
return sum;
}
struct Point {
Point(int x, int y, float z): x(x), y(y), z(z) {}
int x;
int y;
float z;
};
int main() {
vector<Point> points;
points.push_back(Point(1,2,3.8));
points.push_back(Point(1,2,4.5));
points.push_back(Point(1,2,1.7));
// your code goes here
cout << "sum x: " << membersum(points, &Point::x) << endl;
cout << "sum y: " << membersum(points, &Point::y) << endl;
cout << "sum z: " << membersum(points, &Point::z) << endl;
return 0;
}
Этот пример, который я создал на ideone.com.
C ++ не поддерживает рефлексию, и поэтому вы не можете перебирать элементы структуры. Я бы сделал это с помощью функции получения.
template<class Getter>
int movingaverage(COORD *data, int start_point, const Getter &get){
auto sum = get(data[start_point]);
sum = sum + get(data[start_point - 1]);
sum = sum + get(data[start_point + 1]);
return sum;
}
std::cout << "x: " << movingaverage(&points, 3, [](const COORD &coord){return coord.x;}) << '\n';
std::cout << "y: " << movingaverage(&points, 3, [](const COORD &coord){return coord.y;}) << '\n';
std::cout << "z: " << movingaverage(&points, 3, [](const COORD &coord){return coord.z;}) << '\n';
Если вы или ваш компилятор запутались в лямбда-части, вы можете просто написать обычную функцию и передать ее взамен.
Я бы предложил использовать простой функтор.
Class MovingAvg
{
MovingAvg(std::vector<Coordinate> *pSet);
void SetPointSet(std::vector<Coordinate> *p);
double operator()(int startPoint, int option)
{
//calculation here.
double sum = 0;
for(int i = -1; i <= 1; ++i)
{
switch(option)
case 0:
sum += pointSet[startPoint + i].x; //check for bounday conditions.
.................
}
return sum / 3;
}
private:
//container
std::vector<Coordinate> *pointSet;
}
Используйте это как.
MovAvg mvG(pointSet);
double sum = mvG(startP, option);
// изменить закрытый член, если необходимо изменить набор точек.
Функторы очень удобны в подобных случаях.
Вы можете попробовать что-то вроде
class coordinates{
private:
int xyz[3]; //implementation detail(!)
public:
int x() const { return xyz[0]; }
int y() const { return xyz[1]; }
int z() const { return xyz[2]; }
//some relevant setters go here
static int movingaverage(COORD *data, int start_point, int option){
sum = data[start_point]->xyz[option];
sum = sum + data[start_point - 1]->xyz[option];
sum = sum + data[start_point + 1]->xyz[option];
}
};