简体   繁体   中英

How to make a value in C++ undefined?

I was working on a little program that would take a number as input, check if it's bigger than the variable largest and check if it's smaller than the variable smallest . Those variables were supposed to keep track of, well, the largest and smallest value entered so far.

The only problem is that both values start off holding garbage values, so I tried to assign both to zero, but when I do so the program breaks, because when I enter five for example it's supposed to be largest and smallest value but instead C++ assigns zero to the smallest value.

#include<iostream>

int main() {
    double a, largest, smallest;
    while (std::cin >> a) { 
        if (largest < a)
            largest = a;
         if (smallest > a)
            smallest = a;

        std::cout << "The smallest so far: " << smallest <<'\n';
        std::cout << "The largest so far: " << largest << '\n';
    }
}

The simplest approach would be to set smallest to the largest possible value, and largest to the smallest possible value:

double largest = std::numeric_limits<double>::lowest();
double smallest = std::numeric_limits<double>::max();

If you actually want to make a variable have no value, that's what std::optional is for. std::optional<double> largest; would be initialized to have no value at all.

With std::optional. https://en.cppreference.com/w/cpp/utility/optional The std::optional can have, or not, a value. At start, it hasn't value. You can use it to handle the state "don't have yet a value assigned"

Here an example with your case:

#include<iostream>
#include <optional>

int main() {
    double a;
    std::optional<double> largest, smallest;
    while (std::cin >> a) {
        if (largest.has_value() == false || largest < a)
            largest = a;
        if (smallest.has_value() == false || smallest > a)
            smallest = a;

        std::cout << "The smallest so far: " << smallest.value() << '\n';
        std::cout << "The largest so far: " << largest.value() << '\n';
    }
}

With a subtle (but significant) change in the two comparisons, one could initialize largest and smallest to NaN ( not-a-number ) values and then take advantage of the fact that all comparisons to NaN values return false :

#include <iostream>
#include <cmath>

int main()
{
    double a, largest = std::nan(""), smallest = std::nan("");
    while (std::cin >> a) {
        if (!(a <= largest))
            largest = a;
        if (!(a >= smallest))
            smallest = a;

        std::cout << "The smallest so far: " << smallest << '\n';
        std::cout << "The largest so far: " << largest << '\n';
    }
    return 0;
}

This is not really a significant improvement on the answer provided by cdhowie , but I'm nonetheless offering it as an alternative approach.

The reason for the behaviour you see is that largest and smallest are uninitialised, and then their values are accessed in the tests (if largest < a) and if (smallest > a) respectively. Accessing their values (which is necessary in any comparison) then causes undefined behaviour.

One fix is to ensure their values are initialised before the first attempt to access their values.

if (std::cin >> a)
{
    smallest = largest = a;

    do
    { 
        if (largest < a)      // Safe since variables are initialised
           largest = a;
        else if (smallest > a)
           smallest = a;
        std::cout << "The smallest so far: " << smallest <<'\n';
        std::cout << "The largest so far: " << largest << '\n';
    }  while (std::cin >> a);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM