Thread: Reading negative numbers from command line

  1. #1
    Registered User
    Join Date
    Nov 2009
    Posts
    4

    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;
    }
    Last edited by Ace2187; 12-05-2009 at 11:56 PM. Reason: removed debugging printf

  2. #2
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    I use strtol to convert strings to numeric values, then you'll get both negative and positive numbers. In your case I guess that you do some parsing of the string first, but the principle is the same.

  3. #3
    Registered User
    Join Date
    Nov 2009
    Posts
    4
    How exactly would I achieve this? Either method.

  4. #4
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by Ace2187 View Post
    How exactly would I achieve this? Either method.
    strtol, has a man page but the normal call would look like this for base 10:

    Code:
    int numerator = strtol(string, NULL, 0);
    Parsing is done by looking for characters in the string for example '/' and for example replace it with null. You will then get a sub string at that index +1.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Negative numbers in C
    By BlaX in forum C Programming
    Replies: 18
    Last Post: 06-29-2009, 06:30 PM
  2. reading numbers from input file
    By ziga in forum C++ Programming
    Replies: 1
    Last Post: 08-17-2007, 06:23 AM
  3. Reading numbers from a text file
    By wolfindark in forum C++ Programming
    Replies: 12
    Last Post: 03-24-2007, 01:57 PM
  4. question: reading numbers into an array
    By Lince in forum C Programming
    Replies: 15
    Last Post: 11-15-2006, 03:41 AM
  5. Logical errors with seach function
    By Taka in forum C Programming
    Replies: 4
    Last Post: 09-18-2006, 05:20 AM