Thread: getchar - multiple input problems

  1. #1
    Registered User
    Join Date
    Mar 2012
    Posts
    7

    getchar - multiple input problems

    Hi,

    I've run into a silly problem that I thought I'd ask for some help with:

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int i;//Global input var
    
    
    //Example Menu
    int main()
    {
        printf("1) Save File \n");
        printf("2) Go Deeper \n");
        printf("3) Exit \n");
        
        userInput();
        
        while (i < 1 || i > 3)      //Errorcheck user input
        {
            printf("Wrong Input \n");
            main();
        }//end while
    
        switch (i)
        {
            case 1:
                //Save File
            break;
    
            case 2:
                //Go Deeper
            break;
    
            case 3:
                //Exit
            break;
    }
    
    
    //Getting Input
    int userInput()
    {
        getchar();                   //Fetch user input
        
        i = getchar();              //Assign user input
        i -= '0';                   //Convert to suitable int
    }
    The problem with the above example is that when I run it the "userInput();" validator ("Wrong Input") will trigger unless I manually linebreak or input a 'dummy character' infront of my wished menu input.

    I know that this is caused because of the multiple (2) "getchar();" calls in "userInput();" however, my menu system has submenus running off the same functionality and if I were to Go deeper and eventually return to the main menu it would skip input unless I used the multiple (2) "getchar();" calls.

    How would I go about solving this silly problem universally (inside "userInput();" )?

    Any help would be greatly appriciated!
    /Dregg
    Last edited by Dregg; 03-21-2012 at 03:09 AM.

  2. #2
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    Ok first things first:

    1) I fail to see how that even compiles, the switch is missing a bracket.

    2) int main() should be int main(void) if you are not using command line arguments and should have return 0 at the end of main's body.

    3) Don't use global variables. In a program of your size there is absolutely no need for them whatsoever. Use local variables and pass the correct arguments to functions that need parameters.

    4) You don't need a new function just to read user input. In fact, I think that is part of the reason why you are confused about implementing your algorithm.

    The idea is simple:

    Print menu choices -> Read user input -> Print submenu choices -> read user input -> print menu choices, etc..

    EDIT: Can't believe I didn't see this: DON'T EVER CALL MAIN() within main()!
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  3. #3
    Registered User
    Join Date
    Mar 2012
    Posts
    7
    Thanks for the reply!

    1) I fail to see how that even compiles, the switch is missing a bracket.
    I realized that I forgot to mention that this is just a cut/paste from the actual program and it seems I accidently left one of the brackets out. Most of the functions are renamed just to make my question short and concise. (that goes for the faulty main(); call aswell)

    2) int main() should be int main(void) if you are not using command line arguments and should have return 0 at the end of main's body.
    Thanks, forgot to add that.


    3) Don't use global variables. In a program of your size there is absolutely no need for them whatsoever. Use local variables and pass the correct arguments to functions that need parameters.
    This is the start of a pretty extensive assignment that we are supposed to build on for the rest of the semester, so I'm trying to keep everything somewhat 'futureproof', besides wouldn't it be silly to define a local varaible for each submenu?

    4) You don't need a new function just to read user input. In fact, I think that is part of the reason why you are confused about implementing your algorithm.
    What I was trying to achieve was a universal function for menu navigation to make the program easy to extend/update with new content, and also save a few lines of code. Maybe it is a bad idea? I just thought It would make it a bit simpler/cleaner, (since I would be reusing the same algorithm for each submenu anyway?)

  4. #4
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    Quote Originally Posted by Dregg View Post
    This is the start of a pretty extensive assignment that we are supposed to build on for the rest of the semester, so I'm trying to keep everything somewhat 'futureproof', besides wouldn't it be silly to define a local varaible for each submenu?

    What I was trying to achieve was a universal function for menu navigation to make the program easy to extend/update with new content, and also save a few lines of code. Maybe it is a bad idea? I just thought It would make it a bit simpler/cleaner, (since I would be reusing the same algorithm for each submenu anyway?)
    I think it is generally silly to use global variables when you don't need them. It is considered bad practice for a variety of reasons that I am not going to get into. In particular, while working in a larger project with many header and source files it can cause a lot of problems since you make it harder for yourself to identify which variable has local as opposed to global scope. It also makes it tempting to edit values of global variables in an attempt to debug existing problems in your code, forgetting that it may be used in more than one place and introducing even more false apparent problems. It really is like driving your groceries on the top of your car instead of in your trunk, they tend to stay fresher but by the time you get home you realize you are missing half of them.

    I suspect that your problem is not with getchar() in particular since you can easily read documentation for that online. I don't know what the structure of your menu is, but if it is as recursive as you make it look, then it might be best to keep track of the depth you are at using some counter. If you want to print your menu based on your depth, then you can indeed have a menu function which takes as parameters the user input (which you read in main, or wherever) and the current depth and figures out what it needs to display as options.
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  5. #5
    Registered User
    Join Date
    Mar 2012
    Posts
    7
    Thanks for your reply, I'll take it all into consideration and try to correct this error, but somehow I still can't quite figure out whats missing, It's almost as if I need a separate algorithm for the main menu exclusivley.

    To clarify:

    The following works perfectly with the main menu as an exception (reads second char input):
    Code:
    int userIn()
    {
        getchar();                   //Get user input
        
        i = getchar();              //Assign user input
        i -= '0';                   //Convert to suitable int
    }

    This one works as intended for the main menu but returns one faulty entry everytime I traverse between menus :
    Code:
    int userIn()
    {   
        i = getchar();              //Get & Assign user input
        i -= '0';                   //Convert to suitable int
    }
    Last edited by Dregg; 03-21-2012 at 04:12 AM.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Dregg
    This is the start of a pretty extensive assignment that we are supposed to build on for the rest of the semester, so I'm trying to keep everything somewhat 'futureproof'
    As the programs that you write get bigger, locality of reference becomes even more important: it is easier to understand a piece of code when you only have to consider a handful of variables involved than when you have to consider the hundreds of variables involved.

    So it is with this piece of code:
    Code:
    userInput();
    
    while (i < 1 || i > 3)      //Errorcheck user input
    As I reader, I instantly go "huh? what's i?" Compare to this:
    Code:
    int input = userInput();
    
    while (input < 1 || input > 3)
    With the locality of reference and better naming, I don't even need the comment any more, yet a reader can easily understand that the input is being checked, and the reader can trace where the variable value is getting set. Now compare to this:
    Code:
    userInput();
    foo();
    
    while (i < 1 || i > 3)      //Errorcheck user input
    userInput() sets the value of i to 0. Does the while loop run at all? You don't know, because you don't know if foo modified i.

    Quote Originally Posted by Dregg
    besides wouldn't it be silly to define a local varaible for each submenu?
    Why would you need a local variable for each submenu?

    Quote Originally Posted by Dregg
    What I was trying to achieve was a universal function for menu navigation to make the program easy to extend/update with new content, and also save a few lines of code. Maybe it is a bad idea? I just thought It would make it a bit simpler/cleaner, (since I would be reusing the same algorithm for each submenu anyway?)
    Then write a function that takes a menu text to display (and also the lower/upper limits of the range of input), requests for input, and returns the input if it is valid, otherwise it keeps getting the input.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Mar 2012
    Posts
    7
    Quote Originally Posted by laserlight View Post
    message
    Thanks, laserlight for taking your time to answer! I'll revisit my code and keep legibility in mind!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. getchar() doesn't wait for input
    By cantinero74 in forum C Programming
    Replies: 5
    Last Post: 04-27-2010, 09:46 AM
  2. getchar won't take any input after scanf
    By pshirishreddy in forum C Programming
    Replies: 2
    Last Post: 08-02-2009, 11:46 AM
  3. getchar() problems
    By decontrol in forum C Programming
    Replies: 4
    Last Post: 06-06-2003, 03:47 AM
  4. Multiple Problems( window(), gotoxy(), & getchar() )
    By drharv in forum C Programming
    Replies: 2
    Last Post: 02-20-2002, 09:47 PM
  5. Getchar & Structure Problems
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 02-14-2002, 10:16 AM