【问题标题】:Finding which row in an array has the largest average temperature查找数组中哪一行的平均温度最高
【发布时间】:2018-11-09 07:23:46
【问题描述】:

我需要在数组中找到平均温度最高的行。有两个主要变量,一个表示进行温度测量的天数,另一个表示每天进行多少次测量。幸运的是,在我尝试过的大多数情况下,该程序确实指示了平均温度最高的正确日期。但是,在某些情况下,例如以下情况,它不起作用,我无法弄清楚原因。

如果我插入以下值:

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;
}

【问题讨论】:

  • 现在似乎是learn how to debug your programs 的最佳时机。
  • 一个可能的提示:您对这些天的平均值的计算看起来非常可疑。当你得到总和时,应该在内部循环之后计算平均值。
  • 另外你为什么要这样初始化largest?如果array[0][0] 包含一些非常大的值,大于任何每日平均值怎么办?

标签: c++ arrays average temperature


【解决方案1】:

John,很明显,您在理解需要将哪些值作为参数传递给函数以及如何处理循环以根据您的数据获得最大的每日平均值方面有些困难。

首先,需要传递给largestaverage() 的唯一参数是数组本身,以及指示每天使用的days 和measurements 数量的边界。仅根据这些信息,您就可以计算出最大的日平均值——但是如何将最大的日平均值返回到 main() 以便可以使用?

关键是为你的函数选择一个有意义的returntype,这样你就可以return需要的信息。由于您正在验证您在main() 中读取到array 的数据(不是吗?),几乎不需要选择返回类型来指示计算成功/失败,但选择void 并没有任何好处根本没有,你需要通过参考。

虽然这可行,但还有一种更基本的方法来处理返回 - 只需将 return 的值传递给所需类型的 main()。这完全消除了传递largest 的需要。函数总是可以返回自己的类型。但是,什么类型? double 是一个不错的选择,因为 sum 与 measurements 的数字相除的结果将产生 floating-point 值 -- 除非您打算 integer分裂。

更改largestaverage 的返回类型,并重新排列循环,以便每天计算sum 和avg,并在第二天正确重新初始化,包括&lt;limits&gt;这样您就可以使用标准方法将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++ 完成大部分工作

虽然在 C++ 中使用基本数组类型和手动 for 循环绝对没有任何问题,但出于所有实际目的,除了使用 cin/cout 而不是 @987654350 之外,您的代码和上面的代码只不过是标准 C @ 并使用numeric_limits&lt;double&gt;::min() 而不是DBL_MIN。

我们拥有 C++ 的原因是为了让事情变得更简单。不用int array[100][100] 声明一个具有自动存储持续时间的整数数组,以及每个100 数组的固定边界100 int,您可以改用vector&lt;vector&lt;int&gt;&gt; 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 并使用 &gt;&gt; 循环到 @987654366 @到.push_back())

两种方法都很好,第一种基本上是 C 语言,没有任何问题,第二种方法利用了 C++ 的一些优点。如果您还有其他问题,请仔细查看并告诉我。

【讨论】:

    【解决方案2】:

    将最大值设置为您看到的最大平均值,而不是 largest=array[i][k]。

    if(dailyAverage>largest)
    {
       largest=dailyAverage;
       largestDay=i;
    }
    

    此外,就像提到的“@Some 程序员老兄”一样,最好在循环外计算平均值。

    编辑: 将您的最大值初始化为一个不可能的小数字,因为它很可能会导致逻辑错误。

    largest=-1000;
    

    【讨论】:

    • 这里不会出现类型不匹配的情况。 array[0][0] 是一个 int,largest 通过引用传递为 int 而不是 int*。但这可能会导致逻辑错误。理想情况下,最大应该初始化为显着的小数字,例如 -1000 左右。
    猜你喜欢
    • 1970-01-01
    • 2012-10-16
    • 2022-10-26
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多