-1
#include <stdio.h>

int main(void)
{
    int i;
    while (1)
    {
        if (scanf("%i", &i) == 1)
        {
            break;
        }
        fflush(stdin);
    }
}

This code is supposed to ask the user for input until they input an integer, but it only works if the user inputs an integer in the first iteration. If the user first inputs a character, for example, then an integer, the loops continues iterating.

The only answer I have found to my problem said using fflush(stdin) should work, but it doesn't.

Alan
  • 9
  • 2
  • 4
    Please check the documentation of `scanf` about what happens when it fails. Also: https://stackoverflow.com/questions/2979209/using-fflushstdin – Bob__ Feb 23 '23 at 18:06
  • Scanf seems to return the number of successful formats done, in your case, scanf returns 1 for the 1 (and only) format you do. Therefore comparing the return value of scanf to 1 will always be true. – xihtyM Feb 23 '23 at 18:06
  • Just put the scanf before the if statement and compare i to 1 and it will be fixed. – xihtyM Feb 23 '23 at 18:07
  • 1
    @xihtyM And what happens when `scanf` fails to perform a conversion? This is a poor assessment of the example code, and a misunderstanding of `scanf` (and program flow...). – Oka Feb 23 '23 at 18:09
  • @xihtyM, shouldn't it return 0 if the input is invalid, since nothing was formatted successfully? – Alan Feb 23 '23 at 18:10
  • @xihtyM, why would you compare i with 1? The value of i doesn't matter; it just has to be an integer. – Alan Feb 23 '23 at 18:11
  • @Bob__, I have: "Return Values: >0: The number of values converted and assigned successfully. 0: No value was assigned. <0: Read error encountered or end-of-file(EOF) reached before any assignment was made." So it should return 1 when successful in this case, and something else otherwise, right? – Alan Feb 23 '23 at 18:14
  • 1
    `scanf` doesn't consume the input when the conversion fails. So it will just keep failing on the same character. – Emanuel P Feb 23 '23 at 18:14
  • 6
    `fflush(stdin);` is *undefined behaviour* (for an input stream). It is not guaranteed to clear the unprocessed characters from the input. – Weather Vane Feb 23 '23 at 18:14
  • Yes, but consider what Emanuel P said in their comment. – Bob__ Feb 23 '23 at 18:16
  • @Bob__ that is *why* OP is attempting to flush the input, and as they posted, it does not work. OP **knows** that the input needs to be removed. – Weather Vane Feb 23 '23 at 18:17
  • 4
    OP has shown a competent understanding of `scanf`, and an *intent* to clear the input stream when it fails, thus I believe this is ultimately a duplicate of [Using fflush(stdin)](https://stackoverflow.com/q/2979209/2505965), as previously mentioned. – Oka Feb 23 '23 at 18:23
  • Try `int c; while ((c = getchar()) != EOF && c != '\n') ;` but, if it the input is likely to be malformed, it is IMO better to use `fgets()` and `sscanf()` or other string processing function. – Weather Vane Feb 23 '23 at 18:24
  • Related: [Validate the type of input in a do-while loop](https://stackoverflow.com/q/31633005/12149471) – Andreas Wenzel Feb 23 '23 at 19:20
  • @Alan sorry, "shouldn't it return 0 if the input is invalid, since nothing was formatted successfully?" yes this seems to be the case. "why would you compare i with 1? The value of i doesn't matter; it just has to be an integer.", I seem to have presumed that you wanted to compare the users input to 1, not the output. – xihtyM Feb 24 '23 at 16:53
  • @Oka if it fails, as scanf formatted 0 items, it should return 0 based off what I said. – xihtyM Feb 24 '23 at 16:54

1 Answers1

3

From C17:

If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.

where possible undefined behavior ranges from:

ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

You can not use fflush() on an input stream in a portable manner. See Using fflush(stdin).

A better solution would be to read a whole line with fgets(), and then parse it with sscanf(), strtol(), et cetera.

Harith
  • 4,663
  • 1
  • 5
  • 20