How do I add two fractions in a string?

How do I add two fractions together in a string like:

"1/2 + 1/4"

and get the answer 3/4?

I've been sitting here for hours and I just can't seem to find the solution.
closed account (48T7M4Gy)
http://www.cplusplus.com/forum/beginner/198895/
is there anyway to do it without a class? I'm taking a computer science intro class and we haven't really learned about classes yet so it would look weird if I used it.
Last edited on
Here's some functions that might help.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// https://en.wikipedia.org/wiki/Euclidean_algorithm#Background:_greatest_common_divisor
int gcd( int a, int b )
{
    while( b != 0 ) {
        int t{ b };
        b = a % b;
        a = t;
    }
    return a;
}

int lcm( int a, int b )
{
    return a * b / gcd( a, b );
}
How do I get the 1, 2 and 1, 4 by themselves though? I can't calculate the greatest common divisor without those numbers.
How do I get the 1, 2 and 1, 4 by themselves though? I can't calculate the greatest common divisor without those numbers.


Maybe something like this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct Fraction
{
    Fraction( int n = 0, int d = 1 ) : num{ n }, den{ d }
    {

    }

    int num, den;
}

istream& operator>>( istream& is, Fraction& f )
{
    char c{};
    return is >> f.num >> c >> f.den;
}

int main( )
{
    fraction lhs{}, rhs{}; char op{};
    cout << "enter expression: ";
    cin >> lhs >> op >> rhs;
}
OP: since you can't use class I'm not sure you can use struct. If not, you can try something like this to get your numbers into a container (here vector, can even be an array) and then you can do whatever you want with them:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main()
{
    cout<<"Enter string: \n";
    string s;
    getline(cin, s);
    vector<int> v;
    for(auto& elem : s)
    {
        if(isdigit(elem))
        {
            int i = (int)elem - 48;//character encodings for digits in order from 48 (for '0') to 57 (for '9') in ASCII, UTF
            v.push_back(i);
        }
    }
    for(auto& elem : v)
    {
        cout<< elem << "\t";
    }
}




closed account (48T7M4Gy)
is there anyway to do it without a class? I'm taking a computer science intro class and we haven't really learned about classes yet so it would look weird if I used it.


Of course there is, and the reason I referred to an earlier post is to show the various aspects involved which can be used any number of ways.

You can use classes, structs or neither of these. That choice is yours especially if you are not familiar with them.

The point of the class I referred to is it shows how to manipulate the two numerators and two denominators and, this is the crunch, the GCD function to cancel out common factors in the numerator and denominator.

In simple terms your inputs to the addition function ( from processing the overall input string ) are just 4 integers corresponding to the numerator and denominator of each fraction. Call them a,b, c & d. ie a/b + c/d Then calculate integers x and y which are the numerator and denominator of the answer.
So,
a/b + c/d = x/y just like on pencil and paper

Now, a/b + c/d = (a*d +c*b) /(b *d ) so we get x and y (Don't do the division, just get the values of x and y)

Next cancel factors (via GCD) of x and y and, bingo you have your fraction

cout << "answer = " << x << "/" << y << endl;

The missing GCD:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// GREATEST COMMON_DIVISOR
// https://en.wikipedia.org/wiki/Greatest_common_divisor#Using_Euclid.27s_algorithm
int Fraction::GCD( int aa, int bb)
{
    int a = aa;
    int b = bb;
    
    int b_previous = 0;

    // SORT NUMBERS
    int temp = 0;
    if (a < b)
    {
        temp = b;
        b = a;
        a = temp;
    }
    
    int remainder = a % b   ;
    
    if(remainder == 0)
        return b;
    
    while( remainder != 0 )
    {
        a = b;
        b = remainder;
        b_previous = remainder;
        
        remainder = a % b;
    }
    
    return b_previous;
}
Last edited on
@kemort I get how to calculate the answer, but I still don't get how I do those calculations from the single string.

How does: "1/2 + 1/4"

Become 1*4 + 1*2/2*4 ?

Like how do the numbers become integers? That's what I don't get.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
bool get_input( int lhs[2], int rhs[2], char& op )
{
    cout << "enter expression: ";
    char div[2]{};
    cin >> lhs[0] >> div[0] >> lhs[1]
        >> op
        >> rhs[0] >> div[1] >> rhs[1];

    // check validity of input
}

// assume all arguments are valid
void calculate( int lhs[2], int rhs[2], char op, int ans[2] )
{
    switch( op )
    {
    case '+':
        // ...
        break;
    }
}

int main( )
{
    while( true ) {
        int lhs[2]{}, rhs[2]{}; char op{};
        if( !get_input( lhs, rhs, op ) ) 
            // invalid input

        int ans[2]{};
        calculate( lhs, rhs, op, ans );

        cout << "= " << ans[0] << '/' << ans[1] << "\n\n";
    }
}
Last edited on
closed account (48T7M4Gy)
Like how do the numbers become integers? That's what I don't get.


You are talking about parsing the string, so this article, the second response in particular should get you started. Don't forget that there is a string to integer function in <string> and if the equation is always the same you can ignore the / and + characters except for being delimiters. You might need to chech for minus signs but that depends on how tough your teacher is.

http://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
It isn't going to be very happy about minus signs, but try this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;


#define NL << endl <<                                           // because I'm lazy!


//======================================================================


vector<string> stringSplit( string s, string delimiters )       // Split a string at anything in delimiters
{
  vector<string> v;
  int p;

  while( s.size() > 0 )
  {
     p = s.find_first_of( delimiters, 0 );                      // position of first delimiter
     if ( p == string::npos )                                   // if none, just use the rest of the string
     {   
        v.push_back( s );
        s = "";
     }
     else
     {
        v.push_back( s.substr( 0, p ) );                        // up to first delimiter
        v.push_back( s.substr( p, 1 ) );                        // delimiter itself
        s = s.substr( p + 1 );                                  // remainder of string
     }
   }

  return v;
}


//======================================================================


int main()
{
   string testString;
   string delimiters = "+-*/";
   int numerator1, numerator2, denominator1, denominator2;

   // Assign the test string
   cout << "Input a test string: ";
   getline( cin, testString );
   cout << "Test string is: " + testString << endl;


   // Break up the string at the delimiters
   vector<string> parts = stringSplit( testString, delimiters );    
   cout << "\nParts are:" << endl;
   for ( int i = 0; i < parts.size(); i++ ) cout << parts[i] << endl;


   // Dig out the integer bits
   stringstream( parts[0] ) >> numerator1;
   stringstream( parts[2] ) >> denominator1;
   stringstream( parts[4] ) >> numerator2;
   stringstream( parts[6] ) >> denominator2;
   cout << "\nIntegers are:" << endl;
   cout << numerator1 NL denominator1 NL numerator2 NL denominator2 << endl;
}

Thanks for the responses everyone, I'll try them out
closed account (48T7M4Gy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <sstream>

int main()
{
    int a = 0;
    int b = 0;
    
    int c = 0;
    int d = 0;
    
    char divide;
    char op;
    
    std::string  input = "-1/2 + 3/4";
    
    std::stringstream stream;
    stream.str(input);
    
    stream >> a >> divide >> b >> op >> c >> divide >> d;
    
    std:: cout << "a = " << a << '\n';
    std:: cout << "b = " << b << '\n';
    
    std:: cout << "c = " << c << '\n';
    std:: cout << "d = " << d << '\n';
    
    std::cout << "x = " << a*d + b*c << '\n';
    std::cout << "y = " << b*d << '\n';
    
    return 0;
}
a = -1
b = 2
c = 3
d = 4
x = 2
y = 8
Program ended with exit code: 0
Last edited on
stream >> a >> divide >> b >> op >> c >> divide >> d;

I have to confess that that is just beautifully simple!
Good programmers tend to be really good at making things ridiculously simple and efficient.
Thank you @kemort!!
Topic archived. No new replies allowed.