Мне нужно найти строку в массиве, которая имеет наибольшую среднюю температуру. Существует две основные переменные: одна указывает, сколько дней проводят измерения температуры, а другая указывает, сколько измерений проводилось каждый день. К счастью, в большинстве случаев, которые я пробовал, программа показывает правильный день с наибольшей средней температурой. Тем не менее, в некоторых случаях, таких как следующие, это не работает, и я не могу понять, почему.
Если я вставлю следующие значения:
4 3
8 8 10
12 10 7
14 12 11
11 10 12
Он должен отображать 2, так как это день с наибольшей средней температурой. Однако по какой-то причине вместо этого отображается 0.
Вот код, который я использую:
include <iostream>
using namespace std;
void largestaverage (int array[100][100], int amountDays, int amountMeasurements, int &largest, int &largestDay, int dailyAverage)
{
largest=array[0][0];
largestDay=0;
for(int i=0; i<amountDays; i++)
{
dailyAverage=0;
for(int k=0; k<amountMeasurements; k++)
{
dailyAverage+=array[i][k];
dailyAverage=dailyAverage/amountMeasurements;
if(dailyAverage>largest)
{
largest=array[i][k];
largestDay=i;
}
}
}
}
int main ()
{
int array[100][100], amountDays, amountMeasurements, largest, largestDay, dailyAverage=0;
cin>>amountDays;
cin>>amountMeasurements;
for (int i=0; i<amountDays; i++)
{
for (int k=0; k<amountMeasurements; k++)
{
cin>>array[i][k];
}
}
largestaverage (array, amountDays, amountMeasurements, largest, largestDay, dailyAverage);
cout<<largestDay<<endl;
return 0;
}
Установите наибольшее среднее значение, которое вы видите вместо largest=array[i][k]
,
if(dailyAverage>largest)
{
largest=dailyAverage;
largestDay=i;
}
Кроме того, как упомянуто «@Some Programmer Dude», лучше всего было бы рассчитать среднее значение за пределами цикла.
Редактировать:
Инициализируйте самое большое число до невероятно малого числа, так как это, скорее всего, вызовет логическую ошибку.
largest=-1000;
Джон, очевидно, что вы немного боретесь с пониманием того, какие значения вам нужно передать в качестве параметров вашей функции, и как обрабатывать циклы для получения наибольшего среднесуточного значения на основе ваших данных.
Для начала, единственные параметры, которые необходимо передать largestaverage()
являются самим массивом, а границы указывают количество days
а также measurements
принято на каждый день. Только из этой информации вы можете вычислить наибольшее среднесуточное значение, но как вернуть это наибольшее среднесуточное значение main()
так это можно использовать?
Ключ, чтобы выбрать значимый вернуть 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 ++ обрабатывает границы и управление памятью для вас. Вместо того, чтобы зацикливаться на некоторых фиксированных границах, вы просто используете авто диапазон 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 ++. Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.