3

I am working on a simple program in C that asks the user to give an input in a loop until they enter the letter Q when prompted. When I run the program however, it immediately skips the prompt to enter a character and asks the user to enter another input. Any idea why this happens and how I can fix it?

Here is my code:

    while (exit != 'q' && exit != 'Q') {
        printf("Please enter the grade for assignment #%d: ", assignmentNumber);
        scanf("%lf", &gradeInput);

        printf("Press q to quit, press any other character to continue: ");
        exit = getchar();
    } 

I tried changing the getchar to scanf(%c%*c) like I saw someone suggest under a post with a similar problem. It did make it so the prompt to enter a character actually worked, but the loop no longer ended when Q is entered.

2
  • 4
    Don't mix scanf() and getchar(). Preferably use exclusively fgets() for ALL user input (for the grade, for the quit character, ...). scanf() was not designed for user input; getchar() alone can be a PITA; fgets() works like getchar() on steroids. Commented Oct 29, 2023 at 17:02
  • A duplicate of scanf() leaves the newline char in the buffer. Commented Oct 29, 2023 at 17:31

3 Answers 3

4

The problem is getchar() reads the next character from the input line after the floating point number typed by the user. This could be anything, but in most cases, this character will be the newline stored into the input stream when the user hit the Enter key.

You should modify your program to:

  • read input one line at a time
  • check for end of file
  • check for success in the conversion of the user input as a number

Here is a modified version:

#include <stdio.h>

int main() {
    double gradeInput;
    int assignmentNumber = 1;

    for (;;) {
        char input[128];
        printf("Please enter the grade for assignment #%d: ", assignmentNumber);
        if (!fgets(input, sizeof input, stdin)) {
            /* end of file */
            break;
        }
        if (sscanf(input, "%lf", &gradeInput) != 1) {
            printf("invalid input: %s\n", input);
            continue;
        }
        /* handle the grade */
        // [...]
        assignmentNumber++;

        printf("Press q to quit, press any other character to continue: ");
        if (!fgets(input, sizeof input, stdin)) {
            /* end of file */
            break;
        }
        if (input[0] == 'q' || input[0] == 'Q')
            break;
    }
    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

3

This call of getchar

exit = getchar ();

can read new line character '\n'.

Instead change the statement like

scanf( " %c", &exit );
        ^^^

provided that exit has the type char.

Pay attention to the leading space in the format string. It allowes to skip white space characters.

Also it would be better to change the while loop to do-while loop like

do 
{
    printf("Please enter the grade for assignment #%d: ", assignmentNumber);
    scanf("%lf", &gradeInput);

    printf("Press q to quit, press any other character to continue: ");
    scanf( " %c", &exit );
} while ( exit != 'q' && exit != 'Q' );

Comments

2

It looks like the issue you're facing is related to the way the newline character left in the input buffer after reading a double (with scanf("%lf", &gradeInput)) is affecting the behaviour of getchar(). The getchar() function reads the next character from the input buffer, which includes any leftover newline characters.

To fix this issue, you can clear the input buffer after reading the grade by consuming the newline character. Here's an updated version of your code:

#include <stdio.h>

int main() {
    char exit = ' ';
    double gradeInput;
    int assignmentNumber = 1;

    do {
        printf("Please enter the grade for assignment #%d: ", assignmentNumber);

        if (scanf("%lf", &gradeInput) != 1) {
            printf("Invalid input. Please enter a valid number.\n");
            while (getchar() != '\n'); // Clear the input buffer
            continue;
        }

        while ((exit = getchar()) != '\n' && exit != EOF); // Clear the input buffer

        printf("Press q to quit, press any other character to continue: ");
        exit = getchar();
        while (getchar() != '\n'); // Clear the input buffer

        assignmentNumber++;
    } while (exit != 'q' && exit != 'Q');

    return 0;
}

In this code, we use a while loop to clear the input buffer by reading characters until a newline character is encountered. This ensures that any leftover characters, including the newline character, are removed from the input buffer before attempting to read the exit character. This should fix the issue and allow your loop to end when Q or q is entered.

6 Comments

Jibel, I think you misunderstood what @chqrlie said. You still have the potentially infinite loop while (getchar() != '\n'); in there.
What other commenters are saying is that you need to check for EOF, too, since getchar() might return this for a number of reasons. Something like: int c; while ((c = getchar()) != '\n' && c != EOF) { continue; } is traditional.
@adabsurdum Did it fixed in the new edit?
Using different input methods and then applying kludges to get round their different behaviour is a hiding to nowhere. Use one input method, preferbly fgets().
You have two more potential infinite loops with while (getchar() != '\n'). Also exit should have type int, not char. You should test for EOF in the while clause of the do / while loop. Using a for(;;) loop with explicit tests and break statements would be more readable and allow for better consistency.
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.