Search code examples
cfunctionrecursionprimesstdio

Understanding calling one function inside another C


I'd like to ask the following misunderstandings of C language, which I see I'm having.

I'm sorry if the code is not properly indented, I tried as much as I could but there are not so many guides on the internet.

The program asked given a starting number 'val' and a Even-Odd or Odd-Even alternating sequence (which stops whenever this rules is violated) to print the greater prime number with 'val'.

I tried with two functions and the main: one to control the GCD between two given numbers and the other to keep tracks of the greatest one, but I think I miss something in the code or in the conception of C function,

Because when compiled it returns me 0 or great number which I'm not entering.

One example to understand what I should do:

If my sequence was 10, 7, 8, 23 and my val was 3, I had to print 23, because it is the greatest integer prime with 3.

Here's the code :

#include <stdio.h>
int mcd(int a, int b)
{   // Gcd function
    if (a == 0)
        return b;
    else
        return mcd(b % a, b);
}

int valuta(int val, int h)  // Valuing Max function
{
    int temp = 0;
    if (mcd(val, h) == 1 && h > temp)
        temp = h;
    return temp;
}

int main()
{
    int val, d, x, y, z, t, contatore = 1;
    scanf("%d", &val);
    scanf("%d%d", &x, &y);
    if (x > y && mcd(val, x) == 1)
    {   // Two options
        t = x;
    }
    else if (y > x && mcd(val, y) == 1)
    {
        t = y;
    }
    if ((x % 2 == 0 && y % 2 == 0) || (x % 2 == 1 && y % 2 == 1))
    {   // Bad case
        if (x > y && mcd(val, x) == 1)
        {
            t = x;
            contatore = 0;
        }
        else if (y > x && mcd(val, y) == 1)
        {
            t = y;
            contatore = 0;
        }
    }
    else
    {
        while (contatore == 1)
        {
            scanf("%d", &z);
            t = valuta(val, z);
            if (x % 2 == 0 && z % 2 == 0)
            {   // Even- Odd - Even
                scanf("%d", &d);
                t = valuta(val, d);
                if (d % 2 == 0)
                {
                    contatore = 0;
                }
                else
                {
                    contatore = 0;
                }
            }
            if (x % 2 == 1 && z % 2 == 1)
            {   //Odd- Even- Odd
                scanf("%d", &d);
                t = valuta(val, d);
                if (d % 2 == 1)
                {
                    contatore = 0;
                }
                else
                {
                    contatore = 0;
                }
            }
        }
    }
    printf("%d\n", t);
    return 0;
}

PS. Is there any way to reduce the number of lines of code or to reduce the effort in coding? I mean, a straightforward solution will be helpful.


Solution

  • Your valuta() function is flawed in that it needs to return the maximum qualifying value so far but has no knowledge of the previous maximum - temp is always zero. The following takes the previous maximum as an argument:

    int valuta(int val, int h, int previous )
    {
        return ( mcd(val, h) == 1 && h > previous ) ? h : previous ;
    }
    

    And is called from main() thus:

    t = valuta( val, x, t ) ;
    

    The test mcd(val, h) == 1 is flawed, because mcd() only ever returns the value of parameter b which is not modified in the recursion, so will never return 1, unless the argument b is 1. Since I have no real idea what mcd() is intended to do, I cannot tell you how to fix it. It appear to be a broken implementation of Euclid's greatest common divisor algorithm, which correctly implemented would be:

    int mcd(int a, int b)
    {
        if(b == 0)
            return a;
        else
            return mcd(b, a % b);
    }
    

    But I cannot see how that relates to:

    "[...] he greatest integer prime with 3 [...]

    The odd/even even/odd sequence handling can be drastically simplified to the extent that it is shorter and simpler than your method (as requested) - and so that it works!

    The following is a clearer starting point, but may not be a solution since it is unclear what it is it is supposed to do.

    #include <stdio.h>
    #include <stdbool.h>
    
    int mcd(int a, int b)
    {
        if(b == 0)
            return a;
        else
            return mcd(b, a % b);
    }
    
    int valuta(int val, int h, int previous )
    {
        return ( mcd(val, h) && h > previous ) ? h : previous ;
    }
    
    int main()
    {
        int val, x, t ;
        printf( "Enter value:") ;
        scanf("%d", &val);
    
        typedef enum 
        {
            EVEN = 0,
            ODD = 1,
            UNDEFINED
        } eOddEven ;
    
        eOddEven expect = UNDEFINED ;
        bool sequence_valid = true ;
    
        printf( "Enter sequence in odd/even or even/odd order (break sequence to exit):\n") ;
        while( sequence_valid )
        {
            scanf("%d", &x);
            if( expect == UNDEFINED )
            {
                // Sequence order determined by first value
                expect = (x & 1) == 0 ? EVEN : ODD ;
            }
            else
            {
                // Switch expected odd/even
                expect = (expect == ODD) ? EVEN : ODD ;
    
                // Is new value in the expected sequence?
                sequence_valid = (expect == ((x & 1) == 0 ? EVEN : ODD)) ;
            }
    
            //  If the sequence is valid...
            if( sequence_valid )
            {
               // Test if input is largest qualifying value
               t = valuta( val, x, t ) ;
            }
        }
    
        // Result
        printf("Result: %d\n", t);
    
        return 0;
    }