Thread: getting used to functions

  1. #1
    Registered User SCRIPT_KITTEH's Avatar
    Join Date
    Apr 2013
    Posts
    74

    Question getting used to functions

    Hi folks,

    So In my studying of C I am starting to come across more programs with functions in them. I am more comfortable with them than I used to be, but I have a couple of questions about this one function in a particular program from a book I'm reading, if you wouldn't mind taking a look. This particular program asks for two numbers, and calculates the sum of all the squares of the two numbers and the numbers in between them. I am confused about the get_int() function.

    Code:
    /* checking.c -- validating input */
    
    
    #include <stdio.h>
    #include <stdbool.h>
    
    
    int get_int(void); // validate that input is an integer
    bool bad_limits(int begin, int end, int low, int high); // validate that range limits are valid
    double sum_squares(int a, int b); // calculate the sum of the squares of the integers a through b
    
    
    int main(void)
    {
        const int MIN = -1000;    // lower limit to range
        const int MAX = +1000;    // upper limit to range
        int start;        // start of range
        int stop;        // end of range
        double answer; 
    
    
        printf("\nThis program computes the sum of the squares of "
            "integers in a range.\n\nThe lower bound should not "
            "be less than -1000 \nand the upper bound should not "
            "be more than +1000.\n\nEnter the limits (enter 0 for "
            "both limits to quit):\n\n\tlower limit: ");
            
        start = get_int();
        printf("\n\tupper limit: ");
        stop = get_int();
        
        while(start != 0 || stop != 0)
        {
            if(bad_limits(start, stop, MIN, MAX))
                printf("\nPlease try again\n");
            else
            {
                answer = sum_squares(start, stop);
                printf("\nThe sum of the squares of the integers ");
                printf("from %d to %d is %g\n", start, stop, answer);
            }
            printf("\nEnter the limits (enter 0 for both "
                "limits to quit):\n");
            printf("\n\tlower limit: ");
            start = get_int();
            printf("\n\tupper limit: ");
            stop = get_int();
        }
        
        printf("\nDone.\n");
    
    
        return 0;
    }
    
    
    int get_int(void)
    {
        int input;
        char ch;
    
    
        while(scanf("%d", &input) != 1)
        {
            while((ch = getchar()) != '\n'){
                printf("\n");
                putchar(ch);    // dispose of bad input
            }
            printf(" is not an integer.\n\nPlease enter an ");
            printf("integer value, such as 25, -178, 3, etc...: ");
        }
    
    
        return input;
    }
    
    
    double sum_squares(int a, int b)
    {
        double total = 0;
        int i;
        
        for(i = a; i <= b; i++)
            total += i * i;
    
    
        return total;
    }
    
    
    bool bad_limits(int begin, int end, int low, int high)
    {
        bool not_good = false;
        
        if(begin > end)
        {
            printf("\n%d isn't smaller than %d.\n", begin, end);
            
            not_good = true;
        }
        if(begin < low || end < low)
        {
            printf("\nValues must be %d or greater.\n", low);
            
            not_good = true;
        }
        
        return not_good;
    }

    So in that get_int() function, it's pretty simple if scanf returns 1, otherwise... another while loop call the getchar() function, which is assigned to the variable ch. So say I enter 'a' for the lower limit, this is what happens:

    Code:
    Enter the limits (enter 0 for both limits to quit):
    
    
        lower limit: a
    
    
    a is not an integer.
    It seems as if getchar() somehow "got the character" from scanf(). There's no way that getchar() could have been simultaneously reading my input, because that function is not even called until scanf has already not returned 1. So I'm confused how that happened. I was under the impression that getchar() got input from the keyboard, which would lead me to think that I would be prompted to input something again when getchar() is called, before putchar() prints the scanf input. But this is obviously not the case.

    Also, I'm curious about that comment beside putchar(ch) that says //dispose of bad input. (The author of the book I'm reading put that there, not me). I recall a long time ago on these forums, someone told me something about how once scanf has read input, that input is like... stuck to scanf (I'm butchering this phrasing I'm sure). So does putchar() not only print the input from scanf/getchar, but also unload it from scanf, so to speak?

    Forgive me if I'm explaining this stuff poorly, I probably am. As always, I really appreciate you guys & your help

  2. #2
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    When scanf() fails, that is, when it reads an invalid character, the invalid character and any following characters
    remain in the input stream or keyboard buffer. That is why getchar() is able to read the remaining input. In fact,
    something must read the input after scanf() fails, in order to clear out the buffer for the next input.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    The comment -

    // dispose of bad input

    actually refers to getchar(), nut putchar().
    putchar() simply displays the bad character.

    The invalid input characters are not "stuck" in scanf(); what happenened is that scanf() never removed
    them from the input stream (the keyboard buffer in this case). If scanf() finds that all the input characters
    are a valid form for the type that is specified, (a decimal int in this case) it converts the characters into
    an int and stores it in the variable 'input'. It also leaves the input stream (keyboard buffer) empty, and
    returns a 1.

    If scanf() encounters an invalid character, it leaves that character and any that might follow it, in the input
    stream, and returns 0. In that case the function get_int removes the remaining bad character(s) and displays
    them. Everything is now ready for new input.

  4. #4
    Registered User SCRIPT_KITTEH's Avatar
    Join Date
    Apr 2013
    Posts
    74
    Quote Originally Posted by megafiddle View Post
    The comment -

    // dispose of bad input

    actually refers to getchar(), nut putchar().
    putchar() simply displays the bad character.

    The invalid input characters are not "stuck" in scanf(); what happenened is that scanf() never removed
    them from the input stream (the keyboard buffer in this case). If scanf() finds that all the input characters
    are a valid form for the type that is specified, (a decimal int in this case) it converts the characters into
    an int and stores it in the variable 'input'. It also leaves the input stream (keyboard buffer) empty, and
    returns a 1.

    If scanf() encounters an invalid character, it leaves that character and any that might follow it, in the input
    stream, and returns 0. In that case the function get_int removes the remaining bad character(s) and displays
    them. Everything is now ready for new input.
    Ahhh, the *stream*, not scanf... Thank you very much!

  5. #5
    Registered User
    Join Date
    Mar 2011
    Posts
    596
    Glad to help.

    scanf() uses the stream stdin (standard input, which is the keyboard by default). The input stream
    would have been more obvious if fscanf() were being used, where the stream needs to be specified
    as the first arguement in fscanf().

    Also, I should have explained the return value from scanf() better. I was limiting the information
    to that particular program, and to why getchar() was needed.
    scanf() returns the number of input values that were successfully converted and stored. Since only
    one integer was specified, it can only convert and store one value. Therefore the return value can
    only be a 1 (if successful) or a 0 (if unsuccessful). If three integers had been specified, scanf() could
    have returned 0, 1, 2, or 3, depending on how many were successfully converted.

    So it's up to the caller of scanf() to check the return value and make sure all the values requested
    were converted and stored. If not, then you would want to remove whatever might be left in the stream.

    It's one of those library functions that can do so much, that it's hard to remember it all.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 05-27-2013, 06:43 PM
  2. WinAPI functions - similar functions as part of VS C++
    By jlewand in forum Windows Programming
    Replies: 2
    Last Post: 02-02-2012, 08:54 AM
  3. Creating Functions & passing information to other functions
    By RyanLeonard in forum C Programming
    Replies: 4
    Last Post: 10-28-2010, 12:17 PM
  4. Replies: 6
    Last Post: 05-06-2003, 03:08 PM
  5. Replies: 1
    Last Post: 01-20-2002, 11:50 AM