【问题标题】:Problems with a program to get every number be greater or smaller than the numbers before and after itself使每个数字都大于或小于自身前后数字的程序的问题
【发布时间】:2021-01-28 15:24:28
【问题描述】:

我想编写一个程序,用这个规则获取数字: 每个数字都大于或小于自身前后的数字。喜欢:3 1 4 2 6 0 8 3 5 16

只要违反了这条规则,就停止获取号码。

int a, b, c;
bool flag = true;
cin >> a;

while (flag)
{
    cin >> b;
    cin >> c;

    if ((b < a && b < c) || (b > a && b > c))
    {
        flag = true;
        a = c;
    }
    else
    {
        break;
    }
}

我的代码适用于某些输入,但对于此输入:3 1 4 6 当我输入 6 时,程序必须停止,但它会继续输入下一个数字。我该怎么做才能解决它?

【问题讨论】:

  • 您遇到的一个问题:在第一个数字之后,您总是同时要求两个数字。因此,在您的示例中,您读取 3,然后是 (1, 4),然后是 (6, ___)。所以你的程序总是会在读取 6 后要求输入一个数字。提示:您可以在没有c 变量的情况下完成此任务。
  • 我一定是遗漏了一些东西,如果你还没有读过一个数字,你怎么能用它后面的数字来测试它们呢?
  • 我认为他们试图解释数字序列应该在大于和小于前一个值之间交替。

标签: c++


【解决方案1】:

解决这个问题需要大量的逻辑评估。所以,我们需要很多布尔表达式和 if 语句。

解决方案的一个关键是跟踪 2 个值:

  • 当前读取值
  • 先前读取的旧值

我们总是可以比较这些值,然后做出决定。问题是我们一开始没有“以前的”值。所以,我们需要做一个特殊的处理,首先从用户那里读取一个值,并将其存储为上一个值,然后总是在循环中读取一个当前值。

在循环结束时,我们会将当前值赋给“previuosValue”。然后在下一次循环运行中,我们总是只需要从用户那里读取当前值。

蚂蚁这两个值,我们可以在一个while循环中比较。

我们将当前值与之前的值进行比较,并根据结果定义一个“方向”标志以进行进一步比较。

这是我们在读完第二个数字后做的。之后,方向总是确定的,永远不会改变。


例如,如果当前值大于上一个值,那么在下一个循环中,下一个值必须更小。反之亦然。

例子:

  • 第一个值:2
  • 第二个值:6

第二个值大于第一个值。因此,对于我们期望的下一个值

小 --> 大 --> 小 --> 大 --> 小 --> 大 --> 。 . .

等等。这永远不会改变。


反之亦然。

  • 第一个值:9
  • 第二个值:1

第二个值小于第一个值。因此,对于我们期望的下一个值

大 --> 小 --> 大 --> 小 --> 大 --> 小 --> 大 --> 。 . .


在处理完“下一个”数字后,方向标志总是会反转。

然后我们可以在下一次循环运行中评估停止条件。比较是否会产生我们期望的值和方向?

如果不是,或者如果值相等,那么我们停止输入。

当然,我们不会在第一个循环中进行这种评估,因为那样的话,我们总是有一个有效的对,然后再计算方向。

所以,你看。我们总是只需要 2 个变量。

与往常一样,有许多可能的实现方式。请参阅以下示例以获取解决方案:

#include <iostream>

int main() {

    // Read initial previous number (The first number)
    if (int previousNumber{}; std::cin >> previousNumber) {

        // Flag that indicates, if we should continue reading new numbers or not
        bool continueToRead{ true };
        // First number needs special treatment, there is no other number
        bool firstCheck{ true };

        // The "direction" of the comparison
        bool nextNumberMustBeSmaller{false};

        // Read numbers in a loop
        while (continueToRead) {

            // Read current (next) number
            if (int currentNumber{}; std::cin >> currentNumber) {

                // After heaving read the first value in the loop, we can detect the direction
                if (firstCheck) {
                    // Get the "direction" of the comparison for the next numbers
                    // If the number is bigger than last number
                    if (currentNumber > previousNumber)

                        // Then next value muste be smaller
                        nextNumberMustBeSmaller = true;

                    // If this number is smaller
                    else if (currentNumber < previousNumber)

                        // then next number must be bigger
                        nextNumberMustBeSmaller = false;
                    else
                        continueToRead = false;

                    // First check has been done
                    firstCheck = false;
                }
                else {
                    
                    // Find out the stop condition
                    if (
                        // Direction is smaller but number is bigger or
                        (nextNumberMustBeSmaller and (currentNumber > previousNumber)) ||
                        // Direction is bigger but number is smaller or
                        (not nextNumberMustBeSmaller and (currentNumber < previousNumber)) ||
                        // Or numbers are equal
                        (currentNumber == previousNumber)) {

                        // Then: Stop reading values
                        continueToRead = false;
                    }
                    nextNumberMustBeSmaller = not nextNumberMustBeSmaller;
                }

                // Remember the last value. So, for the next loop rund, the current value will become the previous one
                previousNumber = currentNumber;
            }
            else {
                std::cerr << "\n\nInvalid input\n\n";
                continueToRead = false;
            }

        }
    }
    else std::cerr << "\n\nInvalid input\n\n";

    return 0;
}

在启用 C++17 的情况下进行编译。

【讨论】:

    【解决方案2】:

    如果我们按照您的问题给出的任务,这里有一些观察,但我认为您可能以某种方式误解了该任务。

    每个数字都大于或小于自身前后的数字

    1. 小表示不相等。
    2. 您无法检查下一个号码。你甚至不知道有没有下一个号码,所以你只能检查上一个号码
    3. 最后的条件变成“如果当前和最后一个数字相等则停止”

    在代码中可能如下所示:

    int a, b;
    cin >> a;
    
    while (cin >> b && a != b)
    {
        a = b; // current number becomes the last number
    }
    

    请注意,我删除了flag,因为它从未设置为falsebreak 就足够了。我将cin &gt;&gt; b 移动到循环条件中以验证输入。然后事实证明,我们也可以将if-block 合并到循环条件中。

    【讨论】:

    • OP 想要的条件是每个数字都小于两个邻居或大于两个邻居。即原来的条件是正确的。
    • @molbdnilo 你确定吗?我从 OPs 语句 3 1 4 6 当我输入 6 时程序必须停止” 中得到这个想法。但是英语不是我的母语,所以也许这就是我理解错误的原因。
    猜你喜欢
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 2023-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多