C++ parenthesis matching application - c++

I have to write a function that accepts a string and returns a bool. The string passed in is a series or different parenthesis opened or closed ex.({[]}) and returns whether the 'parens' are well-balanced. This has to be implemented by adding items to a stack. I am getting the following error:
parenMatching_demo.cpp:18:12: error: no match for 'operator==' in 'c
== '('
The psudocode is:
matcher(expression)
for each character in expression
if the character is an opener
push on stack
else if the character is a closr
if stack is empty return false
if the (opener at) the top of the stack does not match the closer
return false
pop the stack
if the stack is not empty return false
return true
This is what I have.
template <typename T>
bool parenMatching(string c) {
stack<string> s;
for (int i = 0; i < s.size(); i++) {
if (c == '(' || c == '[' || c == '{' || c == '<')
s.push(c);
else if (c == ')' || c == ']' || c == '}' || c == '>') {
if (s.empty()) return false;
if (s.top() != '(' || s.top() != '[' || s.top() != '{' || s.top() != '<')
return false;
s.pop();
}
}
}

One problem is the type of the stack, it should be
stack<char> s;
Then the for loop, the condition should be
i < c.size()
The next problem is
if (c == '(' || c == '[' || c == '{' || c == '<')
does not compare the character of the string c at i, so you need
const char c2 = c[i];
if (c2 == '(' || c2 == '[' || c2 == '{' || c2 == '<')
If you need help to fix the rest, let me/us know :)

You're comparing a string with a char in your codes that check for the parentheses. You're missing a line where you get the current character you're looking at as you iterate your string - you probably want something like:
char current = c.at(i);
Additionally, you need to fix your stack type as Daniel Frey says in his answer.
edit - he's since changed his to contain this info, so that answer should have everything you need.

Related

Valid Parentheses Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid

I am getting Runtime error for this test case "(){}}{"
AddressSanitizer:DEADLYSIGNAL
=================================================================
==30==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x00000034481b bp 0x7ffd39b417d0 sp 0x7ffd39b41680 T0)
==30==The signal is caused by a READ memory access.
==30==Hint: this fault was caused by a dereference of a high value address (see register values below). Dissassemble the provided pc to learn which register was used.
#3 0x7f977b2d60b2 (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
AddressSanitizer can not provide additional info.
==30==ABORTING
class Solution {
public:
bool isValid(string s) {
stack<char>st;
if(s.size()==1){
return false;
}
for(int i =0; i<s.size(); i++){
if(st.empty() && s[i]=='(' || s[i]=='[' || s[i]=='{'){
st.push(s[i]);
}
else if(!st.empty() && s[i]=='(' || s[i]=='[' || s[i]=='{'){
st.push(s[i]);
}
else if(!st.empty() && s[i]==')' ||s[i]==']' || s[i]=='}'){
if(s[i] == ')' && st.top()=='(' ){
st.pop();
}
else if(s[i]=='}' && st.top()=='{'){
st.pop();
}
else if(s[i]==']' && st.top()=='['){
st.pop();
}
else{
return false;
}
}
else{
if(st.empty() && s[i]==')'||s[i]==']' || s[i]=='}'){
return false;
}
}
}
if(!st.empty()){
return false;
}
else{
return true;
}
}
};
This condition is wrong:
else if (!st.empty() && s[i] == ')' || s[i] == ']' || s[i] == '}') {
It checks s[i] == ']' || s[i] == '}' even if st is empty. If the condition then becomes true, it will access st.top() and it may st.pop() in the following block statement. Both leads to undefined behavior.
Suggested change:
else if (!st.empty() && (s[i] == ')' || s[i] == ']' || s[i] == '}')) {
// ^ ^
This makes sure that !st.empty() must be true for the whole condition to be true.
The same goes for all your checks where you have && and followed by one or more || conditions.
All the ifs you need to change are listed as warnings in this
demo in which I've also added a debug printout which clearly shows that st is in fact empty when you use st.top().

I'm trying to create a bool function that evaluates a char and returns true if char is '(' ')' '*' '-' '+' [duplicate]

This question already has answers here:
C++ "OR" operator
(9 answers)
Closed 3 years ago.
I'm getting a warning code C682 and im newer to programming so I'm not sure exactly what is wrong.
bool isOperator(char ch)
{
if (ch == '(' or ')' or '*' or '-' or '+')
{
return true;
}
else
return false;
}
I want it to return true if the char is one of those and false if it's something else.
or is a logical operator in C++ so you need to put conditional operators:
return ch == '(' or ch == ')' or ch == '*' or ch == '-' or ch == '+');
otherwise you evaluate 'c' and others as an expression which is always true.
Some may see this more readabale (it is less repeatative):
bool isOperator(char ch)
{
switch( ch ) {
case '(' :
case ')' :
case '*' :
case '-' :
case '+' :
return true;
}
return false;
}
or more C++ way (though it is more expensive but in your case of 5 variants unlikely to matter):
bool isOperator(char ch)
{
const std::string_view ops( "()*-+" );
return ops.find( ch ) != std::string_view::npos;
}
Alternatively, you could implement it as a search into an array. This way you can add and remove operators easily.
#include <algorithm>
#include <iterator>
bool isOperator(char op) {
const char operators[] = {'(', ')', '+', '-', '*'};
return std::find(std::begin(operators), std::end(operators), op) != std::end(operators);
}
The right way to write it would be
if (ch == '(' or ch == ')' or ch == '*' or ch == '+')
In addition to the other answers here, you could use std::any_of:
bool isOperator(char ch)
{
static const std::array arr { '(', ')', '*', '-', '+' };
return std::any_of(arr.begin(), arr.end(), [ch](char const& c) {
return ch == c;
});
}
Lets go over a few things:
Replace or with the actual operator || in c++ which is equivalent to or. (Note that or is a ISO646 standard and can be used, but depends on preference)
Next we need to ensure ch is added for every character you are checking
After that we should have in a more simple form:
return (ch == '(') || (ch== ')') || (ch == '*') || (ch == '-') || (ch == '+');
Note: We can also do it the way you have by if/else
bool is_operator_match = false;
if (ch == '(') || (ch== ')') || (ch == '*') || (ch == '-') || (ch == '+')
{
is_operator_match = true;
}
return is_operator_match;

Parsing Parenthesis using stack template class in C++

I have a homework and its just bugging for the last 2 days, I've been doing exactly what the pseudo code and still haven't got it right yet.
For example, if I put in "mike]" or "mike]123", my program will crash, due to the stack is empty...From what I observe, the program will crash when:
- The stack is empty
- And there is a close parenthesis
PS: with the help of us2012, I can fix the crash problem. However, the result is not right.
Instead of printing out "invalid", it outputs "valid"
:(
Here is the pseudo code from my professor:
def parse_parenthesis(str):
stack = create a new empty stack of OpenParen objects
for i from 0 to str.size() - 1:
if str[i] is an open parenthesis
stack.push(new OpenParen(str[i]))
else if str[i] is not a close parenthesis:
# str[i] is not a parenthesis of any kind, so ignore it
continue
# otherwise str[i] must be a close parenthesis, try to
# match it with the most recent open paren, on the top
# of the stack
else if stack is empty
return false;
else if stack.peek() is of the same type as str[i]:
# close properly
stack.pop()
else
return false;
if stack is not empty
return false;
else
return true
and here is what I have so far:
.cpp file
bool ParenMatching(const string& s, unique_ptr<string>& output)
{
unique_ptr<OpenParen> stack(new OpenParen);
bool validOpen, validClose, valid;
bool match; //haveCloseParen;
/*string unMatch = "Unmatch";
string unExpected = "Unexpected close paren";
string noError = "No Error";*/
for (size_t i = 0; i < s.length(); i++)
{
// check if its open parenthesis
validOpen = stack->IsOpenParen(s[i]);
// check if its close parenthesis
validClose = stack->IsCloseParen(s[i]);
// if there is open paren, push into the stack
if(validOpen)
stack->PushObj(s[i]);
else if(!validClose)
{
continue;
}
else if(stack->GetObj().IsEmpty())
valid = false;
else if(match = IsMatchParen(s[i], stack))
stack->PopObj();
else
valid = false;
}
if(!stack->GetObj().IsEmpty())
valid = false;
else
valid = true;
return valid;
}
bool IsMatchParen(const char c, const unique_ptr<OpenParen>& stack)
{
bool valid;
if(c == ')' && stack->PeekObj() == '(')
valid = true;
else if (c == ']' && stack->PeekObj() == '[')
valid = true;
else if (c == '}' && stack->PeekObj() == '{')
valid = true;
else if (c == '>' && stack->PeekObj() == '<')
valid = true;
else
valid = false;
return valid;
}
OpenParen.cpp
// Check if its open paren
bool OpenParen::IsOpenParen(const char c)
{
bool isOpen;
if(c == '(' || c == '[' || c == '{' || c == '<')
isOpen = true;
else
isOpen = false;
return isOpen;
}
// check if its close paren
bool OpenParen::IsCloseParen(const char c)
{
bool isClose;
if(c == ')' || c == ']' || c == '}' || c == '>')
isClose = true;
else
isClose = false;
return isClose;
}
gcc 4.7.3: g++ -Wall -Wextra -std=c++0x parens.cpp
#include <iostream>
#include <stack>
#include <string>
#include <vector>
bool isOpen(char c) {
return c == '(' || c == '[' || c == '{' || c == '<'; }
bool isClose(char c) {
return c == ')' || c == ']' || c == '}' || c == '>'; }
bool isMatch(char c1, char c2) {
return (c1 == '(' && c2 == ')')
|| (c1 == '[' && c2 == ']')
|| (c1 == '{' && c2 == '}')
|| (c1 == '<' && c2 == '>'); }
bool parse(const std::string& s) {
std::stack<std::string::value_type> stk;
for (std::string::size_type i = 0; i < s.size(); ++i) {
if (isOpen(s[i])) { stk.push(s[i]); }
else if (isClose(s[i])) {
if (!stk.empty() && isMatch(stk.top(), s[i])) { stk.pop(); }
else { return false; } } }
return stk.empty(); }
int main() {
std::vector<std::string> ptests = {
"", "()", "()()", "(())", "a(a)a" };
std::vector<std::string> ftests = {
"(", ")", ")(", ")()(", "))((" };
for (const auto& t : ptests) {
if (!parse(t)) { std::cout << "fail: " << t << std::endl; } }
for (const auto& t : ftests) {
if (parse(t)) { std::cout << "fail: " << t << std::endl; } }
}
One important thing you should keep in mind about C++ : Multiple else ifs do not live at the same level. That's because else if is not a single entity, it's an else that belongs to the preceding statement and an ifthat begins a new statement, so
if (cond1)
a();
else if (cond 2)
b();
else if (cond 3)
c();
else
d();
is actually
if (cond1)
a();
else {
if (cond 2)
b();
else {
if (cond 3)
c();
else
d();
}
}
Therefore, your check whether the stack is empty needs to be before the check whether the current close parens matches the top of the stack. Otherwise, your program will try to examine the top of the stack when it's empty, and that results in a crash.
Also, setting valid = false is not the right thing to do when you find a condition that indicates a non-match. The loop will still continue and can reset valid to true in a later iteration. You need to immediately return false, as you can already see in your pseudocode.

Find the first printf format sequence in a C++ string

I search the most concise and efficient way to find the first printf format sequence (conversion specification) in a C++ string (I cannot use std::regex as they are not yet implement in most in compilers).
So the problem is to write an optimized function that will return the beginning of the first printf-format sequence pos and its length n from an input string str:
inline void detect(const std::string& str, int& pos, int& n);
For example, for:
%d -> pos = 0 and n = 2
the answer is: %05d -> pos = 15 and n = 4
the answer is: %% %4.2f haha -> pos = 18 and n = 5
How to do that (clever and tricky ways are welcome)?
Scan forward for %, then parse the content from there. There are some quirky ones, but not THAT bad (not sure you want to make it an inline tho').
General principle (I'm just typing as I go along, so probably not the BEST form of code ever written - and I haven't tried to compile it at all).
inline void detect(const std::string& str, int& pos, int& n)
{
std::string::size_type last_pos = 0;
for(;;)
{
last_pos = str.find('%', last_pos)
if (last_pos == std::string::npos)
break; // Not found anythin.
if (last_pos == str.length()-1)
break; // Found stray '%' at the end of the string.
char ch = str[last_pos+1];
if (ch == '%') // double percent -> escaped %. Go on for next.
{
last_pos += 2;
continue;
}
pos = last_pos;
do
{
if (isdigit(ch)) || ch == '.' || ch == '-' || ch == '*' ||
ch == '+' || ch == 'l' || ch == 'L' || ch == 'z' ||
ch == 'h' || ch == 't' || ch == 'j' || ch == ' ' ||
ch == '#' || ch == '\'')
{
last_pos++;
ch = str[last_pos+1];
}
else
{
// The below string may need appending to depending on version
// of printf.
if (string("AacdeEfFgGiopusxX").find(ch) != std::string::npos)
{
// Do something about invalid string?
}
n = last_pos - pos;
return;
}
} while (last_pos < str.length());
}
}
edit2: This bit is probably better written as:
if (isdigit(ch)) || ch == '.' || ch == '-' || ch == '*' ||
ch == '+' || ch == 'l' || ch == 'L' || ch == 'z' ||
ch == 'h' || ch == 't' || ch == 'j' || ch == ' ' ||
ch == '#' || ch == '\'') ...
if (string("0123456789.-*+lLzhtj #'").find(ch) != std::string::npos) ...
Now, that's your homework done. please report back with what grade you get.
Edit: It should be noted that some things that a regular printf will "reject" is accepted by the above code, e.g. "%.......5......6f", "%5.8d", "%-5-6d" or "%-----09---5555555555555555llllld". If you want the code to reject these sort of things, it's not a huge amount of extra work, just need a little bit of logic to check "have we seen this character before" in the "check for special characters or digit", and in most cases the special character should only be allowed once. And as the comment says, I may have missed a couple of valid format specifiers. It gets further trickier if you also need to cope with "this 'l' is not allowed with 'c'" or such rules. But if the input isn't "malicious" (e.g. you want to annotate where on which line there are format specifiers in a working C source file), the above should work reasonably well.

Evaluating a single char in an if statement: C++

I am having some troubles with my if loop.
First off I have I assigned char sign.
void evaluate_ps(istream& input)
{
char sign;
input >> sign;
cout << sign << endl;
check(sign);
}
That prints / so my sign has the value '/'
Then I go to my void check(char operation) function
void check(char operation)
{
if(operation != '-' || operation != '+' ||
operation != '*' || operation != '/')
{
return false;
}
else return true;
}
and it's returning false... WHY!!!! I can't seem to figure this out.
Thanks everyone.
This happens because you are using the || (OR) operator. When operation is / the check operation != '-' returns true. Since || is short circuited, the entire expression returns true.
Change it to && (AND):
if (operation != '-' && operation != '+' &&
operation != '*' && operation != '/')
Another way to write this is:
if (!(operation == '-' || operation == '+' ||
operation == '*' || operation == '/'))
You probably meant all your || to be &&:
if(operation != '-' && operation != '+' &&
operation != '*' && operation != '/')
Otherwise, it will always enter the if-statement since a character will always not equal one of 4 different things.
The if statement is responding to the / not equaling one of the other values
Think about "or" even in a general sense
if blue is not green or is not red or is not blue say nope
you would need to do something like the following:
if (operation != '+' && operation != '-' && operation != '/' && operation != '*') {
return false;
}
return true;
this way its like this
if blue is not green and is not red and is not blue say nope