2

I am finding the minimum value being input from stdin. For example,

1
5
3
2
-6
7

should return -6 to stdout.

My question is if it is a better practice to initialize my minimum value to INT_MAX or to the first scanf call.

#include <stdio.h>
#include <limits.h>

int main() {
    int min = INT_MAX;

    int input;
    while (scanf("%d", &input) != 0) {
        if (input < min) min = input;
    }
    
    printf("Minimum: %d", min);
}

OR

#include <stdio.h>

int main() {
    int input;
    int min = scanf("%d", &input);

    while (scanf("%d", &input) != 0) {
        if (input < min) min = input;
    }

    printf("Minimum: %d", min);
}
1
  • 1
    what would you consider the expected result if there are no valid inputs? Commented Dec 6, 2022 at 8:21

6 Answers 6

4
int min = scanf("%d", &input);

does not initialize min to the input value - scanf returns the number of items successfully read or assigned, or EOF on end of file or error.

So if your first input was -1234, min would be initialized to 1; if your subsequent inputs were all larger than -1234, your program wouldn't show the correct minimum value.

For what you're doing, initializing min to INT_MAX is the correct action.

Also, your loop condition should be

while ( scanf(  "%d", input ) == 1 )
  ...

You want to continue processing while your scanf calls are successful, and scanf can return either 0 for a matching failure or EOF for an input error.

6

It’s not so much correctness, more deciding what answer shall be chosen.

If you were adding, you would want to say “the sum of 0 numbers” is something that, if you add X to it, gives X”. That is easy. It is 0.

If you were multiplying, you would want to say “the product of 0 numbers” is something that, if you multiply it by X, gives X. That is easy. It is 1.

If you are taking the minimum, you want to say “the minimum of 0 numbers” is a value which, if you take the minimum of it and X, gives you X. That is easy. It is plus infinity.

In your particular case there are two problems. One is that the integer representations we use cannot represent plus infinity. You have to make a decision here - and replacing “plus infinity” with INT_MAX has a lot to be said for it. It makes it impossible to distinguish between “the minimum of 0 numbers” and, say, “the minimum of, say, 3 numbers all of which are INT_MAX”. But in the real world that often does not matter.

The second problem is that in the context of a program you may actually want to distinguish the “0 numbers” case. Then you need to realise that your alleged “min” function is actually returning two answers, not one: (1) are there more than 0 numbers? (2) if there are, what is their minimum?

Finally - the answer here is what you decide it to be, nothing else. There is no “right answer somewhere out there” which you are attempting to find. The decision is yours.

2

Minimum/maximum are tricky. There is a reasonable sum of zero numbers - zero. There is a reasonable product of zero numbers - one. There is no reasonable minimum or maximum of zero values. Take strings - there is no largest string.

So before you write any code you decide what to return if there are zero values. Like your INT_MAX is no reasonable result if there are no values. You could return a result and a bool. You might warn the caller that no values is illegal and assert. In some languages you can use optional values.

I’d have a Boolean that indicates no input yet. Then process input according to that Boolean. Say the user can enter numbers, and you want to return the largest prime they entered. Or the first customer in New Orleans in alphabetical order, then you’d need two loops.

1

In a language that lacks an explicit None value, the right thing to do is to initialize the accumulator to a value that preserves correctness. In this case, INT_MAX does the job. Duplicating code would obscure the logic of your algorithm (although not very much, since here it's just a single expression), and readability is almost as important as correctness.

2
  • 1
    But wouldn't initialization to INT_MAX be incorrect in case no number is entered? By the correctness argument, I'd favour the second solution (or a boolean flag has_value).
    – amon
    Commented Oct 22, 2022 at 19:26
  • Int_max is not reasonable for “the smallest of 0 values”. It’s worse if you look for the first string in alphabetical order -there is no last string.
    – gnasher729
    Commented Nov 1, 2022 at 21:05
1

The answer really should be chosen by "What should the correct result be if no input is given (EOF is reached)."

The former can print a result of INT_MAX. The latter prints an unspecified value. I'd argue unspecified value are worse than a predictable large value -- they can even change between invocations of your program.

If you constrain the problem to guarantee at least one input, then there's an amount of personal preference involved. I like to initialize to INT_MAX myself because it means the scanf only appears once. For something simple like reading a single value, it probably matters little. However, often the processing done for each input is much more expansive, and it's really nice not to duplicate code.

I've also been known to add a boolean named first into the mix. It is initially true, and set to false after the first pass through the loop. This lets me be very explicit about which operations are common, only used on the first pass, or only used in subsequent passes. if (first) turns out to be quite easy to read.

1

My question is if it is a better practice to initialize my minimum value to INT_MAX or to the first scanf call.

Option 3 is best.

  1. "initialize my minimum value to the first scanf call" is not a reasonable option as scanf() returns the count of successful scans - nothing to do with minimum/maximum values read.

  2. "initialize my minimum value to INT_MAX" is reasonable, yet by itself does not distinguish the case where INT_MAX was the minimum input and the case of no inputs.

  3. The best is a 3rd option. Initialize with INT_MAX, to simplify code and also set a flag when valid input occurs.

Also scanf() may return values other than 0, 1. EOF is possible. Rather than compare against one unacceptable value (0), compare against the desired one (1). This also prevents the infinite loop of scanf("%d", &input) != 0 on end-of-file.

int main() {
    bool valid_input = false;
    int min = INT_MAX;

    int input;
    while (scanf("%d", &input) == 1) {
       valid_input = true; // Set the flag to indicate at least 1 value read.
       if (input < min) min = input;
    }
    
    if (valid_input) printf("Minimum: %d\n", min);
    else printf("No Minimum\n");
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.