Kevin
Kevin

Reputation: 5

Infinite loop issue in c

The code below compiles, however when I run it I have an error that causes an infinite loop. The loop doesn't even get to scanf where I should be taking in the new value instead it just always prints the prompt. What exactly have I done wrong to cause this issue..

#include <stdio.h>
#include <stdbool.h>

//variables
bool flag = false;
int input = 0;
//function protoypes
void  get_input(void);
bool  is_valid(int);
void  print_pattern(int number);

int main(){
    get_input();

    print_pattern(input);
    return 0;
}

void get_input(){
    while(flag == false){
        printf("please enter an odd number betwen 1 and 9\n");
        scanf("%d", &input);
        if(is_valid(input)){
            flag = true;
        }else{
            flag = false;
        }

    }
}

bool is_valid(int number){
    if(number == 1 || number == 3 || number == 5 || number == 7 || number ==  9){
        return true;
    }else{
        return false;
    }
}

void print_pattern(int number){
    int i = 0;
    for(i = 0; i < number; i++){
        printf("%s",i);
    }
}

Upvotes: 0

Views: 83

Answers (4)

M Oehm
M Oehm

Reputation: 29136

You have fallen into a scanf trap: When you try to scan a decimal number from a stream (such as a file or stdin), but the stream doesn't contain a valid number, the stream is reset to where it was before the scanning. That means, your while loop scans the same invalid input over and over.

A solution is to read a string first (with scanf("%s", ...) or with fgets and then parse that string with sscanf or, maybe better, with strtol. All these functions have an error condition, described in their documentation, which you should check. There is also the issue of how to treat the unexpected end of file which you may encounter during input.

Finally, you should make the flag local to get_input. Also consider get_input to return the read value with a special value, say -1, to indicate end of file.

An example implementation might look like this.

int get_input()
{
    char buf[80];
    int input = 0;
    bool flag = false;

    while (flag == false) {
        printf("please enter an odd number betwen 1 and 9\n");

        if (fgets(buf, sizeof(buf), stdin) == NULL) return -1;
        flag = (sscanf(buf, "%d", &input) == 1 && is_valid(input));
    }

    return input;
}

(Yes, reading input other than the in a quick-and-dirty way isn't easy.)

Others have already pointed out the wrong format specifier, which -Wall should have caught.

Upvotes: 1

VolAnd
VolAnd

Reputation: 6407

The problem not in the loop. The real problem in the output (%s istead of %d):

void print_pattern(int number){
    int i = 0;
    for(i = 0; i < number; i++){
        printf("%d",i);  // output number
    }
}

and maybe in the input buffer:

void get_input(){
    while(flag == false){
        printf("please enter an odd number betwen 1 and 9\n");
        scanf("%d", &input);
        while( getchar() != '\n' ); // clean input bufer
        if(is_valid(input)){
            flag = true;
        }else{
            flag = false;
        }
    }
}

also consider the following validation function:

bool is_valid(int number){
    return (number % 2); // check number
}

Upvotes: 0

Arun A S
Arun A S

Reputation: 7026

The infinite loop is caused probably because you entered a character instead of an integer. Maybe this will help

void get_input(){
    char ch;
 while(flag == false){
    printf("please enter an odd number betwen 1 and 9\n");
    scanf("%d", &input);
    while((ch=getchar()!= '\n') && ch != EOF);   // this flushes the input buffer to get rid of characters. 
    flag = is_valid(input);       // This is better
  }

}

I also found an issue with your code. i is an int but you are using %s ( which is used for strings ) in

printf("%s",i);

Change it to

printf("%d",i);

instead

Upvotes: 0

SMA
SMA

Reputation: 37103

Your loop wont exit unless you enter an odd number.

Also %s represents string, so you might need to change your print statement to:

printf("%d",i);
         ^

Instead of do if else, change your code to:

flag = is_valid(input);

Upvotes: 1

Related Questions