I want to create a kind of parser of the form:
#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
using namespace std;
bool isValid(istringstream& is)
{
char ch;
is.get(ch); //I know get(ch) is a good start but this is as for as I got :)
.......
....
}
int main()
{
string s;
while(getline(cin,s))
{
istringstream is(s);
cout<<(isValid(is)? "Expression OK" : "Not OK")<<endl;
}
}
A boolean function that returns TRUE if the sequence of char is of the form "5" or "(5+3)" or "((5+3)+6)" or "(((4+2)+1)+6)" ...etc and FALSE for any other case
Basically, an expression will be considered as valid if it is either a single digit or of the form "open parenthesis-single digit-plus sign-single digit-close parenthesis"
Valid Expression = single digit
and
Valid Expression = (Valid Expression + Valid Expression)
Given that there is no limit to the size of the above form (number of opening and closing parenthesis..etc.) I'd like to do that using recursion
Being the newbie that I am.. Thank you for any helpful input!
To do a recursive solution you're gonna want to read the string into a buffer first, then do something like this:
int expression(char* str) {
if (*str == '(') {
int e1 = expression(str + 1);
if (e1 == -1 || *(str + 1 + e) != '+') {
return -1;
}
int e2 = expression(str + 1 + e + 1);
if (e2 == -1 || *(str + 1 + e + 1 + e2) != ')') {
return -1;
}
return 1 + e1 + 1 + e2 + 1;
}
if (*str >= '0' || *str <= '9') {
return 1;
}
return -1;
}
bool isvalid(char* str) {
int e1 = expression(str);
if (e1 < 0) {
return false;
}
if (e1 == strlen(str)) {
return true;
}
if (*(str + e1) != '+') {
return false;
}
int e2 = expression(str + e1 + 1);
if (e2 < 0) {
return false;
}
return (e1 + 1 + e2 == strlen(str));
}
Basically, the expression function returns the length of the valid expression at it's argument. If it's argument begins with a parenthesis, it gets the length of the expression after that, verifies the plus after that, then verifies the closing parenthesis after the next expression. If the argument begins with a number, return 1. If something is messed up, return -1. Then using that function we can figure out whether or not the string is valid by some sums and the length of the string.
I haven't tested the function at all, but the only case this might fail in that I can think of would be excessive parenthesis: ((5)) for example.
An alternative to recursion could be some sort of lexical parsing such as this:
enum {
ExpectingLeftExpression,
ExpectingRightExpression,
ExpectingPlus,
ExpectingEnd,
} ParseState;
// returns true if str is valid
bool check(char* str) {
ParseState state = ExpectingLeftExpression;
do {
switch (state) {
case ExpectingLeftExpression:
if (*str == '(') {
} else if (*str >= '0' && *str <= '9') {
state = ExpectingPlus;
} else {
printf("Error: Expected left hand expression.");
return false;
}
break;
case ExpectingPlus:
if (*str == '+') {
state = ExpectingRightExpression;
} else {
printf("Error: Expected plus.");
return false;
}
break;
case ExpectingRightExpression:
if (*str == '(') {
state = ExpectingLeftExpression;
} else if (*str >= '0' && *str <= '9') {
state = ExpectingEnd;
} else {
printf("Error: Expected right hand expression.");
return false;
}
break;
}
} while (*(++str));
return true;
}
That function's not complete at all, but you should be able to see where it's going. I think the recursion works better in this case anyways.
Related
I just had a small question about my program. So, I have a function that evaluates a postfix expression and returns the integer or float calculated. Here are the following functions involved:
#include <iostream>
#include <sstream>
#include <cstring>
#include <stack>
#include <limits>
float postfixUtility::evaluatePostfix(string pexp)
{
stack<int> S;
int pexpLength = pexp.length();
cout << pexpLength << endl;
for (int i = 0; i < pexpLength; i++)
{
if(pexp[i] == ' ' || pexp[i] == ',')
{
continue;
}
else if(isOperator(pexp[i]))
{
int operand2 = S.top(); S.pop();
int operand1 = S.top(); S.pop();
int result = isOperate(pexp[i], operand1, operand2);
S.push(result);
}
else if(isDigit(pexp[i]))
{
int operand = 0;
while(i<pexp.length() && isDigit(pexp[i]))
{
operand = (operand*10) + (pexp[i] - '0');
i++;
}
i--;
S.push(operand);
}
}
return S.top();
}
bool postfixUtility::isDigit(char C)
{
if(C >= '0' && C <= '9')
{
return true;
}
return false;
}
bool postfixUtility::isOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/')
{
return true;
}
return false;
}
int postfixUtility::isOperate(char operation, int operand1, int operand2)
{
if(operation == '+')
{
return operand1+operand2;
}
if(operation == '-')
{
return operand1-operand2;
}
if(operation == '*')
{
return operand1*operand2;
}
if(operation == '/')
{
return operand1/operand2;
}
}
These functions work together to solve the postfix expression inputted. The expression inputted is not empty and actually holds a postfix expression. However, every time I run the code, it results in a segfault. I am quite baffled actually because it seems to me that my code should work.
Thank you!
EDIT #1: So, the original input to my function is: "(4+3* 12)/ ( 12+ 3/ 2+ 46 /4)"
Then, I put that through another function to convert it to postfix. This is that function:
int postfixUtility::priority(char a)
{
int temp;
if (a == '^')
temp = 1;
else if (a == '*' || a == '/')
temp = 2;
else if (a == '+' || a == '-')
temp = 3;
return temp;
}
string postfixUtility::getPostfix(string nexp)
{
stack<char> operator_stack;
stringstream output;
for (unsigned i = 0; i < nexp.length(); i++) {
if (nexp[i] == '+' || nexp[i] == '-' || nexp[i] == '*' || nexp[i] == '/' || nexp[i] == '^') {
while (!operator_stack.empty() && priority(operator_stack.top()) <= priority(nexp[i])) {
output << operator_stack.top();
operator_stack.pop();
}
operator_stack.push(nexp[i]);
} else if (nexp[i] == '(') {
operator_stack.push(nexp[i]);
} else if (nexp[i] == ')') {
while (operator_stack.top() != '(') {
output << operator_stack.top();
operator_stack.pop();
}
operator_stack.pop();
} else {
output << nexp[i];
}
}
while (!operator_stack.empty()) {
output << operator_stack.top();
operator_stack.pop();
}
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
return output.str();
}
Which converts it to: "43 12*+ 12 3 2/+ 46 4/+/", is that wrong? Would that be the reason why I am getting a segfault?
EDIT #2: So, I have commented out 2 lines in my code and I am no longer getting a segfault.
float postfixUtility::evaluatePostfix(string pexp)
{
stack<int> S;
int pexpLength = pexp.length();
for (int i = 0; i < pexpLength; i++)
{
if(pexp[i] == ' ' || pexp[i] == ',')
{
continue;
}
else if(isOperator(pexp[i]))
{
float operand2 = S.top();
//S.pop();
float operand1 = S.top();
//S.pop();
float result = isOperate(pexp[i], operand1, operand2);
S.push(result);
}
else if(isDigit(pexp[i]))
{
int operand = 0;
while(i<pexp.length() && isDigit(pexp[i]))
{
operand = (operand*10) + (pexp[i] - '0');
i++;
}
i--;
S.push(operand);
}
}
return S.top();
}
However, the answer is supposed to be 1.6, but I am getting 1. Any reason why that is happening?
EDIT #3: I changed the isOperate function to the following:
float postfixUtility::isOperate(char operation, float operand1, float operand2)
{
if(operation == '+')
{
return operand1+operand2;
}
else if(operation == '-')
{
return operand1-operand2;
}
else if(operation == '*')
{
return operand1*operand2;
}
else if(operation == '/')
{
return operand1/operand2;
}
}
However, I still get 1 as a result.
Those pops where important:
float operand2 = S.top();
//S.pop();
float operand1 = S.top();
//S.pop();
Without popping the last element, operand1 will always be equal to operand2 and dividing a number by itself usually results in 1.
The reason you where getting a segfault in the first place is that your postfix converter is giving you (very) wrong results (which should be clear from the fact that its output contains numbers not present in its input). Let's have look at the first part of the output you posted: 43 12*+. Your parser will identify 43 and 12 as numbers and push them on the stack. It will identify * as an operator, take the two numbers from the stack, multiply them and push the result on the stack. Then it will encounter + and try to take two operands from the stack. However, there's only one element on the stack, namely the result of the multiplication. Calling top() on an empty stack is causing your segfault.
Edit: It is generally a good idea to do a sanity check before performing a operation that could result in undefined behavior for incorrect input.This allows you to either do something to solve the problem or to produce an error message containing diagnostic information (e.g. in your case the operator, the position in the string, the string itself, etc.). This will help you identify such problems more easily.
tl;dr: Fix your postfix converter.
The following is the interview question:
Machine coding round: (Time 1hr)
Expression is given and a string testCase, need to evaluate the testCase is valid or not for expression
Expression may contain:
letters [a-z]
'.' ('.' represents any char in [a-z])
'*' ('*' has same property as in normal RegExp)
'^' ('^' represents start of the String)
'$' ('$' represents end of String)
Sample cases:
Expression Test Case Valid
ab ab true
a*b aaaaaab true
a*b*c* abc true
a*b*c aaabccc false
^abc*b abccccb true
^abc*b abbccccb false
^abcd$ abcd true
^abc*abc$ abcabc true
^abc.abc$ abczabc true
^ab..*abc$ abyxxxxabc true
My approach:
Convert the given regular expression into concatenation(ab), alteration(a|b), (a*) kleenstar.
And add + for concatenation.
For example:
abc$ => .*+a+b+c
^ab..*abc$ => a+b+.+.*+a+b+c
Convert into postfix notation based on precedence.
(parantheses>kleen_star>concatenation>..)
(a|b)*+c => ab|*c+
Build NFA based on Thompson construction
Backtracking / traversing through NFA by maintaining a set of states.
When I started implementing it, it took me a lot more than 1 hour. I felt that the step 3 was very time consuming. I built the NFA by using postfix notation +stack and by adding new states and transitions as needed.
So, I was wondering if there is faster alternative solution this question? Or maybe a faster way to implement step 3. I found this CareerCup link where someone mentioned in the comment that it was from some programming contest. So If someone has solved this previously or has a better solution to this question, I'd be happy to know where I went wrong.
Some derivation of Levenshtein distance comes to mind - possibly not the fastest algorithm, but it should be quick to implement.
We can ignore ^ at the start and $ at the end - anywhere else is invalid.
Then we construct a 2D grid where each row represents a unit [1] in the expression and each column represents a character in the test string.
[1]: A "unit" here refers to a single character, with the exception that * shall be attached to the previous character
So for a*b*c and aaabccc, we get something like:
a a a b c c c
a*
b*
c
Each cell can have a boolean value indicating validity.
Now, for each cell, set it to valid if either of these hold:
The value in the left neighbour is valid and the row is x* or .* and the column is x (x being any character a-z)
This corresponds to a * matching one additional character.
The value in the upper-left neighbour is valid and the row is x or . and the column is x (x being any character a-z)
This corresponds to a single-character match.
The value in the top neighbour is valid and the row is x* or .*.
This corresponds to the * matching nothing.
Then check if the bottom-right-most cell is valid.
So, for the above example, we get: (V indicating valid)
a a a b c c c
a* V V V - - - -
b* - - - V - - -
c - - - - V - -
Since the bottom-right cell isn't valid, we return invalid.
Running time: O(stringLength*expressionLength).
You should notice that we're mostly exploring a fairly small part of the grid.
This solution can be improved by making it a recursive solution making use of memoization (and just calling the recursive solution for the bottom-right cell).
This will give us a best-case performance of O(1), but still a worst-case performance of O(stringLength*expressionLength).
My solution assumes the expression must match the entire string, as inferred from the result of the above example being invalid (as per the question).
If it can instead match a substring, we can modify this slightly so, if the cell is in the top row it's valid if:
The row is x* or .*.
The row is x or . and the column is x.
Given only 1 hour we can use simple way.
Split pattern into tokens: a*b.c => { a* b . c }.
If pattern doesn't start with ^ then add .* in the beginning, else remove ^.
If pattern doesn't end with $ then add .* in the end, else remove $.
Then we use recursion: going 3 way in case if we have recurring pattern (increase pattern index by 1, increase word index by 1, increase both indices by 1), going one way if it is not recurring pattern (increase both indices by 1).
Sample code in C#
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ReTest
{
class Program
{
static void Main(string[] args)
{
Debug.Assert(IsMatch("ab", "ab") == true);
Debug.Assert(IsMatch("aaaaaab", "a*b") == true);
Debug.Assert(IsMatch("abc", "a*b*c*") == true);
Debug.Assert(IsMatch("aaabccc", "a*b*c") == true); /* original false, but it should be true */
Debug.Assert(IsMatch("abccccb", "^abc*b") == true);
Debug.Assert(IsMatch("abbccccb", "^abc*b") == false);
Debug.Assert(IsMatch("abcd", "^abcd$") == true);
Debug.Assert(IsMatch("abcabc", "^abc*abc$") == true);
Debug.Assert(IsMatch("abczabc", "^abc.abc$") == true);
Debug.Assert(IsMatch("abyxxxxabc", "^ab..*abc$") == true);
}
static bool IsMatch(string input, string pattern)
{
List<PatternToken> patternTokens = new List<PatternToken>();
for (int i = 0; i < pattern.Length; i++)
{
char token = pattern[i];
if (token == '^')
{
if (i == 0)
patternTokens.Add(new PatternToken { Token = token, Occurence = Occurence.Single });
else
throw new ArgumentException("input");
}
else if (char.IsLower(token) || token == '.')
{
if (i < pattern.Length - 1 && pattern[i + 1] == '*')
{
patternTokens.Add(new PatternToken { Token = token, Occurence = Occurence.Multiple });
i++;
}
else
patternTokens.Add(new PatternToken { Token = token, Occurence = Occurence.Single });
}
else if (token == '$')
{
if (i == pattern.Length - 1)
patternTokens.Add(new PatternToken { Token = token, Occurence = Occurence.Single });
else
throw new ArgumentException("input");
}
else
throw new ArgumentException("input");
}
PatternToken firstPatternToken = patternTokens.First();
if (firstPatternToken.Token == '^')
patternTokens.RemoveAt(0);
else
patternTokens.Insert(0, new PatternToken { Token = '.', Occurence = Occurence.Multiple });
PatternToken lastPatternToken = patternTokens.Last();
if (lastPatternToken.Token == '$')
patternTokens.RemoveAt(patternTokens.Count - 1);
else
patternTokens.Add(new PatternToken { Token = '.', Occurence = Occurence.Multiple });
return IsMatch(input, 0, patternTokens, 0);
}
static bool IsMatch(string input, int inputIndex, IList<PatternToken> pattern, int patternIndex)
{
if (inputIndex == input.Length)
{
if (patternIndex == pattern.Count || (patternIndex == pattern.Count - 1 && pattern[patternIndex].Occurence == Occurence.Multiple))
return true;
else
return false;
}
else if (inputIndex < input.Length && patternIndex < pattern.Count)
{
char c = input[inputIndex];
PatternToken patternToken = pattern[patternIndex];
if (patternToken.Token == '.' || patternToken.Token == c)
{
if (patternToken.Occurence == Occurence.Single)
return IsMatch(input, inputIndex + 1, pattern, patternIndex + 1);
else
return IsMatch(input, inputIndex, pattern, patternIndex + 1) ||
IsMatch(input, inputIndex + 1, pattern, patternIndex) ||
IsMatch(input, inputIndex + 1, pattern, patternIndex + 1);
}
else
return false;
}
else
return false;
}
class PatternToken
{
public char Token { get; set; }
public Occurence Occurence { get; set; }
public override string ToString()
{
if (Occurence == Occurence.Single)
return Token.ToString();
else
return Token.ToString() + "*";
}
}
enum Occurence
{
Single,
Multiple
}
}
}
Here is a solution in Java. Space and Time is O(n). Inline comments are provided for more clarity:
/**
* #author Santhosh Kumar
*
*/
public class ExpressionProblemSolution {
public static void main(String[] args) {
System.out.println("---------- ExpressionProblemSolution - start ---------- \n");
ExpressionProblemSolution evs = new ExpressionProblemSolution();
evs.runMatchTests();
System.out.println("\n---------- ExpressionProblemSolution - end ---------- ");
}
// simple node structure to keep expression terms
class Node {
Character ch; // char [a-z]
Character sch; // special char (^, *, $, .)
Node next;
Node(Character ch1, Character sch1) {
ch = ch1;
sch = sch1;
}
Node add(Character ch1, Character sch1) {
this.next = new Node(ch1, sch1);
return this.next;
}
Node next() {
return this.next;
}
public String toString() {
return "[ch=" + ch + ", sch=" + sch + "]";
}
}
private boolean letters(char ch) {
return (ch >= 'a' && ch <= 'z');
}
private boolean specialChars(char ch) {
return (ch == '.' || ch == '^' || ch == '*' || ch == '$');
}
private void validate(String expression) {
// if expression has invalid chars throw runtime exception
if (expression == null) {
throw new RuntimeException(
"Expression can't be null, but it can be empty");
}
char[] expr = expression.toCharArray();
for (int i = 0; i < expr.length; i++) {
if (!letters(expr[i]) && !specialChars(expr[i])) {
throw new RuntimeException(
"Expression contains invalid char at position=" + i
+ ", invalid_char=" + expr[i]
+ " (allowed chars are 'a-z', *, . ^, * and $)");
}
}
}
// Parse the expression and split them into terms and add to list
// the list is FSM (Finite State Machine). The list is used during
// the process step to iterate through the machine states based
// on the input string
//
// expression = a*b*c has 3 terms -> [a*] [b*] [c]
// expression = ^ab.*c$ has 4 terms -> [^a] [b] [.*] [c$]
//
// Timing : O(n) n -> expression length
// Space : O(n) n -> expression length decides the no.of terms stored in the list
private Node preprocess(String expression) {
debug("preprocess - start [" + expression + "]");
validate(expression);
Node root = new Node(' ', ' '); // root node with empty values
Node current = root;
char[] expr = expression.toCharArray();
int i = 0, n = expr.length;
while (i < n) {
debug("i=" + i);
if (expr[i] == '^') { // it is prefix operator, so it always linked
// to the char after that
if (i + 1 < n) {
if (i == 0) { // ^ indicates start of the expression, so it
// must be first in the expr string
current = current.add(expr[i + 1], expr[i]);
i += 2;
continue;
} else {
throw new RuntimeException(
"Special char ^ should be present only at the first position of the expression (position="
+ i + ", char=" + expr[i] + ")");
}
} else {
throw new RuntimeException(
"Expression missing after ^ (position=" + i
+ ", char=" + expr[i] + ")");
}
} else if (letters(expr[i]) || expr[i] == '.') { // [a-z] or .
if (i + 1 < n) {
char nextCh = expr[i + 1];
if (nextCh == '$' && i + 1 != n - 1) { // if $, then it must
// be at the last
// position of the
// expression
throw new RuntimeException(
"Special char $ should be present only at the last position of the expression (position="
+ (i + 1)
+ ", char="
+ expr[i + 1]
+ ")");
}
if (nextCh == '$' || nextCh == '*') { // a* or b$
current = current.add(expr[i], nextCh);
i += 2;
continue;
} else {
current = current.add(expr[i], expr[i] == '.' ? expr[i]
: null);
i++;
continue;
}
} else { // a or b
current = current.add(expr[i], null);
i++;
continue;
}
} else {
throw new RuntimeException("Invalid char - (position=" + (i)
+ ", char=" + expr[i] + ")");
}
}
debug("preprocess - end");
return root;
}
// Traverse over the terms in the list and iterate and match the input string
// The terms list is the FSM (Finite State Machine); the end of list indicates
// end state. That is, input is valid and matching the expression
//
// Timing : O(n) for pre-processing + O(n) for processing = 2O(n) = ~O(n) where n -> expression length
// Timing : O(2n) ~ O(n)
// Space : O(n) where n -> expression length decides the no.of terms stored in the list
public boolean process(String expression, String testString) {
Node root = preprocess(expression);
print(root);
Node current = root.next();
if (root == null || current == null)
return false;
int i = 0;
int n = testString.length();
debug("input-string-length=" + n);
char[] test = testString.toCharArray();
// while (i < n && current != null) {
while (current != null) {
debug("process: i=" + i);
debug("process: ch=" + current.ch + ", sch=" + current.sch);
if (current.sch == null) { // no special char just [a-z] case
if (test[i] != current.ch) { // test char and current state char
// should match
return false;
} else {
i++;
current = current.next();
continue;
}
} else if (current.sch == '^') { // process start char
if (i == 0 && test[i] == current.ch) {
i++;
current = current.next();
continue;
} else {
return false;
}
} else if (current.sch == '$') { // process end char
if (i == n - 1 && test[i] == current.ch) {
i++;
current = current.next();
continue;
} else {
return false;
}
} else if (current.sch == '*') { // process repeat char
if (letters(current.ch)) { // like a* or b*
while (i < n && test[i] == current.ch)
i++; // move i till end of repeat char
current = current.next();
continue;
} else if (current.ch == '.') { // like .*
Node nextNode = current.next();
print(nextNode);
if (nextNode != null) {
Character nextChar = nextNode.ch;
Character nextSChar = nextNode.sch;
// a.*z = az or (you need to check the next state in the
// list)
if (test[i] == nextChar) { // test [i] == 'z'
i++;
current = current.next();
continue;
} else {
// a.*z = abz or
// a.*z = abbz
char tch = test[i]; // get 'b'
while (i + 1 < n && test[++i] == tch)
; // move i till end of repeat char
current = current.next();
continue;
}
}
} else { // like $* or ^*
debug("process: return false-1");
return false;
}
} else if (current.sch == '.') { // process any char
if (!letters(test[i])) {
return false;
}
i++;
current = current.next();
continue;
}
}
if (i == n && current == null) {
// string position is out of bound
// list is at end ie. exhausted both expression and input
// FSM reached the end state, hence the input is valid and matches the given expression
return true;
} else {
return false;
}
}
public void debug(Object str) {
boolean debug = false;
if (debug) {
System.out.println("[debug] " + str);
}
}
private void print(Node node) {
StringBuilder sb = new StringBuilder();
while (node != null) {
sb.append(node + " ");
node = node.next();
}
sb.append("\n");
debug(sb.toString());
}
public boolean match(String expr, String input) {
boolean result = process(expr, input);
System.out.printf("\n%-20s %-20s %-20s\n", expr, input, result);
return result;
}
public void runMatchTests() {
match("ab", "ab");
match("a*b", "aaaaaab");
match("a*b*c*", "abc");
match("a*b*c", "aaabccc");
match("^abc*b", "abccccb");
match("^abc*b", "abccccbb");
match("^abcd$", "abcd");
match("^abc*abc$", "abcabc");
match("^abc.abc$", "abczabc");
match("^ab..*abc$", "abyxxxxabc");
match("a*b*", ""); // handles empty input string
match("xyza*b*", "xyz");
}}
int regex_validate(char *reg, char *test) {
char *ptr = reg;
while (*test) {
switch(*ptr) {
case '.':
{
test++; ptr++; continue;
break;
}
case '*':
{
if (*(ptr-1) == *test) {
test++; continue;
}
else if (*(ptr-1) == '.' && (*test == *(test-1))) {
test++; continue;
}
else {
ptr++; continue;
}
break;
}
case '^':
{
ptr++;
while ( ptr && test && *ptr == *test) {
ptr++; test++;
}
if (!ptr && !test)
return 1;
if (ptr && test && (*ptr == '$' || *ptr == '*' || *ptr == '.')) {
continue;
}
else {
return 0;
}
break;
}
case '$':
{
if (*test)
return 0;
break;
}
default:
{
printf("default case.\n");
if (*ptr != *test) {
return 0;
}
test++; ptr++; continue;
}
break;
}
}
return 1;
}
int main () {
printf("regex=%d\n", regex_validate("ab", "ab"));
printf("regex=%d\n", regex_validate("a*b", "aaaaaab"));
printf("regex=%d\n", regex_validate("^abc.abc$", "abcdabc"));
printf("regex=%d\n", regex_validate("^abc*abc$", "abcabc"));
printf("regex=%d\n", regex_validate("^abc*b", "abccccb"));
printf("regex=%d\n", regex_validate("^abc*b", "abbccccb"));
return 0;
}
EDIT
This is homework so no straight up code please. Just hints, thank you!
I'm working on a project that will use an expression tree to derive a variety of things and then perform operations on them. Right now I'm not too worried about the deriving part, I just want to get the operations part down.
The expression tree code that I'm using works for integers but once I input "x" or any other variable my answer is wrong. My program works with postfix expression strings... below is an example of what is right and wrong.
5 6 + returns 11. correct
5x 6x + returns 11. incorrect needs to be 11x
Here is my code:
// This is the expression tree code I'm using
#ifndef EXPRNODE_H
#define EXPRNODE_H
#include <cstdlib> // for NULL
using namespace std;
//====================================== class ExprNode
class ExprNode {
public:
ExprNode(char oper, ExprNode* left, ExprNode* right);
ExprNode(int val);
int eval() const; // Evaluate expr tree. Return result.
private:
char _op; // one of +, -, *, /, #
int _value; // integer value used for constants.
ExprNode* _left; // left subtree
ExprNode* _right; // right subtree
};
#endif
//============================================= ExprNode constructor
// Constructs node for a binary operator.
ExprNode::ExprNode(char oper, ExprNode* left, ExprNode* right) {
_op = oper;
_left = left;
_right = right;
}
//============================================== ExprNode constructor
// Constructs a node for an integer constant
ExprNode::ExprNode(int v) {
_op = '#';
_value = v;
_left = NULL;
_right = NULL;
}
//===================================================== ExprNode::eval
int ExprNode::eval() const {
// Recursively evaluate expression tree and return result.
int result;
switch (_op) {
case '+':
result = _left->eval() + _right->eval();
break;
case '-':
result = _left->eval() - _right->eval();
break;
case '*':
result = _left->eval() * _right->eval();
break;
case '/':
result = _left->eval() / _right->eval();
break;
case '#':
result = _value; // an integer constant
break;
}
return result;
}
bool isOperator (char operand)
{
return operand == '+' || operand == '-' || operand == '*' || operand == '/' || operand == '^';
}
bool isNumber (char potentialNumber)
{
return potentialNumber >= '0' && potentialNumber <= '9';
}
bool isX (char letter)
{
return letter == 'x' || letter == 'X';
}
I'm not going to include the code going from infix to postfix because it is unnecessary (I think).... next is the code for the expression tree and calculations
// the expression string is the postfix expression I returned previously
void expressionTree(string expression)
{
string tempNum = "";
string tempNum2 = "";
int count = 1;
int tempNumInt;
int tempNum2Int;
// creates a blank total value and blank numbers
ExprNode* totalVal = new ExprNode('+', new ExprNode(0), new ExprNode(0));
ExprNode* tNum;
ExprNode* tNum2;
// loop through the postfix expression
for (unsigned int iterator = 0; iterator < expression.length(); iterator++)
{
if (isOperator(expression[iterator]))
{
// Don't need to worry about at the moment
if (expression[iterator] == '^')
{
// go to derivative later
}
else
{
if (count % 2 != 0)
{
// we'll do different derivatives here.... for now just add, subtract, multiply, divide
totalVal = new ExprNode(expression[iterator], tNum, tNum2);
}
else if (count % 2 == 0 && expression[iterator] == '+' || expression[iterator] == '*')
{
totalVal = new ExprNode(expression[iterator], tNum, totalVal);
}
else if (count % 2 == 0 && expression[iterator] == '-' || expression[iterator] == '/')
{
totalVal = new ExprNode(expression[iterator], totalVal, tNum);
}
}
count++;
}
if (isNumber(expression[iterator]) && count % 2 != 0)
{
tempNum += expression[iterator];
}
else if (isNumber(expression[iterator]) && count % 2 == 0)
{
tempNum2 += expression[iterator];
}
if (expression[iterator] == ' ' && count % 2 != 0)
{
tempNumInt = atoi (tempNum.c_str());
tNum = new ExprNode(tempNumInt);
tempNum = "";
count++;
}
else if (expression[iterator] == ' ' && count % 2 == 0)
{
tempNum2Int = atoi (tempNum2.c_str());
tNum2 = new ExprNode(tempNum2Int);
tempNum2 = "";
count++;
}
else if (expression[iterator] == ' ')
{
count++;
}
}
cout << totalVal->eval() << endl;
}
I'll try to explain anything that is unclear. Thanks in advance.
I'm not pointing out the exact mistake, but giving you an advice: int ExprNode::eval() const should not return 'int'. That's not enough to handle the variable results, like "11x" (this cannot be represented with a simple int). You'll have to create your own structure that stores the integer part and the variable part of the result (with this last one being optional).
How to find whether a string is guid in native c++? a code sample would help greatly
If you need to do it by hand (information from wikipedia):
Check the length (36, including hyphens)
Check that the hyphens are at the expected positions (9-14-19-24)
Check that all other characters are hexadecimal (isxdigit)
You could use a regex to see if it complies with GUID format.
Try the following code - could help.
_bstr_t sGuid( _T("guid to validate") );
GUID guid;
if( SUCCEEDED( ::CLSIDFromString( sGuid, &guid ) )
{
// Guid string is valid
}
Here's a faster, native C++ version without regular expressions or scanf()-like calls.
#include <cctype>
#include <string>
using namespace std;
bool isCanonicalUUID(const string &s) {
// Does it match the format 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'?
if (s.length() != 36) return false;
if (s[8] != '-' || s[13] != '-' ||
s[18] != '-' || s[23] != '-')
return false;
for (int i = 0; i < s.length(); i++) {
if (i == 8 || i == 13 || i == 18 || i == 23) continue;
if (isspace(s[i])) return false;
if (!isxdigit(s[i])) return true;
}
return true;
}
bool isMicrosoftUUID(const string &s) {
// Does it match the format '{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}'?
if (s.length() != 38) return false;
if (s[0] != '{' || s[37] != '}') return false;
if (s[10] != '-' || s[15] != '-' ||
s[20] != '-' || s[25] != '-')
return false;
for (int i = 1; i < s.length()-1; i++) {
if (i == 10 || i == 15 || i == 20 || i == 25) continue;
if (isspace(s[i])) return false;
if (!isxdigit(s[i])) return true;
}
return true;
}
bool isUUID(const string &s) {
return isCannonicalUUID(s) || isMicrosoftUUID(s);
}
This method leverages the scanf parser and works also in plain C:
#include <stdio.h>
#include <string.h>
int validateUUID(const char *candidate)
{
int tmp;
const char *s = candidate;
while (*s)
if (isspace(*s++))
return 0;
return s - candidate == 36
&& sscanf(candidate, "%4x%4x-%4x-%4x-%4x-%4x%4x%4x%c",
&tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp) == 8;
}
Test with e.g.:
int main(int argc, char *argv[])
{
if (argc > 1)
puts(validateUUID(argv[1]) ? "OK" : "Invalid");
}
Here's a code example in case you still need one :P
#include <ctype.h>
using namespace std;
bool isUUID(string uuid)
{
/*
* Check if the provided uuid is valid.
* 1. The length of uuids should always be 36.
* 2. Hyphens are expected at positions {9, 14, 19, 24}.
* 3. The rest characters should be simple xdigits.
*/
int hyphens[4] = {9, 14, 19, 24};
if (uuid.length() != 36)
{
return false;//Oops. The lenth doesn't match.
}
for (int i = 0, counter = 0; i < 36; i ++)
{
char var = uuid[i];
if (i == hyphens[counter] - 1)// Check if a hyphen is expected here.
{
// Yep. We need a hyphen here.
if (var != '-')
{
return false;// Oops. The character is not a hyphen.
}
else
{
counter++;// Move on to the next expected hyphen position.
}
}
else
{
// Nope. The character here should be a simple xdigit
if (isxdigit(var) == false)
{
return false;// Oops. The current character is not a hyphen.
}
}
}
return true;// Seen'em all!
}
I am looking for a C++ class I can incorporate into a project I am working on.
the functionality I need is evaluation of string operations to numerical form: for example "2 + 3*7" should evaluate to 23.
I do realize what I am asking is a kind of an interpreter, and that there are tools to build them, by my background in CS is very poor so I would appreciate if you can point me to a ready made class .
This should do exactly what you want. You can test it live at: http://www.wowpanda.net/calc
It uses Reverse Polish Notation and supports:
Operator precedence (5 + 5 * 5 = 30 not 50)
Parens ((5 + 5) * 5 = 50)
The following operators: +, -, *, /
EDIT: you'll probably want to remove the Abs() at the bottom; for my needs 0 - 5 should be 5 and not -5!
static bool Rpn(const string expression, vector<string> &output)
{
output.clear();
char *end;
vector<string> operator_stack;
bool expecting_operator = false;
for (const char *ptr = expression.c_str(); *ptr; ++ptr) {
if (IsSpace(*ptr))
continue;
/* Is it a number? */
if (!expecting_operator) {
double number = strtod(ptr, &end);
if (end != ptr) {
/* Okay, it's a number */
output.push_back(boost::lexical_cast<string>(number));
ptr = end - 1;
expecting_operator = true;
continue;
}
}
if (*ptr == '(') {
operator_stack.push_back("(");
expecting_operator = false;
continue;
}
if (*ptr == ')') {
while (operator_stack.size() && operator_stack.back() != "(") {
output.push_back(operator_stack.back());
operator_stack.pop_back();
}
if (!operator_stack.size())
return false; /* Mismatched parenthesis */
expecting_operator = true;
operator_stack.pop_back(); /* Pop '(' */
continue;
}
if (*ptr == '+' || *ptr == '-') {
while (operator_stack.size() && IsMathOperator(operator_stack.back())) {
output.push_back(operator_stack.back());
operator_stack.pop_back();
}
operator_stack.push_back(boost::lexical_cast<string>(*ptr));
expecting_operator = false;
continue;
}
if (*ptr == '*' || *ptr == '/') {
while (operator_stack.size() && (operator_stack.back() == "*" || operator_stack.back() == "/")) {
output.push_back(operator_stack.back());
operator_stack.pop_back();
}
operator_stack.push_back(boost::lexical_cast<string>(*ptr));
expecting_operator = false;
continue;
}
/* Error */
return false;
}
while (operator_stack.size()) {
if (!IsMathOperator(operator_stack.back()))
return false;
output.push_back(operator_stack.back());
operator_stack.pop_back();
}
return true;
} // Rpn
/***************************************************************************************/
bool Calc(const string expression, double &output)
{
vector<string> rpn;
if (!Rpn(expression, rpn))
return false;
vector<double> tmp;
for (size_t i = 0; i < rpn.size(); ++i) {
if (IsMathOperator(rpn[i])) {
if (tmp.size() < 2)
return false;
double two = tmp.back();
tmp.pop_back();
double one = tmp.back();
tmp.pop_back();
double result;
switch (rpn[i][0]) {
case '*':
result = one * two;
break;
case '/':
result = one / two;
break;
case '+':
result = one + two;
break;
case '-':
result = one - two;
break;
default:
return false;
}
tmp.push_back(result);
continue;
}
tmp.push_back(atof(rpn[i].c_str()));
continue;
}
if (tmp.size() != 1)
return false;
output = Abs(tmp.back());
return true;
} // Calc
/***************************************************************************************/
boost::spirit comes with a calculator example which would do what you need:
http://www.boost.org/doc/libs/1_33_1/libs/spirit/example/fundamental/ast_calc.cpp
muParser is written in C++ and does just what you need.
C++ in Action, in addition to being a great book on C++, includes a fully working calculator, doing what you need (and actually much more). And the book is available for free online