在C++中对数组进行最大值和最小值排序

5
这是一个非常简单且常见的练习,尽管我遇到了一个错误,但我似乎无法理解它,并且无法在任何地方找到解释,因为这可能太具体了。
该程序只是提示用户输入第1到10个人吃了多少煎饼,然后打印出某个人吃的最多的煎饼数量。我的问题是,“手动循环”来排序最大和最小值的工作已经完成,但算法(在这个论坛上强烈推荐使用而不是手动循环)不能正确输出最大值,但对于最小值可以正常工作。
以下是我的代码:
void pancakes() {
    int pan[11];
    int small, big;
    for (int i = 1; i < 11; i++)  // counts to 11-1 and prompts user for pancakes
                                  // eaten by person 1==>10
    {
        cout << "How many pancakes did person " << i << " eat?\n";
        cin >> pan[i];
    }

    big = small = pan[1];  // assigns element to be highest or lowest value

    for (int i = 1; i < 11; i++) {
        if (pan[i] > big)  // compare biggest value with current "big" element
        {
            big = pan[i];
        }
        if (pan[i] < small)  // compares smallest value with current "small" element
        {
            small = pan[i];
        }
    }
    cout << "The person who ate the most pancakes ate " << big << " of them."
             << endl;  // prints biggest value
    cout << "The person who ate the least pancakes ate " << small << " of them."
             << endl;  // prints smallest value

    auto minmax = minmax_element(begin(pan), end(pan));

    cout << "min element " << *(minmax.first) << "\n";
    cout << "max element " << *(minmax.second) << "\n";
}   

以下是控制台返回的内容:
How many pancakes did person 1 eat?
45
How many pancakes did person 2 eat?
64
How many pancakes did person 3 eat?
7
How many pancakes did person 4 eat?
34
How many pancakes did person 5 eat?
87
How many pancakes did person 6 eat?
45
How many pancakes did person 7 eat?
89
How many pancakes did person 8 eat?
32
How many pancakes did person 9 eat?
55
How many pancakes did person 10 eat?
66
The person who ate the most pancakes ate 89 of them.
The person who ate the least pancakes ate 7 of them.
min element 7
max element 1606416304
3个回答

9
auto minmax = minmax_element(begin(pan), end(pan));

虽然 finds 确实找到了最小值/最大值,但是在 C++ 中数组的索引是从 0 开始的。你需要从索引 1 开始填充 int pan[11];

big=small=pan[1]; //assigns element to be highest or lowest value; change to pan[0]
for (int i = 1; i < 11; i++){...} // change to i=0

所以,pan[0]会包含垃圾值(在您的情况下为1606416304),minmax_element将考虑它。
事实上,在C和C++中读取未初始化的变量是未定义的行为,任何事情都可能发生,尽管大多数时候只是读取存储在该内存地址处的内容。
如果您使用C++11(现在应该使用),那么您还可以使用range-based for循环来处理煎饼 :)
for(auto& pancake: pan) // note the reference, we are reading
{
    cin >> pancake; // to read
}

并且

for(auto pancake: pan)
{
    // further processing here, like
    if(pancake < small) { small = pancake;} // etc
}

7

您有一个大小为11的数组,但是只循环了10个元素,导致第一个元素未初始化。这意味着它包含垃圾值(未定义行为),在这种情况下是1606416304,这不是最大值吗?=)

请将您的循环从以下形式进行更改:

for (int i = 1; i < 11; i++)

to:

for (int i = 0; i < 11; i++)

std::minmaxelement() 会按照您所希望的方式运作。


后续:

通常,在使用返回不同于预期结果的函数时,一个常见错误是要检查您提供给该函数的数据。这样,您就可以知道数据和/或函数是否存在问题。在您的情况下,打印数组将使您了解到您的数据有问题!


啊,我明白了!但实际上我没有初始化pan[0]的原因是我不想提示用户输入第0个人吃了多少个煎饼。这样做是否是因为实际情况而不能使用数组呢? - SecureCake
2
你不需要提示输入第0个人,在你的打印语句中,你可以将 << i << 改为 << i + 1 << - AresCaelum
是的,我现在明白了,我会从 pan[0] 开始加上 i+1,非常感谢大家! - SecureCake
或者,可以使用 begin(pan)+1 调用 minmax_element - Saul
是的,@Saul,那可能行得通,但拥有带有垃圾值的数组并不好。 - gsamaras
1
@gsamaras 是的,同意 :) - Saul

2

您的pan数组被定义为有11个元素,但是您只初始化了其中的10个。需要注意的是,pan[0]从未被初始化,因此会具有一些随机值。我猜测您的随机值恰好是1606416304。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接