cstructscanfmodulorational-numbers

Custom Struct-returning function stuck on input?


I wanted to make a function with structs to simplify rational numbers ,
one member is the numerator(int) and the other is the denominator(int) but the program stucks at input!! I am aware that scanf() is a bit risky but I thought its just a couple of integers!

#include <stdio.h>
#include <stdlib.h>

typedef struct rational{
    int num;
    int den;
}rational;

rational makerational(int num,int den);
void printrational(rational r);
int main()
{
    int a,b;
    printf("\n\n Input integers for fraction:");
    scanf(" %d%d",&a,&b);
    printrational(makerational(a,b));
}
rational makerational(int a,int b){
    int live=1; 
    rational r;
    r.num=a;
    r.den=b;
  while(live){  
    if(!(r.num%2 && r.den%2)){
        r.num/=2;
        r.den/=2;
    }else if(!(r.num%3 && r.den%3)){
        r.num/=3;
        r.den/=3;
    }else if(!(r.num%5 && r.den%5)){
        r.num/=5;
        r.den/=5;
    }else if(!(r.num%7 && r.den%7)){
        r.num/=7;
        r.den/=7;
    }else live--;
  }
    return r;
}
void printrational(rational r){
    printf("\nFRACTION -> %d/%d\n",r.num,r.den);
}

Solution

  • You getting stuck in an infinite loop here:

    while(live){  
        if(!(r.num%2 && r.den%2)){
            r.num/=2;
            r.den/=2;
        }
    
        …
    }
    

    For example, when r.num == 1 and r.den == 2, consider what's happening:

    Iteration 1

    r.num % 2 == 1 % 2 == 1
    r.den % 2 == 2 % 2 == 0
    !(1 && 0) == 1
    
    r.num / 2 == 1 / 2 == 0
    r.den / 2 == 2 / 2 == 1
    

    Iteration 2

    r.num % 2 == 0 % 2 == 0
    r.den % 2 == 1 % 2 == 1
    !(0 && 1) == 1
    
    r.num / 2 == 0 / 2 == 0
    r.den / 2 == 1 / 2 == 0
    

    Iteration 3 to infinity and beyond…

    r.num % 2 == 0 % 2 == 0
    r.den % 2 == 0 % 2 == 0
    !(0 && 0) == 1
    
    r.num / 2 == 0 / 2 == 0
    r.den / 2 == 0 / 2 == 0
    

    Change the expressions in the branching statements to something like this to correct your logic:

    while(live)
    {
        if((r.num % 2 == 0) && (r.den % 2 == 0))
        {
            r.num /= 2;
            r.den /= 2;
        }
    
        …
    }