Can someone tell me why this function is executing twice?

It's the very last function, isalpha, in the substring.cpp file. It is only called once in main on line 82.

substring.cpp
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
#include "substring.h"
#include <string>
#include <iostream>
#include <algorithm>
#include <locale>

// Constructor that takes a reference to a string:
substring::substring( std::string& str )
    :
    m_str(str),
    m_begin(0),
    m_end(str.length()),
    m_parse_begin(m_begin),
    m_parse_success(true)
{
}

// Constructor that takes string reference, beginning, and ending positions
substring::substring( std::string& str, size_t pos_begin, size_t pos_end )
    :
    m_str(str),
    m_begin(pos_begin),
    m_end(pos_end),
    m_parse_begin(m_begin),
    m_parse_success(true)
{
}

// Return copy of the substring as std::string object
std::string substring::str() const
{
    return m_str.substr(m_begin, size());
    //                  starting length
    //                  position
}

// Return substring size
size_t substring::size() const
{
    return m_end - m_begin;
}

// Return beginning position
size_t substring::begin() const
{
    return m_begin;
}

// Return ending position
size_t substring::end() const
{
    return m_end;
}

// Set beginning position
void substring::begin( size_t pos )
{
    m_begin = pos;
}

// Set ending position
void substring::end( size_t pos )
{
    m_end = pos;
}

// The string content is set to an empty string
void substring::clear()
{
    m_str.replace(m_begin, size(), "");
    m_end = m_begin;
}

// Replace substring with str
substring& substring::replace( std::string const& str )
{
    m_str.replace(m_begin, size(), str);
    m_end = m_begin + str.length();
    return *this;
}

// Fill substring with a particular character
substring& substring::fill( char ch )
{
        size_t pos = m_begin;
        for(; pos < m_end; ++pos){
             m_str[pos] = ch;
        }
    return *this;
}

// Insert str at the specified position:
substring& substring::insert( std::string const& str, size_t pos )
{
    m_str.insert(pos, str);

    if (pos < m_begin){
        m_begin += str.length();
        m_end += str.length();
    }
    else if (pos > m_begin && pos < m_end){
        m_end += str.length();
    }
    else if (pos == m_begin){
        m_end += str.length();

    }
    else if (pos == m_end){
        //assuming the user wants the inserted string to be the end
        m_end += str.length();
    }

    return *this;
}

// Convert substring to UPPER CASE
substring& substring::toupper()
{
    size_t pos = m_begin;
        for(; pos < m_end; ++pos){
             m_str[pos] = std::toupper(m_str[pos]);
        }
    return *this;
}

// Convert substring to lower case
substring& substring::tolower()
{
    size_t pos = m_begin;
        for(; pos < m_end; ++pos){
             m_str[pos] = std::tolower(m_str[pos]);
        }
    return *this;
}

// Search for a new substring starting at the specified position:
size_t substring::search( const std::string& str, size_t pos )
{
    /*
    DONE: use find() of the underlying string and update the beginning
    and the ending positions of the substring.

    DONE: when find() call fails, it returns back the member value
    std::string::npos. In such case the substring must not update
    its positions and also return std::string::npos back to the caller:
    */
    size_t result = m_str.find(str, pos);
    if (result != std::string::npos){
        m_begin = result;
        m_end = m_begin + str.length();
        return result;
    }
    else{
        return std::string::npos;
    }
}

// The string content is set to the size of entire string
void substring::expand()
{
    m_begin = 0;
    m_end = m_str.length();
}

// Equality test between two substrings
bool substring::equals_to( substring const& other ) const
{
    return other.size() == size() &&
           std::equal(m_str.begin() + m_begin,
                      m_str.begin() + m_end,
                      other.m_str.begin() + other.m_begin);
}

// Equality test between substring and std::string
bool substring::equals_to( std::string const& str ) const
{
    return str.size() == size() &&
            std::equal(str.begin(), str.end(), m_str.begin() + m_begin);
}

// Merge with another substring
substring& substring::merge( substring const& other )
{
    m_begin = std::min(this->begin(), other.begin());
    m_end = std::max(this->end(), other.end());
    return *this;
}

// Swap values with another substring
void substring::swap( substring& other )
{
    /*
    DONE: Replace content of this substring with the
    content of the other, and vice versa.

    DONE: Make sure that the substrings don't overlap.
    Save the content of both substrings in two std::string
    objects and then invoke replace.
    */
    std::string temp_a = this->str();
    std::string temp_b = other.str();

    if (this->end() < other.begin() || this->begin() > other.end()){
        this->replace(temp_a);
        other.replace(temp_b);
    }
}

// Prepare substring for parsing
substring& substring::parse()
{
    m_parse_begin = m_begin;
    m_parse_success = true;
    return *this;
}

// Test if substring is alphabetic
substring& substring::isalpha()
{
    /*
    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;
    }
    /*size_t ct = 0;
    for (int pos = m_parse_begin; pos < m_end; pos++){
       if (isalpha(m_str[pos])){
        ct += 1;
       }
       if (ct > 0 && pos == m_end){
        m_begin += ct;
        m_parse_success = true;
       }
    }*/
    std::cout << "this->str() == " << this->str() << '\n';//DEBUG
    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;
        }
        else if (ct == 0 && m_begin == m_end){
            m_parse_success = false;
            m_begin = m_parse_begin;
        }
    }
    std::cout << "m_begin AFTER loop == " << m_begin << '\n';//DEBUG
    std::cout << "m_parse_success AFTER loop == " << m_parse_success << '\n';//DEBUG
    return *this;
}
Last edited on
OUTPUT:

this->str() == ax???
m_str[0] == a
m_str[1] == x
m_str[2] == ?
m_str[3] == ?
m_str[4] == ?
m_begin AFTER loop == 5
m_parse_success AFTER loop == 1
this->str() == ABC123abc
m_str[0] == A
m_str[1] == B
m_str[2] == C
m_str[3] == 1
m_str[4] == 2
m_str[5] == 3
m_str[6] == a
m_str[7] == b
m_str[8] == c
m_str[9] ==
m_begin AFTER loop == 10
m_parse_success AFTER loop == 1

Process returned 0 (0x0) execution time : 0.125 s
Press any key to continue.

main
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// main driver sample to test substring functionality.

#include <cassert>
#include <iostream>
#include "substring.h"

int main()
{
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    // Test basic substring functionality
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    std::string str( "abc" );
    substring sub( str );

    assert( sub.str() == "abc" );
    assert( sub.begin() == 0 );
    assert( sub.end() == 3 );
    assert( sub.end() == sub.size() );

    sub.begin( 1 ); // reposition absolute offsets
    sub.end( 2 );
    assert( sub.str() == "b" );

    sub.replace( "HELLO" );
    assert( sub.str() == "HELLO" );
    assert( str == "aHELLOc" );
    assert( sub.begin() == 1 );
    assert( sub.end() == 6 );
    assert( sub.size() == 5 );

    sub.clear();
    assert( sub.str() == "" );
    assert( str == "ac" );
    assert( sub.begin() == 1 );
    assert( sub.end() == 1 );
    assert( sub.size() == 0 );

    sub.insert( "XYZ", sub.begin() );
    assert( str == "aXYZc" );

    sub.expand();
    assert( str == "aXYZc" );
    assert( sub.begin() == 0 );
    assert( sub.end() == str.size() );

    size_t result = sub.search( "YZc", sub.end() );
    assert( result == std::string::npos );

    result = sub.search( "YZc", sub.begin() );
    assert( result == 2 );
    assert( sub.begin() == 2 );
    assert( sub.end() == str.size() );
    assert( sub.size() == 3 );

    sub.fill( '?' );
    assert( sub.begin() == 2 );
    assert( sub.end() == str.size() );
    assert( sub.equals_to( "???" ) );
    assert( str == "aX???" );

    sub.expand();
    sub.toupper();
    assert( sub.equals_to( "AX???" ) );
    assert( str == "AX???" );

    sub.tolower();
    assert( sub.equals_to( "ax???" ) );
    assert( str == "ax???" );

    substring sub2 = sub; // invokes copy constructor
    result = sub2.search( "x?", sub.begin() );
    assert( sub2.equals_to( "x?" ) );
    assert( sub.equals_to( "ax???" ) );

    std::string temp_a = sub.str();
    std::string temp_b = sub2.str();

    sub2.merge( sub );
    assert( sub2.equals_to( "ax???" ) );
    assert( sub.equals_to( sub2 ) );

    sub.isalpha();

    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    // Parsing tests
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
    str = "ABC123abc ";
    sub.expand();
    if ( sub.parse().isalpha().isdigit().isalnum().isspace().isempty().succeeded() ) {
        sub.match().replace( "xyz" );
        assert( str == "xyz" );
    } else {
        sub.unparse(); // restore the original substring
    }

    return 0;
}


substring.h
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// CIS-62 substring class

#ifndef _CIS62_SUBSTRING_H_INCLUDED_
#define _CIS62_SUBSTRING_H_INCLUDED_

#include <string>

class substring {
    std::string& m_str;
    size_t m_begin;  // absolute offset of the substring beginning
    size_t m_end;    // absolute offset of the substring ending
    size_t m_parse_begin; // position where parsing starts
    bool m_parse_success; // flag to indicate the parsing succeeded
public:
    // Constructor that takes a reference to a string:
    substring( std::string& str );

    // Constructor that takes string reference, beginning, and ending positions
    substring( std::string& str, size_t pos_begin, size_t pos_end );

    // Return copy of the substring as std::string object
    std::string str() const;

    // Return substring size
    size_t size() const;

    // Return beginning position
    size_t begin() const;

    // Return ending position
    size_t end() const;

    // Set beginning position
    void begin( size_t pos );

    // Set ending position
    void end( size_t pos );

    // The string content is set to an empty string
    void clear();

    // Replace substring with str
    substring& replace( std::string const& str );

    // Fill substring with a particular character
    substring& fill( char ch );

    // Insert str at the specified position:
    substring& insert( std::string const& str, size_t pos );

    // Convert substring to UPPER CASE
    substring& toupper();

    // Convert substring to lower case
    substring& tolower();

    // Search for a new substring starting at the specified position:
    size_t search( const std::string& str, size_t pos );

    // The string content is set to the size of entire string
    void expand();

    // Equality test between two substrings
    bool equals_to( substring const& other ) const;

    // Equality test between substring and std::string
    bool equals_to( std::string const& str ) const;

    // Merge with another substring
    substring& merge( substring const& other );

    // Swap with another substring
    void swap( substring& other );

    // Prepare substring for parsing
    substring& parse();

    // Test if substring is alphabetic
    substring& isalpha();

    // Test if substring is upper case
    substring& isupper();

    // Test if substring is lower case
    substring& islower();

    // Test if substring is digit
    substring& isdigit();

    // Test if substring is alphabetic or digit
    substring& isalnum();

    // Test if substring is blank, tab, newline, return, formfeed, or vertical tab
    substring& isspace();

    // Test if substring is matches text specified by str
    substring& isstr( const std::string& str );

    // Test if substring is empty
    substring& isempty();

    // Return beginning position
    bool succeeded() const;

    // Return matching substring
    substring match() const;

    // Undo changes caused by parsing
    substring& unparse();
};
#endif // _CIS62_SUBSTRING_H_INCLUDED_ 
Last edited on
You don't show main(). Show main() please, or we are unable to respond. Also how do you determine it is called twice?
Oh boy, scratch this. I'm dumb.
Your main function calls it twice. (Lines 82 and 89.)
Topic archived. No new replies allowed.