Code:
#include <stdio.h> //printf, sscanf, sprintf
#include <string.h> //strcasecmp
#include <stdlib.h> //calloc
//declares a struct called Fraction with parts
//num and den
typedef struct {int num, den;} Fraction;
//declares an enumeration of operators
typedef enum {ADD = 1, SUB, MUL, DIV} Operator;
//prototypes
Operator readOperator(char s[]);
char operator2char(Operator);
Fraction *newFraction(int, int);
Fraction *readFraction(char s[]);
char *fraction2str(Fraction *f);
int GCD(int, int);
void simplify(Fraction *f);
Fraction *addFractions(Fraction *f1, Fraction *f2);
Fraction *subFractions(Fraction *f1, Fraction *f2);
Fraction *mulFractions(Fraction *f1, Fraction *f2);
Fraction *divFractions(Fraction *f1, Fraction *f2);
Fraction *execute(Operator, Fraction *f1, Fraction *f2);
int main(int argc, char *argv[]) {
Fraction *f1, *f2, *f3;
//Reading operator
Operator op = readOperator(argv[1]);
//Reading first fraction
f1 = readFraction(argv[2]);
//Reading second fraction
f2 = readFraction(argv[3]);
//To declare x/0 an error
if (f1->den == 0 || f2->den == 0) {
printf("incorrect fraction (zero denominator)");
return 0;
}
//calculating the operation resultant
f3 = execute(op, f1, f2);
//printing results
printf("%s ", fraction2str(f1));
printf("%c ", operator2char(op));
printf("%s ", fraction2str(f2));
printf("= %s", fraction2str(f3));
return 0;
}
//This function reads an input string and
//turns it into a, b, c which are turned into
//a string. This string is then compared with
//the given operators to determine what op
//will be
Operator readOperator(char s[]) {
Operator op;
char a, b, c;
char buffer[6];
sscanf(s, "%c%c%c", &a, &b, &c);
sprintf(buffer, "%c%c%c", a, b, c);
if (strcasecmp(buffer, "ADD") == 0) op = ADD;
else if (strcasecmp(buffer, "SUB") == 0) op = SUB;
else if (strcasecmp(buffer, "MUL") == 0) op = MUL;
else if (strcasecmp(buffer, "DIV") == 0) op = DIV;
return op;
}
//This function returns a char based on a
//a switch of op(the operator input)
char operator2char(Operator op) {
char operator_in_char;
switch (op) {
case ADD:
return '+';
break;
case SUB:
return '-';
break;
case MUL:
return '*';
break;
case DIV:
return '/';
break;
}
}
//This function creates a new Fraction out
//of two numbers by allocating room for them
//and then copying the components
Fraction *newFraction(int n, int d) {
Fraction *f = malloc(sizeof(Fraction));
f->num = n;
f->den = d;
return f;
}
//This function reads the numerator and the
//denominator of a given string and then
//creates a Fraction of them by sending them
//to newFraction
Fraction *readFraction(char s[]) {
int n, d;
Fraction *f;
sscanf(s, "%d/%d", &n, &d);
f = newFraction(n, d);
return f;
}
//This function allocates room for a string
//sprints the numerator and denominator to
//that string and returns the string
char *fraction2str(Fraction *f) {
char *buffer = calloc(22,sizeof(int));
sprintf(buffer, "%d/%d", f->num, f->den);
return buffer;
}
//This function calculates the greatest common
//denominator of 2 numbers
int GCD(int m, int n) {
/* int i, remainder_n, remainder_m;
for(i = 30000; i > 0; i--) {
remainder_m = m % i;
remainder_n = n % i;
if (remainder_m == 0 && remainder_n == 0) break;
}
return i; */
while(m != n) {
if(m > n)
m -= n;
else
n -= m;
}
return m;
}
//This function simplifies the fraction by dividing
//both the numerator and denominator by GCD
void simplify(Fraction *f) {
int GCF = GCD(f->num,f->den);
f->num /= GCF;
f->den /= GCF;
}
//This function adds the fractions. It creates
//new fractions by sending the resultant numerator
//and denominator to newFractions then simplifies
Fraction *addFractions(Fraction *f1, Fraction *f2) {
Fraction *f3;
int n, d;
n = f1->num * f2->den + f2->num * f1->den;
d = f1->den * f2->den;
//Returning 0/1 for 0 num
if (f3->num == 0) {
f3->den = 1;
return f3;
}
//Fixing negative values
else if (n < 0 && d > 0) {
n = -n;
f3 = newFraction(n, d);
simplify(f3);
f3->num = -f3->num;
return f3;
}
else if (d < 0 && n > 0) {
d = -d;
f3 = newFraction(n, d);
simplify(f3);
f3->num = -f3->num;
return f3;
}
else if (d < 0 && n < 0) {
d = -d;
n = -n;
f3 = newFraction(n, d);
simplify(f3);
return f3;
}
//Normal Computation
else {
f3 = newFraction(n, d);
simplify(f3);
return f3;
}
}
//This function subtracts the fractions. It creates
//new fractions by sending the resultant numerator
//and denominator to newFractions then simplifies
Fraction *subFractions(Fraction *f1, Fraction *f2) {
Fraction *f3;
int n, d;
n = f1->num * f2->den - f2->num * f1->den;
d = f1->den * f2->den;
//Returning 0/1 for 0 num
if (n == 0) {
f3 = newFraction(n, d);
f3->den = 1;
return f3;
}
//Fixing negative values
else if (n < 0) {
n = -n;
f3 = newFraction(n, d);
simplify(f3);
f3->num = -f3->num;
return f3;
}
else {
f3 = newFraction(n, d);
simplify(f3);
return f3;
}
}
//This multiplies the fractions, if either f1->num or
//f2->num is 0 then the function will return 0/x
//If either f1->den or f2->den is 0 it prints error
//and exits. It creates new fractions by sending the
//resultant numerator and denominator to newFractions
//then simplifies
Fraction *mulFractions(Fraction *f1, Fraction *f2) {
Fraction *f3;
int d, n;
//Finding 0 num
if (f1->num == 0 || f2->num == 0) n = 0;
else n = f1->num * f2->num;
//Finding 0 den
if (f1->den == 0 || f2->den == 0) {
printf("incorrect fraction (zero denominator)");
exit(1);
}
else d = f1->den * f2->den;
f3 = newFraction(n, d);
//Returning 0/1 for 0 num
if (f3->num == 0) {
f3->den = 1;
return f3;
}
else simplify(f3);
return f3;
}
//This divides the fractions, if either f1->num or
//f2->den is 0 then the function will return 0/x
//If either f1->den or f2->num is 0 it prints error
//and exits. It creates new fractions by sending the
//resultant numerator and denominator to newFractions
//then simplifies
Fraction *divFractions(Fraction *f1, Fraction *f2) {
Fraction *f3;
int n, d;
if (f1->num == 0 || f2->den == 0) {
n = 0;
}
else n = f1->num * f2->den;
//Finding 0/x
if (f1->den == 0 || f2->num == 0) {
printf("incorrect fraction (zero denominator)");
exit(1);
}
else d = f1->den * f2->num;
//Returning 0/1 for 0 num
f3 = newFraction(n, d);
if (f3->num == 0) {
f3->den = 1;
return f3;
}
simplify(f3);
return f3;
}
//This picks what operation is to take place, sends
//the fractions to the function of the given operator
//and returns the resultant fraction
Fraction *execute(Operator op, Fraction *f1, Fraction *f2) {
Fraction *f3;
switch (op) {
case 1:
f3 = addFractions(f1,f2);
break;
case 2:
f3 = subFractions(f1,f2);
break;
case 3:
f3 = mulFractions(f1,f2);
break;
case 4:
f3 = divFractions(f1,f2);
break;
}
return f3;
}