Джон, очевидно, вы немного боретесь с пониманием того, какие значения вам нужно передать в качестве параметров вашей функции и как обрабатывать циклы для получения наибольшего среднесуточного значения на основе ваших данных.
Для начала, единственные параметры, которые необходимо передать в largestaverage()
, - это сам массив, и границы, указывающие число days
и measurements
, взятых для каждого дня. Только из этой информации вы можете вычислить наибольшее среднесуточное значение - но как вернуть это наибольшее среднесуточное значение обратно к main()
, чтобы его можно было использовать?
Ключом является выбор значимого return type
для вашей функции, чтобы вы могли return
необходимую информацию. Поскольку вы проверяете данные, которые вы прочитали в array
в main()
(не так ли?), Нет необходимости выбирать тип возврата, чтобы указать на успех / неудачу расчета, но выбор void
не дает никаких преимуществ на всех, и вам остается передать ссылку.
Хотя это будет работать, есть гораздо более фундаментальный способ обработки возврата - просто return
значение до main()
нужного типа. Это исключает необходимость проходить largest
вообще. Функция всегда может вернуть свой собственный тип. Но какого типа? double
делает правильный выбор, так как результат деления sum
на число measurements
приведет к значению с плавающей точкой - если вы не намерены целочисленное деление произойдет.
Внесение изменений в тип возврата для largestaverage
и перестановка циклов таким образом, чтобы sum
и avg
вычислялись ежедневно и должным образом повторно инициализировались на следующий день, включая <limits>
так что вы можете использовать стандартный способ инициализации largest
наименьшим значением, доступным для вашего type
, вы можете сделать что-то похожее на:
...
#include <limits> /* for numeric_limits */
...
#define MAXDM 100 /* if you need a constant, #define one (or more) */
/* choose a meaningful return type, and return a value */
double largestaverage (int array[][MAXDM], int days, int msrmts)
{
/* initialize largest sufficiently small (all vals could be negative) */
double largest = std::numeric_limits<double>::min();
for (int i = 0; i < days; i++) { /* loop over each day */
int sum = 0; /* initialize sum/avg */
double avg = 0;
for (int k = 0; k < msrmts; k++) /* loop over measurements */
sum += array[i][k]; /* compute sum */
avg = sum / (double)msrmts; /* compute avg */
if (avg > largest) /* check against largest */
largest = avg;
}
return largest; /* return largest */
}
Переставив main()
и добавив необходимые проверки для каждого ввода, вы можете сделать что-то похожее на следующее:
int main (void) {
int array[MAXDM][MAXDM] = {{0}}, /* declare/initialize variables */
days, measurements;
if (!(cin >> days >> measurements)) { /* VALIDATE read of input */
cerr << "error: invalid format for days/measurements\n";
return 1;
}
for (int i = 0; i < days; i++) /* loop over days */
for (int k = 0; k < measurements; k++) /* loop over measurements */
if (!(cin>>array[i][k])) { /* VALIDATE read of input */
cerr << "error: invalid format row '" << k + 1 << "'\n";
return 1;
}
/* output results */
cout << "largest daily avg: "
<< largestaverage (array, days, measurements) << endl;
}
Если поместить его в краткий пример, то получится:
#include <iostream>
#include <limits> /* for numeric_limits */
using namespace std;
#define MAXDM 100 /* if you need a constant, #define one (or more) */
/* choose a meaningful return type, and return a value */
double largestaverage (int array[][MAXDM], int days, int msrmts)
{
/* initialize largest sufficiently small (all vals could be negative) */
double largest = std::numeric_limits<double>::min();
for (int i = 0; i < days; i++) { /* loop over each day */
int sum = 0; /* initialize sum/avg */
double avg = 0;
for (int k = 0; k < msrmts; k++) /* loop over measurements */
sum += array[i][k]; /* compute sum */
avg = sum / (double)msrmts; /* compute avg */
if (avg > largest) /* check against largest */
largest = avg;
}
return largest; /* return largest */
}
int main (void) {
int array[MAXDM][MAXDM] = {{0}}, /* declare/initialize variables */
days, measurements;
if (!(cin >> days >> measurements)) { /* VALIDATE read of input */
cerr << "error: invalid format for days/measurements\n";
return 1;
}
for (int i = 0; i < days; i++) /* loop over days */
for (int k = 0; k < measurements; k++) /* loop over measurements */
if (!(cin>>array[i][k])) { /* VALIDATE read of input */
cerr << "error: invalid format row '" << k + 1 << "'\n";
return 1;
}
/* output results */
cout << "largest daily avg: "
<< largestaverage (array, days, measurements) << endl;
}
Пример ввода
$ cat file
4 3
8 8 10
12 10 7
14 12 11
11 10 12
Пример использования / Вывод
$ ./bin/dailyavg < file
largest daily avg: 12.3333
Наибольшее среднее значение, соответствующее вводу за третий день.
Позволяя C ++ выполнять большую часть работы
Хотя в использовании базовых типов массивов и ручных циклов for
в C ++ нет ничего плохого, для всех практических целей ваш код и приведенный выше код - не что иное, как стандартный C, кроме использования cin/cout
вместо scanf/printf
и используя numeric_limits<double>::min()
вместо DBL_MIN
.
Причина, по которой у нас есть C ++, состоит в том, чтобы упростить задачу. Вместо int array[100][100]
объявления целочисленного массива с автоматической продолжительностью хранения и фиксированными границами 100
массивов 100 int
каждый, вы можете вместо этого использовать vector<vector<int>> array;
и позволить C ++ обрабатывать границы и управление памятью для вас. Вместо того, чтобы зацикливаться на некоторых фиксированных границах, вы просто используете цикл auto range for
(C ++ 11), чтобы зациклить то, что заполнено. (это также устраняет необходимость передавать границы вашей функции, вместо этого просто передайте ссылку на array
).
Вместо суммирования внутренних и внешних циклов и вычисления каждого среднесуточного значения вы можете просто циклически повторять ежедневные данные, используя accumulate
для суммирования значений каждого дня, а затем просто делить на .size()
суточного вектора.
Позволяя C ++ выполнять большую часть работы за вас, уменьшается количество циклов, суммирования и усреднения, необходимых, например,
#include <iostream>
#include <vector> /* for vector */
#include <numeric> /* for accumulate */
#include <limits> /* for numeric_limits */
using namespace std;
/* choose a meaningful return type, and return a value */
double largestaverage (vector<vector<int>>& array)
{
/* initialize largest sufficiently small (all vals could be negative) */
double largest = std::numeric_limits<double>::min();
for (auto day : array) { /* loop over each day vector */
double avg = accumulate (day.begin(), day.end(), 0) /
static_cast <double>(day.size()); /* compute avg */
if (avg > largest) /* check against largest */
largest = avg;
}
return largest; /* return largest */
}
int main (void) {
vector<vector<int>> array; /* declare vector of vectors */
int days, measurements;
if (!(cin >> days >> measurements)) { /* VALIDATE read of input */
cerr << "error: invalid format for days/measurements\n";
return 1;
}
for (int i = 0; i < days; i++) { /* loop over days */
vector<int> tmp;
for (int k = 0; k < measurements; k++) { /* loop over measurements */
int msrmt;
if (!(cin >> msrmt)) { /* VALIDATE read of input */
cerr << "error: invalid format row '" << k + 1 << "'\n";
return 1;
}
tmp.push_back(msrmt); /* add msrmt to tmp vector */
}
array.push_back(tmp); /* add tmp vector to array */
}
/* output results */
cout << "largest daily avg: " << largestaverage(array) << endl;
}
(вы могли бы даже устранить необходимость читать первую строку вашего файла данных и просто читать дни как string
с getline
и создавать цикл stringstream
и цикл с >>
до int
до .push_back()
)
Оба подхода хороши, первый - просто C, и в этом нет ничего плохого, второй использует некоторые тонкости C ++. Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.