I wrote this program and it supposed to test for the correct use of the three grouping symbols "(",")";"[","]"; and "{","}". It is using the array implementation of the stacks and supposed to evaluate if it is good string or a bad string. For example: (a+b), [(a-b)+c] would be good and )a+b( etc. would be bad string. When i run the program i get only one error. I thought i am missing a semi-colon or something, but after looking through the code several time,i can't find it. Maybe i got tunnel vision. Can you please see what the problem here is? This is the error: project1.cpp:41: error: expected initializer before 'while'.
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
const int DefaultListSize = 100;
typedef char Elem;
class Astack {
private:
int size;
int top;
Elem *listArray;
public:
Astack (int sz = DefaultListSize)
{size = sz; top= 0; listArray = new Elem[sz];}
~Astack() {delete [] listArray;}
void clear() {top=0;}
bool push(const Elem& item) {
if (top == size) return false;
else {listArray[top++] = item; return true;}}
bool pop(Elem& it) {
if (top==0) return false;
else {it = listArray[--top]; return true;}}
bool topValue(Elem& it) const {
if (top==0) return false;
else {it = listArray[top-1]; return true;}}
bool isEmpty() const {if (top==0) return true;
else return false;}
int length() const{return top;}
}; //end of class Astack
Astack s;
const string LEFTGROUP="([{";
const string RIGHTGROUP=")]}";
int main()
while (!EOF) {
while (!EOL) {
ch = getc();
if (ch == LEFTGROUP[0]) {
s.push(ch);
}
if (ch == LEFTGROUP[1] {
s.push(ch);
}
if (ch == LEFTGROUP[2] {
s.push(ch);
}
} //checking for openers
while (!EOL) {
ch = getc();
if (s.top() == LEFTGROUP[0]) {
if (ch == RIGHTGROUP[0]) {
s.pop();
}
}
if (s.top() == LEFTGROUP[1]) {
if (ch == RIGHTGROUP[1]) {
s.pop();
}
}
if (s.top() == LEFTGROUP[2]) {
if (ch == RIGHTGROUP[2]) {
s.pop();
}
}
if (!s.empty()) {
cout<<"Bad String."<<endl;
else {
cout<<"Good String."endl;
}
}
}
return 0;
You forgot a { at the beginning of int main(). You should also end with }
int main(){
//your while code
return 0;
}
Related
I have to write a program which balances a string with brackets.I wrote the program but it doesn't matter which string I enter because the program always says that the string is good.
Here's the code:
header file
#ifndef HEADER_H_
#define HEADER_H_
#include <string>
struct Element {
char data;
Element* link;
};
typedef Element* Stack;
void initStack(Stack& S);
void push(Stack& S, int a);
void pop(Stack &S);
int top(Stack& S);
bool isEmpty(Stack &S);
bool goodPair(char deschis, char inchis);
bool check(std::string s);
#endif
functions file
#include <iostream>
#include <string>
#include "header.h"
using namespace std;
void initStack(Stack& S)
{
S = nullptr;
}
void push(Stack& S, int a)
{
Element*nou = new Element;
nou->data = a;
nou->link = S;
S = nou;
}
void pop(Stack& S)
{
Stack aux = S;
S = S->link;
delete(aux);
}
int top(Stack& S)
{
if (isEmpty(S))
return int();
return S->data;
}
bool isEmpty(Stack &S)
{
if (S == 0)
return true;
else
return false;
}
bool goodPair(char deschis, char inchis)
{
if (deschis == '(' && inchis == ')')
return true;
else if (deschis == '[' && inchis == ']')
return true;
else if (deschis == '{' && inchis == '}')
return true;
else if (deschis == '<' && inchis == '>')
return true;
else
return false;
}
bool check(std::string s)
{
Element* S;
for (int i = 0; i < s.length(); i++)
{
if (s[i] == '(' || s[i] == '[' || s[i] == '{' || s[i] == '<')
push(S, s[i]);
else
{
if (s[i] == ')' || s[i] == ']' || s[i] == '}' || s[i] == '>')
if (isEmpty(S) || !goodPair(top(S), s[i]))
return false;
else
pop(S);
}
}
if (isEmpty(S))
return false;
else
return true;
}
main file
#include <iostream>
#include <string>
#include "header.h"
using namespace std;
int main()
{
Stack S;
initStack(S);
string s;
cout << "Write the string:";
cin >> s;
if (check(s))
cout << "Good";
else
cout << "Bad";
return 0;
}
I used a stack and I traversed each character.If the character is an opening bracket I put it in the stack.When the character is a closing bracket, I compare it with the top of the stack.If it's good I pop the top of the stack.
You create a pointer to Element (aliased as Stack) S in main() and initialize it with nullptr using initStack() and then you do not use this variable anymore. Instead you create a local S in function check() and use it uninialized, which leads to UB.
Looks like you get confused by naming as you call of them S (variable in main(), variable in check(), all reference parameters all called S). It is not illegal to do so, but looks like you confused yourself. (you even called std::string lowercase s to increase confusion)
Also you have logical error in your function:
if (isEmpty(S))
return false;
else
return true;
should be opposite, if stack is empty then string is balanced, not vice versa. So replace it with:
return isEmpty( S );
I need to check if number of letters "a" is equal to number of letters "b" using stack.
So i understand logic of this task, but my code doesn't work.
Logic:
If current letter == to letter in stack (s.pop()) or stack is empty then push into stack
else pop from stack
after end of cycle check size of stack. If it is empty so number of letters is equl, else not
I already have class stack
#include <string>
#include <iostream>
#include <cstdlib> // для system
using namespace std;
class stack {
public:
stack() {
ptr = 0;
}
~stack() {}
bool push(int val) {
if (ptr >= MAXSIZE) return false;
body[ptr++] = val; return true;
}
bool pop(int *val) {
if (ptr == 0) return false;
*val = body[--ptr]; return true;
}
bool empty() {
return ptr == 0;
}
private:
enum { MAXSIZE = 100 };
int body[MAXSIZE];
int ptr; // указатель на последний элемент
};
int main()
{
stack s;
std::string str;
std::cout << "Enter your ab string ";
getline(std::cin, str);
for (int c : str) {
if (c == s.pop(&c) || s.empty()) {
s.push(c);
}
else {
s.pop(&c);
}
}
if (s.empty()) {
cout << "YES\n";
system("pause");
return 0;
}
else {
cout << "NO\n";
system("pause");
}
}
result for abab, aabb, ab 'YES'
for aaabb, aba 'NO'
You need a method to look at current value on top of stack without popping it:
class stack {
...
int top() { // never use on an empty stack
return body[ptr-1];
}
...
};
That way you can write:
for (int c : str) {
// short circuit evaluation ensures that top is never called on an empty stack
if (s.empty() || (c == s.top()) {
s.push(c);
}
else {
s.pop(&c);
}
If you cannot, you must push back the popped value if it should not have been popped:
for (int c : str) {
int d;
if (! s.pop(&d)) { // s was empty
s.push(c);
}
else if (c == d) {
s.push(d); // should not have been popped
s.push(c);
}
}
You can push everytime you see a.
for (int c = 0; c < str.size() ; ++c) {
if (str[c] == 'a') s.push('a');
}
if ((s.size() * 2) == str.size()) cout << "YES\n"; else cout << "NO\n";
stack::size can be implemented this way:
int stack::size() {
return ptr;
}
I showed my codes and i have an error reading character of string. Everything is okey in my debugger until the NULL.
*Warning C4715 `String::equas`: not all control paths return a value*
I can not use it because I am using a NULL pointer for the parameter.
How can I solve this problem?
Thanks a lot and have a nice day!
Header:
class String
{
public:
String();
bool empty();
String(char * other_str);
bool equals(const String other_str);
private:
char* m_str;
};
My Codes:
#include "String.hpp"
#include <string>
#include<iostream>
int my_len(const char* p) {
int c = 0;
while (*p != '\0')
{
c++;
*p++;
}
return c;
}
String::String()
:m_str(NULL)
{
}
String::String(char * other_str)
{
}
bool String::empty()
{
return true;
}
bool String::equals(const String other_str)
{
if (m_str == NULL && other_str.m_str == NULL) {
return true;
}
if (m_str == NULL && other_str.m_str != NULL) {
return false;
}
if (m_str != NULL && other_str.m_str == NULL) {
return false;
}
if (m_str != NULL && other_str.m_str != NULL) {
int mystrlen = my_len(m_str);
int myrhslen = my_len(other_str.m_str);
if (mystrlen != myrhslen)
{
return false;
}
else
{
for (int i = 0; i < mystrlen; i++)
{
if (m_str[i] != other_str.m_str[i])
{
return false;
}
else {
return true;
}
}
}
}
}
i will add this codes:
int mylen(const char* p) {
int c = 0;
while (*p != '\0')
{
c++;
*p++;
}
return c;
}
void my_cpy(char dest, const char* src) {
int i = 0;
while (src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
}
char mytrdup(const char *s) {
char* d = (char*)malloc((my_len(s) + 1) * sizeof(char));
if (d == NULL) {
return NULL;
}
else{
my_cpy(d, s);
}
return d;
}
String empty_string2(NULL);
This will invokde the constructor version :
String::String(char* other_str) {}
which does nothing, leaving the m_str pointer dangling/uninitialized. You should change this constructor somehow, either by copying the string and setting the m_str pointer accordingly, or by setting m_str to the same address as the parameter. Either case it depends on what you want to achieve.
Besides, many other problems exist in your code. I notice already this one in you implemented function my_len. you should change *p++ into p++. I wonder how this passed the compilation btw, since the parameter is a const char*.
Finally, the compiler's warning is correct and very clear, although it is not the source of the problem you are facing for the time being.
EDIT: to make a duplicate copy of the string, you can write you constructor like this:
String::String(const char* other_str)
{ m_str = (other_str ? strdup(other_str) : other_str); }
And besides, preferably use null_ptr instead of NULL in your code. Since C++11, this is the standard for null pointers.
I add TEST_TRUE and then that work correctly.
I'm trying to write a simple program to convert infix notation to prefix and postfix. So far the postfix one works perfectly. However, I can't seem to get the prefix conversion right. I used the shunting yard algorithm for both. Apologies beforehand if my code is a bit unusual (i.e. writing my own stack class instead of using #include, unnecessarily using other things), I have to meet assignment requirements (this is a college assignment). Here's what I've tried so far:
#include<iostream>
#include<string.h>
using namespace std;
const int Max=255;
class Stack
{
private:
char element[Max];
int top;
public:
Stack()
{
top=-1;
}
bool isFull()
{
if(top>=(Max-1)) return true;
else return false;
}
bool isEmpty()
{
if(top==-1) return true;
else return false;
}
bool push(char x)
{
if(!isFull())
{
top++;
element[top]=x;
return true;
}
else
{
cout<<"Stack is full"<<endl;
return false;
}
}
bool pop(char &x)
{
if(!isEmpty())
{
x=element[top--];
return true;
}
else
{
//cout<<"Stack is empty"<<endl;
return false;
}
}
char retrieve()
{
if(!isEmpty())
{
return element[top];
}
else
{
//cout<<"Stack is empty"<<endl;
return ' ';
}
}
};
class Converter
{
private:
public:
Converter(){}
bool isOperator(char x)
{
if(x=='+'||x=='-'||x=='*'||x=='/'||x=='^'||x=='('||x==')') return true;
else return false;
}
bool isOperand(char x)
{
if(x>='0'&&x<='9') return true;
else return false;
}
int Hierarchy(char x)
{
if(x=='+'||x=='-') return 1;
else if(x=='*'||x=='/') return 2;
else if(x=='^') return 3;
else return 0;
}
char*ToPostfix(char infix[])
{
Stack stack1;
char res[20];
int resindex=0;
for(int i=0;i<strlen(infix);i++)
{
if(isOperator(infix[i]))
{
if(infix[i]=='(')
{
stack1.push(infix[i]);
}
else if(infix[i]==')')
{
while(stack1.retrieve()!='(')
{
stack1.pop(res[resindex++]);
}
stack1.pop(res[resindex]);
}
else
{
while(Hierarchy(infix[i])<=Hierarchy(stack1.retrieve()))
{
stack1.pop(res[resindex++]);
}
stack1.push(infix[i]);
}
}
else if(isOperand(infix[i]))
{
res[resindex++]=infix[i];
}
}
while(!stack1.isEmpty())
{
stack1.pop(res[resindex++]);
}
res[resindex]='\0';
return res;
}
char*ToPrefix(char infix[])
{
char res[20];
strcpy(res,strrev(infix));
for(int i=0;i<strlen(res);i++)
{
if(res[i]=='(')
{
res[i]=')';
}
else if(res[i]==')')
{
res[i]='(';
}
}
strcpy(res,ToPostfix(res));
strcpy(res,strrev(res));
return res;
}
};
int main()
{
Converter convert;
char infix[20];
cout<<"Enter infix expression: ";
cin>>infix;
cout<<endl<<"Prefix: "<<convert.ToPrefix(infix)<<endl;
cout<<"Postfix: "<<convert.ToPostfix(infix)<<endl;
return 0;
}
when I try to convert a simple infix notation, i.e. 1*(2+3)/4^5-6, the postfix conversion is right (123+*45^/6-) but the prefix conversion returns the wrong answer (-*1/+23^456) instead of -/*1+23^456. can anyone help?
Actually, both answers are correct because you can switch the order of the division and the multiplication if multiplication comes first in infix. So your wrong answer is correct in this case. However, there is a left to right precedence, so your hierarchy handling is not correct: change else if(x=='*'||x=='/') return 2;.
I can't use boost::spirit in my environment. But I would like to use STL and boost as much as possible to build my own expression evaluator. Is there such an alternative to boost::spirit?
The following code includes unit tests and a complete parser I wrote in an about 90 minute session at ACCU 200x (8 or 9). If you need more, it might be easy enough to extend. You can make it do doubles by defining Parse::value_type, or extracting it into a separate header file and make it a template class.
Or you can take the test cases and try yourself. (it uses CUTE from http://cute-test.com)
#include "cute.h"
#include "ide_listener.h"
#include "cute_runner.h"
#include <cctype>
#include <map>
namespace {
class Parser {
typedef int value_type;
typedef std::vector<value_type> valuestack;
typedef std::vector<char> opstack;
typedef std::map<std::string,value_type> memory;
public:
memory variables;
private:
void evaluateSingleOperator(char op,value_type &result,value_type operand) {
switch(op) {
case '+': result += operand; break;
case '-': result -= operand; break;
case '*': result *= operand; break;
case '/': result /= operand; break;
default: throw("invalid operand");
}
}
void evaluateStacks(valuestack &values, opstack &ops) {
while(ops.size() && values.size()>1) {
char op = ops.back(); ops.pop_back();
value_type operand = values.back(); values.pop_back();
evaluateSingleOperator(op,values.back(),operand);
}
}
bool higherPrecedenceOrLeftAssociative(char last, char current) {
return (last == current)||(last == '*' || last == '/') ;
}
bool shouldEvaluate(char op,opstack const &ops) {
return ops.size() > 0 && higherPrecedenceOrLeftAssociative(ops.back(),op);
}
std::string parseVariableName(std::istream &is) {
std::string variable;
char nextchar=0;
while ((is >> nextchar) && isalpha(nextchar)) {
variable += nextchar;
}
if (variable.size() == 0) throw std::string("internal parse error");
is.unget();
return variable;
}
int peekWithSkipWhiteSpace(std::istream &is) {
int nextchar = EOF;
while(isspace(nextchar = is.peek())) is.get();
return nextchar;
}
value_type getOperand(std::istream &is) {
int nextchar = peekWithSkipWhiteSpace(is);
if (nextchar == EOF) throw std::string("syntax error operand expected");
if (isdigit(nextchar)){
value_type operand=0;
if (!(is >> operand)) throw std::string("syntax error getting number") ;
return operand;
} else if ('(' == nextchar) {
is.get();
return parse(is);
} else if (isalpha(nextchar)) {
std::string variable= parseVariableName(is);
if( parseAssignmentOperator(is)) {
variables[variable] = parse(is);
} else {
if (!variables.count(variable)) throw std::string("undefined variable: ")+variable;
}
return variables[variable];
}
throw std::string("syntax error");
}
bool parseAssignmentOperator(std::istream &is) {
int nextchar = peekWithSkipWhiteSpace(is);
if ('=' != nextchar) {
return false;
}
is.get();
return true;
}
public:
value_type parse(std::istream &is) {
is >> std::skipws;
valuestack values;
opstack ops;
values.push_back(getOperand(is));
char op=')';
while((is >>op) && op != ')') {
if (shouldEvaluate(op, ops)) {
evaluateStacks(values, ops);
}
values.push_back(getOperand(is));
ops.push_back(op);
}
evaluateStacks(values,ops);
return values.back();
}
value_type eval(std::string s) {
std::istringstream is(s);
return parse(is);
}
};
int eval(std::string s) {
return Parser().eval(s);
}
void shouldThrowEmptyExpression() {
eval("");
}
void shouldThrowSyntaxError() {
eval("()");
}
void testSimpleNumber() {
ASSERT_EQUAL(5,eval("5"));
}
void testSimpleAdd() {
ASSERT_EQUAL(10,eval("5 +5"));
}
void testMultiAdd() {
ASSERT_EQUAL(10,eval("1 + 2 + 3+4"));
}
void testSimpleSubtract() {
ASSERT_EQUAL(5,eval("6-1"));
}
void testTenPlus12Minus100() {
ASSERT_EQUAL(-78,eval("10+12-100"));
}
void testMultiply() {
ASSERT_EQUAL(50,eval("10*5"));
}
void testDivision() {
ASSERT_EQUAL(7,eval("21/3"));
}
void testAddThenMultiply() {
ASSERT_EQUAL(21,eval("1+4 *5"));
}
void testAddThenMultiplyAdd() {
ASSERT_EQUAL(16,eval("1+4*5 -5"));
}
void testAddSubSub() {
ASSERT_EQUAL(-4,eval("1+2-3-4"));
}
void testSimpleParenthesis() {
ASSERT_EQUAL(1,eval("(1)"));
}
void testSimpleOperandParenthesis() {
ASSERT_EQUAL(2,eval("1+(1)"));
}
void testParenthesis() {
ASSERT_EQUAL(5,eval("2*(1+4)-5"));
}
void testNestedParenthesis() {
ASSERT_EQUAL(16,eval("2*(1+(4*3)-5)"));
}
void testDeeplyNestedParenthesis() {
ASSERT_EQUAL(8,eval("((2*((1+(4*3)-5)))/2)"));
}
void testSimpleAssignment() {
Parser p;
ASSERT_EQUAL(1, p.eval("a=1*(2-1)"));
ASSERT_EQUAL(8, p.eval("a+7"));
ASSERT_EQUAL(1, p.eval("2-a"));
}
void testLongerVariables() {
Parser p;
ASSERT_EQUAL(1, p.eval("aLongVariableName=1*(2-1)"));
ASSERT_EQUAL(42, p.eval("AnotherVariable=7*(4+2)"));
ASSERT_EQUAL(1, p.eval("2-(aLongVariableName*AnotherVariable)/42"));
}
void shouldThrowUndefined() {
eval("2 * undefinedVariable");
}
void runSuite(){
cute::suite s;
//TODO add your test here
s.push_back(CUTE_EXPECT(CUTE(shouldThrowEmptyExpression),std::string));
s.push_back(CUTE_EXPECT(CUTE(shouldThrowSyntaxError),std::string));
s.push_back(CUTE(testSimpleNumber));
s.push_back(CUTE(testSimpleAdd));
s.push_back(CUTE(testMultiAdd));
s.push_back(CUTE(testSimpleSubtract));
s.push_back(CUTE(testTenPlus12Minus100));
s.push_back(CUTE(testMultiply));
s.push_back(CUTE(testDivision));
s.push_back(CUTE(testAddThenMultiply));
s.push_back(CUTE(testAddSubSub));
s.push_back(CUTE(testAddThenMultiplyAdd));
s.push_back(CUTE(testSimpleParenthesis));
s.push_back(CUTE(testSimpleOperandParenthesis));
s.push_back(CUTE(testParenthesis));
s.push_back(CUTE(testNestedParenthesis));
s.push_back(CUTE(testDeeplyNestedParenthesis));
s.push_back(CUTE(testSimpleAssignment));
s.push_back(CUTE(testLongerVariables));
s.push_back(CUTE_EXPECT(CUTE(shouldThrowUndefined),std::string));
cute::ide_listener lis;
cute::makeRunner(lis)(s, "The Suite");
}
}
int main(){
runSuite();
}
YACC++ is a very good tool for parser generator for c++ applications. ANTLR is also agood option howver that does not have good documentation for its usage in C/C++.