Пользовательская функция возврата структуры застряла при вводе?

Я хотел создать функцию со структурами для упрощения рациональных чисел,
один член является числителем (целое число), а другой — знаменателем (целое число), но программа зависает при вводе!! Я знаю, что scanf() немного рискованно, но я думал, что это всего лишь пара целых чисел!

#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);
}

person solid.py    schedule 15.01.2014    source источник
comment
Какой ввод вы предоставляете? Программа запустится, если вы укажете, например, 2 3. Я думаю, что для вашего ввода вы входите в бесконечный цикл. Займитесь отладкой! выводить значения r.num и r.den каждый раз по циклу/   -  person David Heffernan    schedule 15.01.2014
comment
Если я использую 7 10 или 8 20   -  person solid.py    schedule 15.01.2014
comment
Пожалуйста, прекратите использовать TAB для отступа (и используйте только пробелы); это приводит к беспорядку, здесь и в других местах.   -  person meaning-matters    schedule 15.01.2014
comment
Почему инф цикл? если по модулю не 0 , !(1&&1)=0 верно?   -  person solid.py    schedule 15.01.2014
comment
@значение имеет значение, хорошо, я должен нажимать пробел 2-4 раза для каждой вложенной команды, чтобы сделать отступ? (немного непрактично)   -  person solid.py    schedule 15.01.2014
comment
Это бесконечный цикл. Знаете ли вы вообще какие-либо методы отладки?   -  person David Heffernan    schedule 15.01.2014
comment
Используйте редактор, в котором есть возможность генерировать 4 пробела при нажатии клавиши TAB. Я не знаю редакторов кода, которые не поддерживают это. Тогда получение дрянного отформатированного кода будет гораздо более непрактичным.   -  person meaning-matters    schedule 15.01.2014
comment
Забавный факт, что мой редактор (gedit) редактирует, сколько пробелов генерирует Tab (вероятно, я перепутал копирование-код-вставку)   -  person solid.py    schedule 15.01.2014


Ответы (2)


Вы застряли в бесконечном цикле здесь:

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

    …
}

Например, когда r.num == 1 и r.den == 2, подумайте, что происходит:

Итерация 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

Итерация 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

Итерация 3 до бесконечности и далее…

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

Измените выражения в операторах ветвления на что-то вроде этого, чтобы исправить свою логику:

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

    …
}
person Fiddling Bits    schedule 15.01.2014
comment
потому что, когда остаток не равен 0 , это не обязательно 1 (или обрабатывается так), верно? - person solid.py; 15.01.2014
comment
Теперь это, безусловно, более ясно; одно условие, чтобы проверить, достаточно ли «r.num/den!=0» ....? - person solid.py; 15.01.2014
comment
Если я не использую ! полностью, например, программа будет выводить 0/0 для ввода, такого как 1/2, верно? - person solid.py; 15.01.2014
comment
@niCk Если бы вы убрали ! и ввели, например, 4/2, ваш окончательный ответ был бы 2/1, чего вы и хотите, верно? - person Fiddling Bits; 15.01.2014
comment
с || например, один div с остатком 0, другой не 0 (модуль 5 предполагает, что он обрабатывается как логическая 1), затем 0||1=1 (1 без того, чтобы оба числа были разделены на 2) - person solid.py; 15.01.2014
comment
@niCk Смотрите мой новый комментарий. Не обращайте внимания на ||. - person Fiddling Bits; 15.01.2014
comment
4 2 ввод (без !) вернул 1/0 и я увидел редактирование - person solid.py; 15.01.2014
comment
Оба мода должны быть равны нулю, так что это (!a)&&(!b) или !(a^^b) (^^ XOR, если не ошибаюсь) верно? - person solid.py; 15.01.2014
comment
@ник Да. Или вы можете сделать что-то вроде этого: if((r.num%2 == 0) && (r.den%2 == 0)) - person Fiddling Bits; 15.01.2014

Проблема в том, что когда вы вводите 8 20, числа меняются как бы под паром;

4 10

2 5

1 2

0 1

0 0 ‹--- вот бесконечный цикл

причина в том, что целое число округляется в меньшую сторону, вы должны добавить оператор управления для случая, когда числа достигают 0

person zgrw    schedule 15.01.2014
comment
Я думаю, что перепутал логическое выражение: 4/8->1/2 - person solid.py; 15.01.2014
comment
Немного запутался. Предполагаемый способ работы был таким: если оба члена разделены, сделайте упрощение, иначе проверьте другое ... иначе live=0 exit. - person solid.py; 15.01.2014
comment
вы не проверяете обоих участников. Ваши операторы if проверяют только 1 число, например, у вас есть 2 5; if(!(r.num%2 && r.den%2)) // эта строка становится this; if(!(0 && 1)) if(!0) if(1) вы должны использовать его без ! - person zgrw; 15.01.2014