Чтение дробей в C

Как мне прочитать дробь в C, чтобы сделать с ней математику? (Дробь будет содержать символ косой черты) Например, пользователь введет 3/12. (строка) Программа найдет НОД, рассчитает уменьшенную дробь и даст 1/4.

Мой первоначальный план состоял в том, чтобы использовать функцию strtok() для получения числителя и знаменателя по отдельности, но я столкнулся с проблемой хранения числителя и знаменателя в отдельных переменных. Это верный метод? Если да, то как сохранить числитель и знаменатель в две отдельные переменные после токенизации строки?

void blah(void) {
  char str[30];
  scanf("%s",&str);
  char * pch;
  pch = strtok (str,"/");
  int i;
  while (pch != NULL)
  {
    i = atoi(pch);
    printf("\n%d", i);
    pch = strtok (NULL, "/");
  }
}

person xsad    schedule 11.03.2013    source источник


Ответы (5)


Это использует sscanf для получения чисел, вы, конечно, можете использовать scanf напрямую:

#include <stdio.h>
int main() {
  const char *s = " 13/6  \n";
  int a,b;
  sscanf(s, "%d/%d", &a, &b);
  printf("%d frac %d\n", a, b);
  return 0;
}
person perreal    schedule 11.03.2013

Держите указатель на начало строки.

Затем изучите использование strchr(), чтобы получить второй указатель, указывающий на / персонаж.

Затем вы можете:

  1. Читать символы из разыменованного первого указателя до тех пор, пока ваш первый указатель не будет равен второму указателю. Сохраните эти символы в виде char [] или char * — это ваш числитель в виде строки C.
  2. Читать со следующего символа после того, куда указывает второй указатель, до завершающего символа /0 nul в конце строки. Сохраните эти символы во втором char [] или char * — это ваш знаменатель в виде строки C.

Используйте atoi() для преобразования обеих строк C в целые числа.

Если strchr() возвращает NULL, вы можете очень легко выполнить проверку ошибок, потому что во входной строке не было /.

person Alex Reynolds    schedule 11.03.2013

Хорошо. У меня другой способ. Используйте strtol, который вернет вам указатель на '/', к которому вы добавите 1 и снова вызовете strtol для второй половины.

Это в два раза сложнее, чем первый ответ, и наполовину сложнее, чем второй. :)

#include <stdio.h>
#include <string.h>

int main(){
    char *f = " 12/7 ";
    char *s;
    long n,d;
    n = strtol(f, &s, 10);
    d = strtol(s+1, NULL, 10);
    printf(" %ld/%ld \n", n, d);
    return 0;
}

Чтобы ответить на остальную часть вашего вопроса, вам определенно нужны 2 переменные, если это будет дробь. Если вы можете использовать числа с плавающей запятой внутри, а дроби — просто удобная функция для пользовательского ввода, тогда вы можете пойти дальше и разделить их и сохранить число в одной переменной.

double v;
v = (double)n / d;

Приведение к double предназначено для принудительного деления двух целых чисел с плавающей запятой.

С другой стороны, если вам нужно работать с большим количеством фракций, вы можете создать структуру для их хранения (объект, если вы будет).

struct frac {
    long num;
    long den;
};
struct frac f = { 12, 7 };
printf("%ld/%ld\n", f.num, f.den);
person luser droog    schedule 11.03.2013

можно и так сделать......

  char str[30];
  scanf("%s",str);
  char c[30];
  int i, num, denom;

  i = 0;
  while (*(str+i) != '/')
  {
      memcpy((c+i), (str+i), 1);
      i++;
  }
  *(c+i) = 0;
  i++;
  num = atoi(c);
  strcpy(c, (str+i));
  denom = atoi(c);
  printf("%d\n", num);
  printf("%d\n", denom);
person Kinjal Patel    schedule 11.03.2013
comment
Вы заново изобрели strchr! - person luser droog; 11.03.2013

Вот что я обычно делаю.

int main()
{
double a,b=1.0f,s;
scanf("%lf/%lf",a,b);
s=a/b;
printf("%lf",s);
}

Даже если пользователь не вводит значение переменной b, значение уже инициализировано до 1.0f, поэтому он все равно может вычислить его значение.

Это проверено на Ubuntu с GCC.

person Aniruddha Bera    schedule 20.04.2017