How to read an equation from STDin

So I'm trying to figure out how I could write a program that reads user input from STDin in the following format: y = mx+b. I want the user to be able to enter the full equation as listed above and for two lines. I want my program to be able to read the two lines and determine if they have a solution and the point at that solution (i.e. they intersect).

I have a header and implementation file for the functions that will determine these things, but I'm not sure how to go about reading user input like y = mx + b and grabbing the appropriate values. Help?

This is my header file with descriptions on what everything does:

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#ifndef LINE_H_
#define LINE_H_

#include <ostream>
#include <iostream>
using namespace std;


struct Point
{
	double x;
	double y;

  /**
  Description:   Default constructor for Point structure.
  Return:        None
  Precondition:  None.
  Postcondition: Initializes x and y to zero.
  */
	Point(double a = 0.0, double b = 0.0)
	{
		x = a;
		y = b;
	}
  /**
  Description:   Display function that displays coordinates of point.
  Return:        Void
  Precondition:  Point exits.
  Postcondition: Displays coordinates in ( , ) format.
  */
	void display(ostream& out)
	{
		out << "(" << x << "," << y << ")";
	}
};


class Line
{
private:
  Point p1, p2;

public:

  /**
  Description:   Default constructor for Line class
  Return:        None
  Precondition:  None
  Postcondition: Initializes default coordinates for p1 and p2
  */
  Line();

  /**
  Description:   Custom constructor for Line class
  Return:        None
  Precondition:  None
  Postcondition: Constructs Line class given two Points
                (each composed of an x and y coordinate)
  */
  Line(Point, Point);

  /**
  Description:   Mutator method used to set the first set of
                 x and y coordinates.
  Return:        Void
  Precondition:  Line must exist
  Postcondition: Sets the coordinates of p1 (first point)
  */
  void setFirstPoint(Point);

  /**
  Description:   Mutator method used to set the second set of
                 x and y coordinates.
  Return:        Void
  Precondition:  Line must exist
  Postcondition: Sets the coordinates of p2 (second point)
  */
  void setSecondPoint(Point);

  /**
  Description:   Constant function that returns the first point, of which
                 includes an x and y coordinate.
  Return:        Point
  Precondition:  Line must exist
  Postcondition: Returns the value of p1 (composed of an x and a y coordinate)
  */
  Point getFirstPoint() const;

  /**
  Description:   Constant function that returns the second point, of which
                 includes an x and y coordinate.
  Return:        Point
  Precondition:  Line must exist
  Postcondition: Returns the value of p2 (composed of an x and a y coordinate)
  */
  Point getSecondPoint() const;

  /**
  Description:   Constant function that returns whether a line has a slope
                 (verifies that it is valid, i.e not zero or undefined).
  Return:        Bool
  Precondition:  Line must exist
  Postcondition: Returns the whether the slope exists, and if so, the value of
                 the slope via a reference parameter.
  */
  bool slope(double& m) const;

  /**
  Description:   Constant function that returns whether the line has a y
                 intercept value.
  Return:        Bool
  Precondition:  Line must exist
  Postcondition: Returns the a y-intercept exists, and its value
                 via a reference parameter.
  */
  bool yIntercept(double& b) const;

  /**
  Description:   Constant function that determines if 2 lines are parallel
  Return:        Bool
  Precondition:  2 Lines must exist
  Postcondition: Returns whether 2 lines are parallel by comparing their slopes
  */
  bool isParallel(Line) const;

  /**
  Description:   Constant function that determines if 2 lines are collinear.
  Return:        Bool
  Precondition:  2 Lines must exist
  Postcondition: Returns whether 2 lines are collinear by comparing their
                 p1 and p2 coordinates.
  */
  bool isCollinear(Line) const;
  /**
  Description:   Constant function that determines if 2 lines are
                 perpendicular.
  Return:        Bool
  Precondition:  2 Lines must exist
  Postcondition: Returns whether 2 lines are perpendicular by determining if
                 one slope is the negative reciprocal of the other slope.
  */
  bool isPerpendicular(Line) const;

  /**
  Description:   Constant function that returns the point of intersection of
                 2 lines.
  Return:        Point
  Precondition:  2 Lines must exist
  Postcondition: Returns the intersection point of the 2 lines
                 (x and y coordinates)
  */
  Point intersect(Line) const;

  /**
  Description:   Constant function that displays a message to output stream
  Return:        Void
  Precondition:  none.
  Postcondition: Displays a message to output stream (stdout, file, etc.)
  */
  void display(ostream&) const;
};

#endif /* LINE_H_ */
Last edited on
how to go about reading user input like y = mx + b and grabbing the appropriate values. Help?

May this basic code be of any help?
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <exception>
#include <iostream>
#include <limits>
#include <string>
#include <optional>
#include <utility>
#include <vector>

std::optional<double> stodNoExcept(const std::string& s);
std::optional<double> getGradient(const std::string& s);
void waitForEnter();

const std::vector<std::string> errs {
    { "Equal symbol missing: badly formed equation rejected.\n" },          //  0
    { "Two 'x' parameters detected: badly formed equation rejected.\n" },   //  1
    { "Two '+' symbols detected: badly formed equation rejected.\n" },      //  2
    { "Cannot recognize y-intercept term.\nEquation should be in the form "
      "y = mx + b.\nPlease retry.\n" },                                     //  3
    { "Cannot extract gradient.\nEquation should be in the form "
      "y = mx + b.\nPlease retry.\n" },                                     //  4
                                        };

int main()
{
    // y = mx + b
    //    -->   m       b
    std::pair<double, double> par;
    bool again { true };
    do {
        par = { 0.0, 0.0 };
        std::cout << "Please enter equation (ex. y = mx + b): ";
        std::string line;
        std::getline(std::cin, line);
        // Method: check for y = mx + b, y = mx (b==0), y = b (m==0).
        //         Don't check for mx + b = y, so if input "4 = y", then
        //         the equation is ill-formed and rejected.
        // Discard up to '=' included.
        std::string::size_type ps = line.find('=');
        if(ps == std::string::npos) { std::cout << errs.at(0); continue; }
        line = line.substr(ps+1);

        // "line" could be: "mx + b", "mx", "b" or "y".
        // Search for '+' and 'x' (there should be only one of each of them).
        // 1) if both
        //    if '+' comes first, than "b + mx" otherwise "mx + b".
        // 2) if 'x', than "mx" or "xm", otherwise "b" or "y".
        std::string::size_type ps_x = line.find('x');
        // no duplicate admitted
        if(ps_x != std::string::npos && line.find('x', ps_x+1) != std::string::npos)
            { std::cout << errs.at(1); continue; }
        ps = line.find('+');
        if(ps != std::string::npos && line.find('+', ps+1) != std::string::npos)
            { std::cout << errs.at(2); continue; }

        if(ps_x != std::string::npos) {
            if(ps != std::string::npos) {    // both "mx" and "b"
                if(ps < ps_x) {     // "b + mx"
                    std::optional<double> b = stodNoExcept(line);
                    if(b) { par.second = b.value(); }
                    else  { std::cout << errs.at(3); continue; }
                    line = line.substr(ps+1);
                    std::optional<double> m = getGradient(line);
                    if(m) { par.first = m.value(); }
                    else  { std::cout << errs.at(4); continue; }
                } else {            // "mx + b" or "xm + b"
                    std::optional<double> m = getGradient(line);
                    if(m) { par.first = m.value(); }
                    else  { std::cout << errs.at(4); continue; }
                    line = line.substr(ps+1);
                    std::optional<double> b = stodNoExcept(line);
                    if(b) { par.second = b.value(); }
                    else  { std::cout << errs.at(3); continue; }
                }
            } else {    // only "mx" or "xm"
                std::optional<double> m = getGradient(line);
                if(m) { par.first = m.value(); }
                else  { std::cout << errs.at(4); continue; }
            }
        } else {        // only "b" (or "y", i.e. not a number)
            std::optional<double> b = stodNoExcept(line);
            if(b) { par.second = b.value(); }
            else  { std::cout << errs.at(3); continue; }
        }
        std::cout << "Equation y = mx + b where m = " << par.first
                  << " and b = " << par.second << ".\n"
                     "Do you want to enter another equation (y/n)? ";
        char c {};
        std::cin >> c;
        std::cin.ignore(1000, '\n');
        if('y' != c) { again = false; }
    } while(again);
    waitForEnter();
    return 0;
}

std::optional<double> stodNoExcept(const std::string& s)
{
    try {
        double d = std::stod(s);
        return { d };
    } catch(std::logic_error& e) {
        return std::nullopt;
    }
}

// s: "mx", "xm", "mx + b", "xm + b" --> '+' must be after 'x' or missing
std::optional<double> getGradient(const std::string& s)
{
    std::optional<double> g = stodNoExcept(s);
    if(g) { return g; } // "mx" or "mx + b"
    return stodNoExcept( s.substr(s.find('x')+1) ); // from char after 'x' on
}

void waitForEnter()
{
    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Output:
Please enter equation (ex. y = mx + b): y = 13x + 666
Equation y = mx + b where m = 13 and b = 666.
Do you want to enter another equation (y/n)? y
Please enter equation (ex. y = mx + b): y = 13
Equation y = mx + b where m = 0 and b = 13.
Do you want to enter another equation (y/n)? y
Please enter equation (ex. y = mx + b): y = 13x
Equation y = mx + b where m = 13 and b = 0.
Do you want to enter another equation (y/n)? n

Press ENTER to continue...

Thank you very much!
Topic archived. No new replies allowed.