Reading negative numbers from command line
This is a program I'm writing for class. I'm not sure if it is required to accept negative numbers but I'm trying to make it do that anyways. The purpose of the program is to do operations on fractions that are input on the command line. Input would be a.out div 2/3 4/2. It works fine with positive integers, however when I tried it with negative integers it runs into what seems to be an infinite loop. I think the problem is with sscanf in the function readFraction. I posted the entire code in case it matters.
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;
}