Thread: Character Input Validation

  1. #1
    Registered User
    Join Date
    Jan 2009
    Posts
    13

    Character Input Validation

    Hello it's me, again...

    I am having a problem with a character input validation function.

    Code:
    char check_letter(void)
    {
        char input, ch;
    
        while (scanf("%c", &input) != 1 || input != 'A' && input != 'P')
        {
            while ((ch = getchar()) != '\n')
                ;
            printf("Enter correct value: ");
        }
    
        return input;
    }
    Basically this function checks if the user input 1) a valid letter character, and 2) the user enters either A or P, and this is case-sensitive.

    When I test this function, I enter in A or P as it asks "Enter a letter (A or P)". When I enter A for example, I get the error message "Enter correct value: "

    Now when I enter in A again or even P the 2nd try, the function accepts the letter as valid input and continues on with the rest of the program.

    Again, I am very new to coding, I have looked at various books and researched on the web but have not found anything useful to tell me how to properly create a function like this.

    I asked a few days ago about integer input validation functions and I got that working, but it appears letters act a bit different?

    I would appreciate any constructive help Thanks!

  2. #2
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    My guess is you have a trailing newline characterfrom some previous input function. Read the Clear input stream FAQ.

    It is hard to tell without seeing more code, like where in your program you called this function.
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  3. #3
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    I suspect you're having a problem with a "scanf()" somewhere, but it's difficult to say without seeing more code. Would you be able to provide more?

    I ran this function from a simple program and it appears to be doing what you want.

    Code:
    #include <stdio.h>
    
    char check_letter(void);
    
    int main(void)
    {
        printf("\nEnter a character:  ");
        check_letter();
    
        return 0;
    }
    Also, why are you doing this in two steps?

    1. Verify valid character
    2. Verify either 'A' or 'P'

    Why not just verify that it's 'A' or 'P'?

  4. #4
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Well, it appears we have the beginning of a consensus. =)

  5. #5
    Registered User
    Join Date
    Jan 2009
    Posts
    13
    Code:
    #include <stdio.h>
    
    int check_hour(void);
    char check_letter(void);
    
    int main(void)
    {
        int hour;
        char letter;
    
        printf("Enter the hour: ");
        hour = check_hour();
        printf("Enter A (for AM) or P (for PM): ");
        letter = check_letter();
    
        return 0;
    }
    
    int check_hour(void)
    {
        int input;
        char ch;
    
        while (scanf("%d", &input) != 1 || (input < 1 || input > 12))
        {
            while ((ch = getchar()) != '\n')
                ;
            printf("Enter correct value: ");
        }
    
        return input;
    }
    
    char check_letter(void)
    {
        char input, ch;
    
        while (scanf("%c", &input) != 1 || (input != 'A' && input != 'P')
        {
            while ((ch = getchar()) != '\n')
                ;
            printf("Enter correct letter: ");
        }
    
        return input;
    
    }
    This is @ matticus, that is what my int main(void) looks like. The check_hour function works fine, but when I check_letter I am having a problem with a newline somewhere, like press enter a few times when entering hour, and it's fine, then press enter a few times on the check_letter and it does different things.

    Different things such as on every 2nd enter it shows the prompt to enter correct letter. And then when I enter either A or P it finally recognizes the letter and then ends the program. I am so lost as to why this check_letter() function is doing this to me.

    I read this thread:

    http://faq.cprogramming.com/cgi-bin/...&id=1043284392 (Flush the input buffer) thread that AndrewHunter pointed me too (thanks btw). But if I flush my input using that idea then the presentation of my code will change when the user is entering in values. Plus I still get the same problem when I enter in A or P, says re-enter value, and when i re-enter the letter it reads it properly.

    Sorry about the late reply.
    Last edited by stevenson; 07-15-2011 at 02:17 PM.

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Code:
    scanf(" %c", &input);  <--- note the space between " and %

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    In check_letter and check_hour, you need to declare ch to be an int, since that's what getchar returns (that's how it can handle special return values like EOF).

    Here's what's going on with the double enter deal:
    1. You ask the user for a single char with scanf. The input buffer is currently empty.
    2. The user presses <enter>, which sends that line of input to your program for consumption. There is nothing in the input buffer except the <enter> key, which corresponds to the '\n' (newline) character, so that char is read in and stored in your input variable. The input buffer is now empty again.
    3. Since input is neither an 'A' or a 'P', you enter the body of the while loop.
    4. You keep calling getchar in a loop until it receives a new line. But your input buffer is empty, so there is nothing for getchar to read. You need to type something to satisfy getchar (but remember, you need an <enter> to send the input to your program).
    5. You press <enter> again.
    6. Your getchar loop is satisfied and you can know print out the prompt "Enter correct letter: "


    To fix this, only run your getchar loop if input is not a newline:
    Code:
    char input;
    int ch;  // must be int since getchar returns an int
    while (scanf("%c", &input) != 1 || (input != 'A' && input != 'P'))
    {
        if (input != '\n')  // only consume leftover input if there is leftover input
        {
            while ((ch = getchar()) != '\n')
                ;
        }
        printf("Enter correct letter: ");
    }
    So you have to think about what you expect of your user. You can have something like:
    Code:
    Enter an hour followed by A or P for AM/PM: 12A<enter>
    or
    Code:
    Enter an hour: 12<enter>
    Enter A for AM or P for PM: A<enter>
    If you want the first type, you can wrap the two functions in one and use a slightly more complicate scanf: scanf("%d%c", ...). If you want the second, which I think you do, you will have to deal with the possibility that you may have several "Enter correct letter" statements on the screen if you have a dumb user. The only alternative is to use some sort of console manipulation library (e.g. ncurses) that lets you do fancy stuff like rewrite the same line. But those are complicated and too much effort for your project I think.

  8. #8
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by CommonTater View Post
    Code:
    scanf(" %c", &input);  <--- note the space between " and %
    @stevenson: Tater brings up an excellent for skipping any new lines or white space in the buffer. Unfortunately, without your getchar loop, int will handle the first A or P it comes across, no matter how screwed up the input is. For example, if the user input CAR, your code would interpret that as AM. But something like SPARE would be interpreted as P (since the P comes first). I just realized too that your loop wont clear the new line from the input buffer if they just press A<enter>. You need to clear the input buffer again, after your while (scanf...) loop. Since you're repeating the same bit of code over and over again to clear the input buffer, I recommend a simple function:
    Code:
    void clear_input_buffer(void)
    {
        int ch;
    
        while ((ch = getchar()) != '\n' && ch != EOF)
            ;
    }
    
        // in check_letter
        if (input != '\n')
        {
            clear_input_buffer();
        }

  9. #9
    Registered User
    Join Date
    Jan 2009
    Posts
    13
    Quote Originally Posted by CommonTater View Post
    Code:
    scanf(" %c", &input);  <--- note the space between " and %
    Can you explain what the space between " and % does? I am trying to look through my textbooks but can't see anything about that.

    And anduril462, THANK YOU! I can't believe something that simple gave me such a headache, you opened my eyes a lot, however you did not add the space between the " and % in the scanf statement, so when I got to letter input the output was:

    Enter A (for AM) or P (for PM): Enter correct value: A

    But with the space between the " and % in my scanf statement it solved the problem of "enter correct value" popping up before I even got to enter either A or P or an incorrect value.

    But regardless this function actually works now, and thanks again for the help guys, always appreciated!

  10. #10
    Registered User
    Join Date
    Jan 2009
    Posts
    13
    Quote Originally Posted by anduril462 View Post
    @stevenson: Tater brings up an excellent for skipping any new lines or white space in the buffer. Unfortunately, without your getchar loop, int will handle the first A or P it comes across, no matter how screwed up the input is. For example, if the user input CAR, your code would interpret that as AM. But something like SPARE would be interpreted as P (since the P comes first). I just realized too that your loop wont clear the new line from the input buffer if they just press A<enter>. You need to clear the input buffer again, after your while (scanf...) loop. Since you're repeating the same bit of code over and over again to clear the input buffer, I recommend a simple function:
    Code:
    void clear_input_buffer(void)
    {
        int ch;
    
        while ((ch = getchar()) != '\n' && ch != EOF)
            ;
    }
    
        // in check_letter
        if (input != '\n')
        {
            clear_input_buffer();
        }
    I just implemented this function and all works great now. Still a bit confused about " &c" however.... does this have something to do with skipping whitespace?

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Yes. Did you find scanf in your book yet?
    Quote Originally Posted by Not the book, but the manual
    The format string may also contain other characters. White space (such as blanks, tabs, or newlines) in the format string match any amount of white space, including none, in the input. Everything else matches only itself.

  12. #12
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by stevenson View Post
    Can you explain what the space between " and % does? I am trying to look through my textbooks but can't see anything about that.
    Did you look up scanf() in your C library documentation? Textbooks while your best educational tool are seldom the best sources of information about the actual library or it's functions...

    The space tells scanf() to skip invisible characters (\n \t \b spaces etc) before %c ... but scanf() is a lot more complex than that, it can do some pretty amazing stuff if you know how to set it up.

  13. #13
    Registered User
    Join Date
    Jan 2009
    Posts
    13
    Ahh ok I see what it does now, but no I have not really looked at C library documentation, didn't think to look at that stuff, i'm still a noob at coding. But I will look at that stuff.

  14. #14
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by stevenson View Post
    Ahh ok I see what it does now, but no I have not really looked at C library documentation, didn't think to look at that stuff, i'm still a noob at coding. But I will look at that stuff.
    When in doubt the ultimate source of information is the library documentation supplied with your compiler. This information is not only compiler specific it is versionally accurate to account for minor changes from one edition to the next.

    In all due respect... Think to look there. Really... it's your best source of information.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Input validation problem
    By Huncowboy in forum C Programming
    Replies: 3
    Last Post: 01-28-2010, 08:27 AM
  2. Input/Validation
    By nokia123456 in forum C++ Programming
    Replies: 3
    Last Post: 03-23-2009, 11:26 AM
  3. input validation, kinda
    By dynamethod in forum C++ Programming
    Replies: 1
    Last Post: 09-15-2008, 12:52 AM
  4. Input Validation!
    By noaksey in forum C Programming
    Replies: 2
    Last Post: 05-02-2004, 05:19 AM
  5. Input validation
    By Unregistered in forum C++ Programming
    Replies: 1
    Last Post: 12-02-2001, 11:18 PM