-2

I need to write a program which calculates fibonacci sequence but I stuck because of this infinite loop.

When I enter -5 it prints Please enter "positive" term(s) number:.

Then I enter "a" and it prints Please enter "numeric" term(s) number: infinitely.

I couldn't figure out why it is. Thanks for any help.

(note : I tried to use fflush(stdin) but didn't fix this. I thought maybe \n char left in the stdin buffer.)

#include <stdio.h>
void calculate_fibonacci_sequence(){
        int n,is_entry_valid;
        int flag = 0;
        printf("Please enter term(s) number : ");
        while(!flag){
                is_entry_valid = scanf("%d",&n);
                if(is_entry_valid == 1){
                        if(n > 0){
                                flag = 1;
                        }else{
                                printf("Please enter \"positive\" term(s) number: ");
                        }
                }else{
                        printf("Please enter \"numeric\" term(s) number: ");
                }
        }
}

int main(){
        calculate_fibonacci_sequence();
        return(0);
}
Baran
  • 131
  • 8
  • 1
    In the `else{ printf("Please enter \"numeric\" term(s) number: "); }` block, add code the reads the offending non-integer input, like `scanf("%*s");`. – chux - Reinstate Monica Mar 23 '21 at 20:23
  • thanks to you now I understand why it is and scanf("%*s"); fix this. But still I am confused about why fflush(stdin) can't remove 'a' from the input stream. – Baran Mar 23 '21 at 20:30
  • 1
    @BaranSAHİN: `fflush` is not defined for input streams. A few implementations such as MSVC do implement `fflush( stdin )` to clear out all input, but that's specific to the implementation; it's not standard behavior and you shouldn't rely on it. – John Bode Mar 23 '21 at 20:36
  • Thanks. Now I understand. – Baran Mar 23 '21 at 20:37

3 Answers3

1

%d tells scanf to skip over any leading whitespace, then read characters up to the next non-digit character; that non-digit character is left in the input stream. Without a call to getchar or fgetc or similar, that character will not be removed.

So in the else branch of your if (is_entry_valid == 1) statement, you'll need to add something like

while ( getchar() != '\n' )
  ; // empty loop

which will remove everything up to and including the newline from the input stream.

John Bode
  • 119,563
  • 19
  • 122
  • 198
1

fgets can be used to read a line then parse the line with sscanf.
In the case of non-integer input, the problem input has been removed by fgets so trying again for acceptable input is easy to do.

#include <stdio.h>
void calculate_fibonacci_sequence(){
    char line[100] = "";
    int n,is_entry_valid;
    int flag = 0;
    printf("Please enter term(s) number : ");
    while(!flag){
        fgets ( line, sizeof line, stdin);
        is_entry_valid = sscanf(line, "%d",&n);
        if(is_entry_valid == 1){
            if(n > 0){
                flag = 1;
            }else{
                printf("Please enter \"positive\" term(s) number: ");
            }
        }else{
            printf("Please enter \"numeric\" term(s) number: ");
        }
    }
}

int main(){
    calculate_fibonacci_sequence();
    return(0);
}
user3121023
  • 8,181
  • 5
  • 18
  • 16
1

You need to flush stdin when you get a bad user input in order to clean the input buffer, this code should work:

#include <stdio.h>

void calculate_fibonacci_sequence(void)
{
    int n, is_entry_valid;
    int flag = 0;

    printf("Please enter term(s) number : ");
    while (!flag)
    {
        is_entry_valid = scanf("%d",&n);
        if (is_entry_valid == 1) {
            if (n > 0) {
                flag = 1;
            } else {
                printf("Please enter \"positive\" term(s) number: ");
            }
        } else {
            printf("Please enter \"numeric\" term(s) number: ");

            int c;
            // Flush stdin
            while ((c = fgetc(stdin)) != EOF && c != '\n');
        }
    }
}

int main(void)
{
    calculate_fibonacci_sequence();
    return(0);
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94