Proper way to return from this loop

I'm not sure how to properly exit the loop after doing everything the function is supposed to do. The first 'if' in the for loop is where I'm stuck. I want to exit when the loop reaches the end, but I also want to do whatever that 'if' is going to do if one or more characters were alphabetic, not just the last one, which is what I'm currently testing for. Also, if anyone has any idea what my professor might mean by "the function rolls m_begin forward" please give me your interpretation. It's too early in the morning for me to email him. This is due very, very soon, so I'm posting here for help. I can provide the rest of the program if you need to reference it. For now, this is the function I'm working with:

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
// Test if substring is alphabetic
substring& substring::isalpha()
{
    /*
    DONE: if m_parse_success is equal to false, the function
    should do nothing and return immediately:

        if ( m_parse_success == false ) {
            // Nothing to do: the test has already failed prior
            // to this call:
            return *this;
        }

        // Parser state is ok, proceed:
        // ...


    TODO: use character by character scanning to test
    the characters of the underlying substring as follows:

        if ( isalpha( m_str[ position ] ) )

    The code uses standard library character classification
    function isalpha(ch), which returns non-zero if character ch
    is alphabetic, zero if not.

    After successful test m_begin position should be rolled forward
    to point to the next unparsed character in the underlying substring
    as shown by the following diagram:

 parsed characters                   unparsed characters
                 \____  ____________/
                  \   \/           /
        m_str: XXXXabcd????????????XXXXXXXXXX
                   |   |           |
                   |   `-m_begin   `-m_end
                   |
                   `-m_parse_begin
                     m_parse_success == true

    IMPORTANT: the test should stop immediately as soon as m_end position
    is reached.

    The success of the test is measured by the number of good matches.
    If one or more matches are found, the function rolls m_begin forward
    and returns.

    If no good matches are found (or if the substring is empty),
    the function should set m_parse_success flag to false and return:

        m_parse_success = false;
        return *this;

    */
    if (m_parse_success == false){
        return *this;
    }
    if (this->str() == ""){
        m_parse_success = false;
        return *this;
    }
    int pos = m_parse_begin;
    for (; pos <= m_end; pos++){
        if (std::isalpha(m_str[pos] && pos == m_end)){
            //m_parse_success = true;
            return *this;
        }
        if (!(std::isalpha(m_str[pos]))){
            m_parse_success = false;
            return *this;
        }
    }
}
this more advanced than me, but would exit (1) work?
My question relates more about exiting after doing "x" instead of using "x" to exit. In other words, I know how to exit a loop, but not necessarily when to in this case.
Either I'm misunderstanding the problem, or it's very simple problem explained in a very complicated way. Are you just trying to check if the entire substring is alphabetic?

If so: Only the second if is necessary. If the char at pos is non-alphabetic, it will quit. As far as "Quit as soon as m_end is reached": you don't need to do that manually (I'm guessing that's what you're trying to do with the first if?). Just set the ending condition to pos < m_end. When pos = m_end, the loop will exit by itself.

With "roll forward", I'm guessing you need to increment m_begin with the amount of alphabetic chars found, so they don't have to be checked again, i.e. m_begin needs to be assigned the value of the first non-alphabetic char. This value is already saved in "pos", which either holds the first non-alphabetic position (because the second if quit the loop at that point), or m_end (if all chars are alphabetic).

P.S.: In case I misunderstood the problem and you do need the first if:
Think you made a mistake on line 64:
if (std::isalpha(m_str[pos] && pos == m_end)){
should be:
if (std::isalpha(m_str[pos]) && pos == m_end){
(Or, better yet, reverse both, because "pos == m_end" is the cheaper one.)
you can enter line 62 (loop variable initialization) inside for statement like this:
for (int pos = m_parse_begin; pos <= m_end; pos++) as this is the usual form. No difference in program function though.

If I am getting right what are you trying to do you want to break a loop before reach its normal end (like here before reaching m_end)? If so you can always place break; to the point where you want to exit the loop.

Some explanation:
break;: terminates the inner loop you are in. This means in a coupled loop (loop inside loop only one loop is broken).

continue;: this one just proceeds to next loop circle. That means if in this loop circle pos was 3 by calling continue; we immediately go to next loop circle where pos=4.

I guess m_begin forward just means you start from your first place and advance by incrementing this (m_begin+1,m_begin+2 etc). Take in mind that I don't know what m_end and m_begin are but I hope you do. I guess they are some type of iterator right?

As far as I get it you just check one character per function call.
And if it's alphabetic you advance m_begin: m_begin++; and return *this;
If for some reason it's not alphabetic or it's empty sets m_parse_success = false; and return.

You just have to check current position versus m_end for this.
Well, in my functions 'return' is always the last statement. This is how I'd write that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    if(m_parse_success)
        m_parse_success = (this->str() != "");

    if(m_parse_success)
    {
        bool ok = m_parse_success; // You have 2 reasons to stop
        int pos = m_parse_begin;
        for(; ok && (pos < m_end); pos++) // Note: 'pos < m_end' since the index is 0 based
        {
            ok = std::isalpha(m_str[pos]);
        }
        m_parse_success = (pos > m_parse_begin);
        if(m_parse_success)
            m_parse_begin = pos;
    }
    return *this;


There's on condition missing here: What if m_parse_begin == m_end?
Yeah, come to think of it, you don't even need "pos". If you iterate directly over m_begin, it will contain the value of the first non-alphabetic, or m_end. Then, the parse success can be determined like this:
1
2
m_parse_success = (m_begin == m_end); 
// Returns 0 if not equal -> loop quit before it reached end -> there is a non-alpha! 
Gaminic: Success is
If one or more matches are found


EDIT: But you're right 'pos' is not necessarily needed
Last edited on
ok as I said Im not this advanced yet so sorry I couldnt help
Updated:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    if (m_parse_success == false){
        return *this;
    }
    else if (this->str() == ""){
        m_parse_success = false;
        return *this;
    }
    else if (!(std::isalpha(m_str[m_parse_begin]))){
        m_parse_success = false;
        return *this;
    }
    for (size_t ct = 0; m_begin < m_end; m_begin++){
        //std::cout << "m_str[" << m_begin << "] == " << m_str[m_begin] << '\n';//DEBUG
        if (std::isalpha(m_str[m_begin])){
            ct += 1;
        }
        if (ct > 0 && m_begin == m_end){
            m_parse_success = true;
        }
    }
     return *this;


also, some more description:

Proposed substring design favors pattern recognition and disambiguation, while the std::string is more of a text placeholder with built-in functionality for search and text mutation.

substring::parse( ) is the character scan initialization.

substring::isalpha( ) is the scan.

substring::succeeded( ) is the way to get boolean answer to whether the scan has passed ok.

Once the boundaries of the substring are initially set, the parsing can take various logical paths. If one would like to assure that the result of the scan has consumed the entire substring, they can use the substring::isempty( ) test at the end:

if ( sub.parse().isaplha().isempty().succeeded() == true ) //...

Due to rolling m_begin forward to m_end the substring will remain at an empty status once the entire sequence of characters was parsed successfully.

Since failed scan would inevitably obliterate the substring, substring::unparse( ) function allows program to recover and try an alternative character matching pattern.

Character test functions consume characters starting at the position m_begin. If characters pass the isalpha(ch) test, m_begin moves forward. For example,

sub.parse().isaplha().succeeded()

returns true if there is at least one alphabetic character at the beginning of the substring.

----------------------------------------------------------------------------------------------------------------------

I think this version works. Does anyone see anything wrong?

Full program code here: http://cplusplus.com/forum/beginner/58036/
Last edited on
Topic archived. No new replies allowed.