Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 13 of 13
  1. #1
    New Coder
    Join Date
    Nov 2004
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts

    C Scanf Problem.

    I'm having a bit of a problem with scanf. The following code works fine, provided a valid response is given. The function is stored, and the value is returned. However, if the default case in the switch statement is reached, and the function is called again, it seems to skip that very same scanf statement. It then enters through the switch statement, reaches the default case ( since the value hasn't changed ), and calls the function again. At this point, if I enter a valid response, it works normally, but it repeats itself if I enter an invalid response ( reaches default case ). Any ideas?

    Here is the code:
    Code:
    char GetUserChoice (void)
    {
       char choice;
    
       printf("\n          D - Display to Screen \n");
       printf("\n          W - Write to File \n");
       printf("\n          Q - Quit \n");
       printf("\nEnter your choice : ");
       scanf ("%c", &choice );
    
       switch (choice)
       {
          case 'D':
             return choice;
          case 'd':
             return choice;
          case 'W':
             return choice;
          case 'w':
             return choice;
          case 'Q':
             return choice;
          case 'q':
             return choice;
          default :
             fprintf( stderr, "\nPlease enter a valid response.\n");
             GetUserChoice();
       }
    
       return choice;
    }
    And here is an example of the output for clarification:
    Code:
              D - Display to Screen
    
              W - Write to File
    
              Q - Quit
    
    Enter your choice : X
    
    Please enter a valid response.
    
              D - Display to Screen
    
              W - Write to File
    
              Q - Quit
    
    
    Please enter a valid response.
    Enter your choice :
              D - Display to Screen
    
              W - Write to File
    
              Q - Quit
    
    Enter your choice :

  • #2
    Regular Coder
    Join Date
    Feb 2003
    Location
    California
    Posts
    925
    Thanks
    0
    Thanked 0 Times in 0 Posts
    you have a matter of recursion going on here...everytime you call the function within the same function you are adding layers which you will need to get out of. you might try putting the whole thing in a while loop and instead of calling the function use a break statement to get out of the switch to return to the top of the while loop...make sense?


    Jason

    edit: you could also use the goto function, though not recomended but you don't want to keep calling the same function within the function, your not looking for recursion with this problem
    Last edited by Jason; 11-19-2004 at 11:07 PM.

  • #3
    New Coder
    Join Date
    Nov 2004
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Oh I understand it's recursion, but I'm not sure if you misunderstood my problem. It's not that I have an endless loop or anything like that, my only issue is that's it's skipping one of the scanf statements. I've tried modifying the code in a couple of ways. I've had the default case return something like an 'X'. Then, in main, I had a while loop that said:
    Code:
    choice = userChoice();
    
    while ( choice == 'X' )
    {
        fprintf ( stderr, "Please enter a valid selection \n");
        choice = userChoice();
    }
    With that, I'm getting identical results.

    Basically, if you look at the sample output above, it recognized that X is an invalid response, printed the appropriate error message, printed the message directly before the scanf statement, then skips over the scanf statement. It then runs the function again, and the scanf statement works then, provided I enter a valid response. If not, it does the exact same thing over again.

  • #4
    Regular Coder
    Join Date
    Feb 2003
    Location
    California
    Posts
    925
    Thanks
    0
    Thanked 0 Times in 0 Posts
    then your problem is that you are accepting char as a string in your scanf so what it would probably do is take the invalid char as the first character and say its wrong then take EOF which would be the return character and say thats wrong then ask appropriately...use

    Code:
    scanf('%c', %char);  //and not double quotes
    try that.

    Jason

  • #5
    New Coder
    Join Date
    Nov 2004
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Making the change from
    Code:
    scanf( "%c", &choice);
    to
    Code:
    scanf('%c', &choice);
    Gives me two warnings when I compile, and a core dump when run.

  • #6
    Regular Coder
    Join Date
    Oct 2004
    Posts
    230
    Thanks
    0
    Thanked 0 Times in 0 Posts
    You need to clear the input after your call to scanf because the return character '\r' is still in the buffer.

    Code:
        scanf ("%c", &choice );
        fflush(stdin);

  • #7
    New Coder
    Join Date
    Nov 2004
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts
    That doesn't seem to work either. I'll re-post my code, in case I put it in the wrong spot, but I'm pretty sure I followed your direction.

    Code:
    {
       char choice;
    
       printf("\n          D - Display to Screen \n");
       printf("\n          W - Write to File \n");
       printf("\n          Q - Quit \n");
       printf("\nEnter your choice : ");
       scanf ("%c", &choice );
       fflush (stdin);
    
       switch (choice)
       {
          case 'D':
             return choice;
          case 'd':
             return choice;
          case 'W':
             return choice;
          case 'w':
             return choice;
          case 'Q':
             return choice;
          case 'q':
             return choice;
          default :
             fprintf( stderr, "\nPlease enter a valid response.\n");
             GetUserChoice();
       }
    
       return choice;
    }
    Still getting the identical output.

  • #8
    Regular Coder
    Join Date
    Feb 2003
    Location
    California
    Posts
    925
    Thanks
    0
    Thanked 0 Times in 0 Posts
    edit: you could try putting the fflush beofre the scanf aswell, don't know if that will help...

    Jason
    Last edited by Jason; 11-20-2004 at 12:40 AM.

  • #9
    Regular Coder
    Join Date
    Oct 2004
    Posts
    230
    Thanks
    0
    Thanked 0 Times in 0 Posts
    You asked why your program was seemingly skipping the next call to scanf. If you look at the output now you will see that it is different, and nothing is being skipped. (Actually it wasn't skipping the scanf statement, it was extracting the '\r' character from the stream). The fflush statement fixed that.

    Your other problem, which is an incorrect return, is because of recursion. Your program will always return the first entry entered. To fix that, make sure you return the current choice all throughout recursion.

    Code:
          default :
             fprintf( stderr, "\nPlease enter a valid response.\n");
             return GetUserChoice();

  • #10
    New Coder
    Join Date
    Nov 2004
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I'm not trying to sound ungrateful for the help, but let me try and explain it again.

    The output I have above ( my first post ), is exactly the same as the output I have after adding the fflush(stdin); statement. Again, I'll admit I'm not familiar with fflush, but it just didn't seem to solve my problem in this instance.

    Also, I'm not sure I agree that I have a problem with my return. If you look at the code, the only meaningul return statements are within the cases in the switch statement. If it gets to the default statement, what would be the point of changing it to return GetUserChoice? The point of the default case it to catch any invalid responses, and prompt the user to try again. It seems to be doing exactly that, so I'm not really sure why there's a problem with the return.

  • #11
    Regular Coder
    Join Date
    Oct 2004
    Posts
    230
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Without the fflush statement, my output is the same as yours was (this is after entering one invalid character):
    Code:
              D - Display to Screen
    
              W - Write to File
    
              Q - Quit
    
    Enter your choice : X
    
    Please enter a valid response.
    
              D - Display to Screen
    
              W - Write to File
    
              Q - Quit
    
    Enter your choice :
    Please enter a valid response.
    
              D - Display to Screen
    
              W - Write to File
    
              Q - Quit
    
    Enter your choice :

    After I added the fflush statement, the output is like this (it doesn't ask for a valid choice twice):
    Code:
              D - Display to Screen
    
              W - Write to File
    
              Q - Quit
    
    Enter your choice : X
    
    Please enter a valid response.
    
              D - Display to Screen
    
              W - Write to File
    
              Q - Quit
    
    Enter your choice :

    If it doesn't work as expected on your compiler, there is an alternative way to eat the '\r' character instead of fflush:
    Code:
       char choice, trash;
    
       scanf ("%c%c", &choice, &trash );

    As far as your return, you are not understanding how the stack works with recursion. On your first call to GetUserChoice() if you make an invalid choice, it gets stored in that instance of your function. After you recurse through the function again and finally end up making a valid choice, the stack unwinds back to the top value (from your first call) and that is what gets returned to the caller. Returning the current choice throughout recursion ensures that the last entered choice is what gets returned from the top of the stack.

    Look at it this way. If your first choice is 'X', and that gets stored in your variable choice, when the stack unwinds and returns choice you are returning 'X'.. no matter what value is stored in the other function instances of their own copy of choice.

    Try it like this instead, maybe it will make more sence to you if you see it written this way:
    Code:
          default :
             fprintf( stderr, "\nPlease enter a valid response.\n");
             choice = GetUserChoice();

  • #12
    New Coder
    Join Date
    Nov 2004
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Ah. The second method worked for getting rid of the return. As for the recursion, I see what you mean now. I was under the impression that the return choice statement would leave the function entirely, and return that value to main, not simply to the previous version of GetUserChoice. Thanks for the help!

  • #13
    Regular Coder
    Join Date
    Oct 2004
    Posts
    230
    Thanks
    0
    Thanked 0 Times in 0 Posts
    You're welcome. Just remember that the alternative method I posted is not idiot-proof. What happens when a user enters more than one character? I'll leave it to you to implement a suitable replacement for fflush (which removes everything in the stream buffer). Hint: you can use scanf in a while loop.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •