Help with applying a find function

So I have an assignment where I have to enter a phrase with opening and/or closing delimiters (i.e. (a), <e>, <(io>) etc.) where it checks to make sure that the opening and closing delimiters are used correctly and if not to tell you. The problem that I have is that I am now supposed to use a find function to specifically tell me which opening and/or closing delimiter I am missing. Though I understand the concept of the find() function I don't know how I should apply it to this program. Any help is greatly appreciated! Thanks!
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
#include <iostream>
#include <string>
#include <stack>
using namespace std;
int matcher(string expression);
int isOpener(char d);
int isCloser(char c) ;
int matches(char opener, char closer);
int main() {
	string exp, nil;
    nil = "";
    string balanced = "The expression is balanced";
    string unbalanced = "The expression is unbalanced";
	cout << "Enter an expression ";
    getline(cin, exp);
	while (exp != nil) {
		cout << exp << ": ";
		if (matcher(exp))
			cout << "Matched ok. " << balanced << endl;
		else
			cout << "Match error. " << unbalanced << endl;
        getline(cin, exp);
	}
	cout << "--- Done ---" << endl;
	return 0;
}

int matcher(string expression) {
	stack<char> s;
	for (int i = 0; i < expression.length(); i++) {
		if (isOpener(expression[i]))
			s.push(expression[i]);
		else if (isCloser(expression[i])) {
			if (s.empty()) return false;
			char opener = s.top();
			s.pop();
			if (!matches(opener, expression[i]))
                return false;
		}
	}
	if (!s.empty()) return false;
	return true;
}

int isOpener(char d) {return d == '(' || d == '[' || d == '<';}
int isCloser(char c) {return c == ')' || c == ']' || c == '>';}
int matches(char opener, char closer) {
	return
    (opener == '(' && closer == ')') ||
    (opener == '[' && closer == ']') || (opener == '<' && closer == '>');
}
You currently use an iterative technique to validate the expression - instead, replace your loop with a different loop that continually finds the next opener or closer.
Ok thanks I'll try that.
So as I realized I made a mistake in how I interpreted the assignment. I am supposed to find the missing limiter or delimiter. However, I do not necessarily need a find function and I'm pretty sure I need to keep the stack.
Ah, then your original code was fine, you just need to tweak it a bit to identify to the user where the error is ;)
So now I'm just stuck. I figure that the tweaks that I need have to be in the matcher function. However I just can't get it to recognize the opposite limiter and to print it out. Am I wrong to put it in the matcher function? I just can't figure out how. Can you give me a nudge in the right direction?
Is the delimiter always a single character?
For instance (Hello World) - delimiters ( and )

Or could it also be multiple characters?
For instance (<Hello World>) - delimiters (< and >)
it could be multiple. and it could be in the wrong order and it would still tell you if it was wrong. i.e. <(H>, [()], <[>]
The stack based approach is simpler; however since the assignment seems to be: 'get familiar with the find family of functions'

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

const std::string ws = " \t\n" ;
const std::string leading_delimiters = "(<[{" ;
const std::string trailing_delimiters = ")>]}" ;

// trim leading whitespace
std::string trim_leading_ws( const std::string& str )
{
     // http://www.cplusplus.com/reference/string/string/find_first_not_of/
     const auto pos = str.find_first_not_of(ws) ;
     return pos != std::string::npos ? str.substr(pos) : "" ;
}

// trim trailing whitespace
std::string trim_trailing_ws( const std::string& str )
{
     //http://www.cplusplus.com/reference/string/string/find_last_not_of/
     const auto pos = str.find_last_not_of(ws) ;
     return pos != std::string::npos ? str.substr( 0, pos+1 ) : "" ;
}

// trim trailing and trailing whitespace
std::string trim( const std::string& str )
{ return trim_trailing_ws( trim_leading_ws(str) ) ; }

// find starting delimiters
std::string find_starting_delimiters( std::string str )
{
     str = trim_leading_ws(str) ;
     const auto pos = str.find_first_not_of(leading_delimiters) ;
     return pos != std::string::npos ? str.substr(0,pos) : "" ;
}

// determine ending delimiters given the starting delimiters
std::string determine_ending_delimiters( const std::string& starting_delimiters )
{
    std::string temp ;

    // http://www.stroustrup.com/C++11FAQ.html#for
    for( char c : starting_delimiters )
    {
        // http://www.cplusplus.com/reference/string/string/find/
        const auto pos = leading_delimiters.find(c) ;
        if( pos != std::string::npos ) temp += trailing_delimiters[pos] ;
        else break ;
    }

    // ending delimiters must be in reverse order of starting delimiters
    return std::string( temp.rbegin(), temp.rend() ) ;
}

int main()
{
    std::string str = "    (<({[hello world!]})>)    " ;
    std::cout << "original: " << str << '\n' ;

    str = trim(str) ;
    std::cout << "trimmed: " << str << '\n' ;

    const std::string start_delims = find_starting_delimiters(str) ;
    std::cout << "starting delimiters: " << start_delims << '\n' ; // (<({[

    const std::string ending_delims = determine_ending_delimiters(start_delims) ;
    std::cout << "corresponding ending delimiters: " << ending_delims << '\n' ; // ]})>)
    
    // TODO: does the string str end with ending_delims?
    // TODO: if not, where is the mismatch?
}

http://coliru.stacked-crooked.com/a/ca5b529254ef124b
Like I said, I misinterpreted what my professor wanted. The friend function suggestion was a hint to figure out the problem. It didn't mean that I had to use it. Also, the program that you just added just tells me the opening the and closing delimiters. It doesn't specify which are missing in a specific situation. I need the program to point out if a '(' is missing or a '['. Also I need to keep the stack
Last edited on
> Also I need to keep the stack

You don't *need* a stack. Just parse the delimiters in pairs, from either end.

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

const std::string ws = " \t\n" ;

// trim leading whitespace
std::string trim_leading_ws( const std::string& str )
{
     // http://www.cplusplus.com/reference/string/string/find_first_not_of/
     const auto pos = str.find_first_not_of(ws) ;
     return pos != std::string::npos ? str.substr(pos) : "" ;
}

// trim trailing whitespace
std::string trim_trailing_ws( const std::string& str )
{
     //http://www.cplusplus.com/reference/string/string/find_last_not_of/
     const auto pos = str.find_last_not_of(ws) ;
     return pos != std::string::npos ? str.substr( 0, pos+1 ) : "" ;
}

// trim trailing and trailing whitespace
std::string trim( const std::string& str )
{ return trim_trailing_ws( trim_leading_ws(str) ) ; }

const std::string leading_delimiters = "(<[{" ;
const std::string trailing_delimiters = ")>]}" ;

// determine corresponding ending delimiter character
char ending_delimiter( char starting_delimiter )
{
    const auto pos = leading_delimiters.find(starting_delimiter) ;
    if( pos != std::string::npos ) return trailing_delimiters[pos] ;
    else return 0 ;
}

int main()
{
    std::string str = "    (<({[  hello world!  ]>)>)    " ;
    str = trim(str) ;
    std::cout << '\n' << str << "\n012345678901234567890123456789\n\n" ;

    const auto size = str.size() ;

    for( std::size_t i = 0 ; i < size ; ++i )
    {
        char end_delim = ending_delimiter( str[i] ) ;
        if( end_delim )
        {
            if( str[ size - i - 1 ] != end_delim )
            {
                std::cout << "mismatched deliniter at position " << i << '\n'
                          << "tried to match '" << str[i] << "' expected '" << end_delim
                          << "' got '" << str[ size - i - 1 ] << "'\n" ;
                break ;
            }
        }
        else break ;
    }
}


1
2
3
4
5
6
clang++ -std=c++11 -stdlib=libc++ -O2 -Wall -Wextra -pedantic-errors main.cpp -lsupc++ && ./a.out
(<({[  hello world!  ]>)>)
012345678901234567890123456789

mismatched deliniter at position 3
tried to match '{' expected '}' got '>'

http://coliru.stacked-crooked.com/a/63a9d1266e6cf576
Topic archived. No new replies allowed.