cscanffactorialbinomial-coefficients

Writing a Binomial Coefficient calculator in C : Problem with checking scanf failure


I want to write a computer programme that will do the following things :

  1. Ask for two integer inputs n and k from the user using scanf.

  2. If one of the scanfs don't return 1, it will print "Failed" and will return 1. or else it will do the following:

  3. Calculate the Pochhammer symbol n_k. For example if n = 5 and k = 3 then

    poc = ( 5 - 0 ) * ( 5 - 1 ) * ( 5 - 2 ).

  4. It will calculate the factorial k!. For example if k = 3 then

    fac = 1 * 2 * 3.

  5. It will divide poc by fac and loop back to beginning.

I wrote the following which doesn't work:

#include <stdio.h>

unsigned long long bin_cof ( int bc_n , int bc_k ) {
    
    //calculate pochhammer symbol n_k
    int i = 0 ; unsigned long long poc = 1 ;
    for ( ; i < bc_k ; i++ ) { poc = poc * ( bc_n - i ) ; }
    
    //calculate factorial k! 
    i = 1 ; unsigned long long fac = 1 ;
    for ( ; i < bc_k ; i++ ) { fac = fac * ( i + 1 ) ; }

    //calculate binomial coefficient
    return poc / fac ;
}

int main (  ) {
    
    printf ( "Give me an n : " ) ; int n ; scanf ( "%d" , &n ) ;
    printf ( "Give me a k : " ) ; int k ; scanf ( "%d" , &k ) ;
    
    if ( scanf ( "%d" , &n ) != 1 ) { printf ( "!!Failed!!" ) ; return 1 ; }
    if ( scanf ( "%d" , &k ) != 1 ) { printf ( "!!Failed!!" ) ; return 1 ; }
    
    printf ( "\n%dC%d = %llu\n\n" , n , k , bin_cof ( n , k ) ) ; main (  ) ;

    return 0 ; 
}

But if I comment out the checking of the return value of scanfs part, it works.

    /*if ( scanf ( "%d" , &n ) != 1 ) { printf ( "!!Failed!!" ) ; return 1 ; }
    if ( scanf ( "%d" , &k ) != 1 ) { printf ( "!!Failed!!" ) ; return 1 ; }*/

What mistake/s am I making with checking the return values of scanfs and how can I correct it?


Solution

  • As noted in the good comments, you actually have some extra calls to scanf that you should not need to acquire your coefficient values. When I compiled your code, I received the following compiler warnings.

    ||=== Build: Release in Coefficient (compiler: GNU GCC Compiler) ===|
    /home/craig/C_Programs/Console/Coefficient/main.c||In function ‘main’:|
    /home/craig/C_Programs/Console/Coefficient/main.c|19|warning: ignoring return value of ‘scanf’ declared with attribute ‘warn_unused_result’ [-Wunused-result]|
    /home/craig/C_Programs/Console/Coefficient/main.c|20|warning: ignoring return value of ‘scanf’ declared with attribute ‘warn_unused_result’ [-Wunused-result]|
    ||=== Build finished: 0 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|
    

    Warnings like that often provide a clue as to some possible undefined or unwanted behavior in a program even if the compilation is successful.

    Refactoring your code to eliminate the untested "scanf" calls and utilize the conditioned calls, following is the resulting sample code.

    #include <stdio.h>
    
    unsigned long long bin_cof ( int bc_n, int bc_k )
    {
        //calculate pochhammer symbol n_k
        int i = 0 ;
        unsigned long long poc = 1 ;
        for ( ; i < bc_k ; i++ )
        {
            poc = poc * ( bc_n - i ) ;
        }
    
        //calculate factorial k!
        i = 1 ;
        unsigned long long fac = 1 ;
        for ( ; i < bc_k ; i++ )
        {
            fac = fac * ( i + 1 ) ;
        }
    
        //calculate binomial coefficient
        return poc / fac ;
    }
    
    int main (  )
    {
        int n, k;                       /* Preference to define data elements at the beginning when possible */
    
        printf ( "Give me an n : " ) ;
    
        if ( scanf ( "%d", &n ) != 1 )  /* Removed extraneous scanf calls and used tested scanf calles       */
        {
            printf ( "!!Failed!!" ) ;
            return 1 ;
        }
    
        printf ( "Give me a k : " ) ;
    
        if ( scanf ( "%d", &k ) != 1 )
        {
            printf ( "!!Failed!!" ) ;
            return 1 ;
        }
    
        printf ( "\n%dC%d = %llu\n\n", n, k, bin_cof ( n, k ) ) ;
    
        return 0 ;
    }
    

    FYI, I also removed your call to the "main" function within your code. I am guessing that you were tapping some experience with Python where a "main" function is defined and then called, but that is not necessary here. In fact, that would probably cause a continual recursive call which would be undesired. With that, the compilation is clean.

    -------------- Build: Release in Coefficient (compiler: GNU GCC Compiler)---------------
    
    gcc -Wall -O2  -c /home/craig/C_Programs/Console/Coefficient/main.c -o obj/Release/main.o
    gcc  -o bin/Release/Coefficient obj/Release/main.o  -s  
    Output file is bin/Release/Coefficient with size 14.13 KB
    Process terminated with status 0 (0 minute(s), 0 second(s))
    0 error(s), 0 warning(s) (0 minute(s), 0 second(s))
    

    In testing this refactored code, following is some sample terminal output.

    craig@Vera:~/C_Programs/Console/Coefficient/bin/Release$ ./Coefficient 
    Give me an n : 4
    Give me a k : 5
    
    4C5 = 0
    

    The takeaway from this is probably getting more familiar with the various methods of requesting data input along with testing. There are plenty of tutorials both printed and online.