Stack program to check parenthesis balance

I have to write a program that prompts for a file name and then reads the file to check for balanced curly braces, {; parentheses, (); and square brackets, []. I have to use a stack to store the most recent unmatched left symbol. The program should ignore any character that is not a parenthesis, curly brace, or square bracket. I have to return the line that has the error.

Here is my code:

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
#include<iostream>
#include<string>
#include<stack>
#include<fstream>

using namespace std;

int checkBalance(char expression[]);

int main()
{
	int checkResult;
	char code[500];
	string fileName = "input1.txt";
	char x;
	ifstream inFile;
	inFile.open(fileName);
	inFile >> x;
	while (!inFile.eof())
	{
		for (int i = 0; i < 500; i++)
		{
			code[i] = x;
			inFile >> x;
		}
	}
	checkResult = checkBalance(code);
	if (checkResult == 0)
		cout << "There are no errors" << endl;
	else
		cout << "The error is on line: " << checkResult << endl;


	return 0;
}

int checkBalance(char expression[])
{
	stack<char> s;
	char a, b, c;
	int count = 1;
	while (count > 0)
	{
		for (int i = 0; i < strlen(expression); i++)
		{
			if (expression[i] == '(' || expression[i] == '{' || expression[i] == '[')
			{
				s.push(expression[i]);
			}
			else
			{
				switch (expression[i])
				{
				case ')':
					a = s.top();
					s.pop();
					if (a == '{' || a == '[')
						return count;
					break;
				case '}':
					b = s.top();
					s.pop();
					if (b == '(' || b == '[')
						return count;
					break;
				case ']':
					c = s.top();
					s.pop();
					if (c == '(' || c == '{')
						return count;
					break;
				}
			}
		}
		count++;
	}
	return 0;

}


It's compiling without any errors but when I try to run it, I get no output. I don't get any errors, but I don't get an output either. I don't understand what's wrong
Last edited on
1
2
3
4
5
6
7
8
9
	inFile >> x;
	while (!inFile.eof())
	{
		for (int i = 0; i < 500; i++)
		{
			code[i] = x;
			inFile >> x;
		}
	}
if your text has more than 500 characters you'll overwrite the beginning of `code'
if it has less, you'll reach an invalid state but keep writing to the end.
regardless, you do not put the terminator character '\0' on the c-string, so you can't use it on `strlen()'
1
2
3
4
5
6
int size = 0;
while(input>>x and size<500-1){ //more characters will be discarded
   code[size] = x;
   ++size;
}
code[size] = '\0';
you also said «I have to return the line that has the error» but I don't see where you separate between lines.


now, in `checkBalance()'
1
2
3
4
5
	int count = 1;
	while (count > 0){
		//...
		count++;
	}
¿when will that end?

and another thing
1
2
//case ')', ']', '}' 
a = s.top(); //¿what if `s' is empty? 
I don't see a way to get the lines without a lot of trouble (and avoiding the stack). You can do it inefficiently by reading ahead, but that isn't very clean. If you don't allow the symbols to span lines, its simple, but assuming they can split lines, it a bit of a pain.

do you need to make a little struct with character type and line #s? Then whats left on the stack is mismatched at that line?
Last edited on
jonnin said (before he edited his answer): you don't need a stack for this, an integer will do

You need a stack to ensure the different types of brackets are properly nested.
How would your system handle: ( [ ) ] ?
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class brace_balance_check{
public:
   bool check_balance(const std::string &line);
   bool empty() const;
private:
   std::stack<char> state;
};

brace_balance_check checker;
std::string line;
int line_number = 1;
while(std::getline(input, line){
   if(not checker.check_balance(line))
      std::cout << "error on line " << line_number << '\n';
   ++line_number;
}
if(not checker.empty())
   std::cout << "error on line " << line_number << '\n';
Do the brackets actually have to match on the same line? Or is:
(This is line 1;
This is line 2)

allowed?

Strictly speaking, you could probably use a string as a stack here. std::string has all the requisite operations.
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
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

//======================================================================

int checkBracket( istream &in )
{
   const string bracket = "({[";
   const string tekcarb = ")}]";
   string state, line;
   int numLines = 0;
   while( getline( in, line ) )
   {  
      numLines++;
      for ( char c : line )
      {
         if ( bracket.find( c ) != string::npos ) state += c;

         int pos = tekcarb.find( c );
         if ( pos != string::npos ) 
         {
            if ( state == "" || state.back() != bracket[pos] ) return numLines;
            state.pop_back();
         }
      }
   }

   return state == "" ? 0 : numLines;
}

//======================================================================

int main()
{
   stringstream in( "(ab(cd))=\n"
                    "a{b[d]b)a\n"
                    "E[[[d ]]]\n" );

   int L = checkBracket( in );

   if ( L ) cout << "Error in line " << L << '\n';
   else     cout << "All's well with the world.\n";
}

Last edited on
oh. If you just want to know if they balance, you have an integer for each symbol pair. there are only like 5 total in most languages/math/etc type text files.

paren ()
bracket {}
square []
angle <>

so those integers, find one ++, find mate --, at the end check if zero to see if it balanced.

But to find the line number of the problem is more work. You can't do that with just an integer. You can across 1 line, but not across a file. At that point a stack or other tracking system is needed to actually find the match (rather than just total up ).
Last edited on
you are still not handling nesting ( < ) > should be reported as an error, but only with numbers you can't distinguish (< from <(
correct. They balance, but are incorrect in syntax. You can't check syntax with just an integer, for sure.

and when you get to a real language checker, you can't do it with just a stack.

you get junk like

string s = "blah blah \" blah" //no stack or anything else will tell you this one: you have to actually parse it and 'understand' the escaped quote vs normal quotes.
Last edited on
Topic archived. No new replies allowed.