Convert string to logical operators

closed account (yqi6RXSz)
I need to convert string "or; and; not" to a logical operators.
these are the given bools: a=0; b=1; c=1; d=1; e=0;
I read this line from the file: a and not b or e

This is how it works, if it's typed in by hand:
bool IsTrue(a and not b or e);
cout << IsTrue << endl; // Displays 0

I have no clue how to do it with a string.
Last edited on
I don't understand what you have to do and what you're troubled with. Do you have a link or a text that explains the task you're having issues with?
closed account (E0p9LyTq)
The "how" depends on what exactly your string is. C-style char array or C++ STL.

There are functions to locate a substring within a larger string, either type of string.
First, you need to know the operator precedence for the logical operators.

The precedence in C++ for (or, and, not) is as follows:
! > && > ||
i.e NOT > AND > OR
where, NOT has highest precedence and OR has the least precedence.

Second, you need to look for patterns. By your example it seems that every operator/operand is separated by a single whitespace. This can be useful. Also we know that the expression is always valid, if not we have to handle invalid expressions.

Third, you need to analyze what you're allowed to use. This problem can be solved in many ways, i.e with stringstreams, using strings and its methods or c-style strings and manually iterating over them.

Keep note of the values of a,b,c,d and e.

Now to come up with a coding approach, we try to solve the problem in our mind using logic and hand.
Consider the example: a AND NOT b OR e

One way we can solve is by using the operator precedence since we assumed that the expression is always valid.

First lets convert a,b,c,d and e to 0 or 1. So we search the string, if we find a,b,c,d or e we change it to either 1 or 0 depending on the value. Remember we're changing the character of the string.

Now we have:
0 AND NOT 1 OR 0

Now we find the operator with the highest precedence, i.e NOT.
We find it to be the third word.

So we change the value of the 4th word, which is guaranteed to be an operand because of our assumption. Go to 4th word -> change 1 to 0

We now have

0 AND NOT 0 OR 0
But wait, we just used the NOT, so we pop NOT outside.

we get,

0 AND 0 OR 0

Now we check AND which is the next operator according to the precedence chart.

And is found to be in the 2nd word. So we take the value on 1st word and 3rd word and compare them. If both are 1, then replace the three words with 1 otherwise 0

So expression becomes

0 or 0

Lastly do the same for or and you get

0 as your output.


Try solving it by yourself and if you're not able to then you can show us what you've done and we'll help you correct it! ;)
what is intended? the English expression could be
a & !(b|e)
or (haha..)
a & !b | e

you may want some sort of stack type approach? assuming the bottom version of the expression:
operand: evaluate everything.
operator: push onto stack. //I am not sure if this is right for all expressions, you may need to research it or check it out. Its an example of what you are looking for, though.
a, evaluate: result = 0.
and, push to stack.
not, push to stack.
b, evaluate: (pop not)
not b is 0
0 and 0 is 0 (pop 'and' and evaluate)
everything is evaluated, next?
or, push
e, evaluate, 0 or 0 is 0.
everything is evaluated, stack is empty, input is empty, done.

Last edited on
closed account (yqi6RXSz)
All of this looks great, but how would it work if im given this:

a = 0; b = 1; c =1; d = 0; e = 0;
a or b or c or d or e

It should put out 1, but I'm always left with a 0. Maybe I'm not doing it correctly with the OR?
a or b or c or d or e,

= 0 or 1 or 1 or 0 or 0
= ((((0 or 1) or 1) or 0) or 0)
= (((1 or 1) or 0) or 0)
= ((1 or 0) or 0)
= 1 or 0
= 1

How did you get 0? or would give 1 if either one of the two operands are 1.
We have no idea what is going wrong, because we can't see any code.

a = 0; b = 1; c =1; d = 0; e = 0;
a or b or c or d or e
1
2
3
4
5
6
7
8
9
10
11
12
13
// Example program
#include <iostream>

int main()
{
    bool a, b, c, d, e;
    
    // your post (almost verbatim)
    a = 0; b = 1; c =1; d = 0; e = 0;
    bool result = a or b or c or d or e;
    
    std::cout << result << std::endl;
}


Edit: Apologies, I ignored the fact that you were still talking about strings.
Last edited on
closed account (yqi6RXSz)
You explained everythhing very well, I just dont know how to make an algorithm that gets the result from any logical sentence. (the logical sentence can't be more than 100 spaces)I dont really know how to use stack yet, I tried doing it with an array, but I can't really just pop out something out of an array, so that doesn't work. (The sentence is read from a file, not put in manually into a cout, which makes it harder)
Last edited on
Okay then let's go little steps by little steps.

First try to write something that can handle only:
a or b or c or d or e

And then let's worry about putting things together.

Let
a = 0; b = 1; c =1; d = 0; e = 0;
like you had said earlier.
We have to store these values, you could use a map, two arrays, or a structure and probably more ways.

Since you want to use arrays lets use a structure.

Define a structure say 'values', with two members.
first member: char data type which holds key value. i,e the character a,b,c,d or e
second member: bool or int (either can be used) data type which holds the value.

Now make an array of this structure with the size of how many ever letters there are. 5 letters in our case. And enter the two structure member values for all elements. You should have an array of 5 'values' structure that have filled data members.

Now for parsing.

We have
a or b or c or d or e
.
By using stringstream, string::find, manual for-loops etc. you can separate the expression into words.
Let's store the words into an array like you intended to.

So we now have an array of strings with 9 elements.

Each element is either a letter a, b, c, d, e or an operation.
But a, b, c, d and e are not useful to use. What is useful is their values.

Write a loop that will iterate over each of the array with 9 elements such that,
under each element, if the element is not an operator, there will be another for-loop to compare it with all the elements of the first data members of the array of structures we had made.

If a match is found, then change the element of the 9 elements where a match was found into 0 or 1 according to the 2nd data member.

Now you have

0 or 1 or 1 or 0 or 0

Write another loop to search for operators.

Once you've found an 'or', evaluate the element before it and after it, and pop the two evaluated elements. Replace the operator with what the elements evaluated to, i.e either 1 or 0.

You can use vector::erase to pop elements. Try to write code until here. You know the logic so if you're able to write until here then you might be able to complete it.

Well, depending on how "correct" you're trying to be, you need to implement your own subset of your language/parser.


If your file is
a=0; b=1; c=1; d=1; e=0;


Then one possible solution is to do something like this.
This solution does absolutely no error checking, and doesn't use the names of the symbols themselves, but may serve as a starting point.
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
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>

int main()
{
    // I am using an std::istringstream with the contents of the file,
    // because it's easier to communicate over the internet with it.
    std::istringstream f("a=0; b=1; c=1; d=1; e=0;");
    // Use an std::ifstream here as an alternative:
    ////std::ifstream f("myfile.txt");
    
    std::vector<int> booleans;
    
    // get each substring based on ; delimiter
    std::string assignment;
    while (getline(f, assignment, ';'))
    {
        // (don't change this part to ifstream, keep it as istringstream)
        std::istringstream assignment_ss(assignment);
        
        std::string variable_name; // TODO: trim whitespace (if necessary)
        getline(assignment_ss, variable_name, '=');
        
        int n;
        assignment_ss >> n;
        
        std::cout << "variable_name  = " << variable_name << "\n"
                  << "variable_value = " << n << "\n\n";
                  
        booleans.push_back(n);
    }
    
    // vector ORing
    bool or_result = false;
    for (size_t i = 0; i < booleans.size(); i++)
    {
        or_result = or_result || booleans[i];
    }
    
    std::cout << "result of ORing all symbols: " << or_result << std::endl;
}
you can use vector for a cheap stack tool for this to get started, via its push back and pop back methods. arrays do work, you just have a max size and a current index, pushing increments it, popping decrements it, current is where you currently are at... you don't need a full blown stack class right now (but you should at some point figure out how to do one).

a quick & dirty 'stack' in a C array
int stack[1000];
int stackindex = 0;
...
pushing in:
stack[strackindex++] = newvalue; //write into 0, then move index to 1
popping out:
value = stack[--stackindex]; //move index (at 1 now) to zero, then read it out, updated index back to zero.

reading from a file or reading from cin should be equally difficult. You have like 2 extra lines to use a file ... an open and a close statement, and the open can be stuck to the variable creation. Don't let it being a file freak you out, its still just a stream of characters coming into your program from an external source -- landing in the same kinds of places, doing the same kinds of things...
Last edited on
Topic archived. No new replies allowed.