Simple parsing function

I'm working within the isalpha() function, starting on line 221 of substring.cpp.
I've started writing the definition, but I'm pretty sure I'm doing it wrong. I'm not sure where to begin fixing it. Any tips?

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())
{
}

// 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)
{
}

// 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 )
{
    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 )
{
    if (this->end() < other.begin() || this->begin() > other.end()){
        this->replace(temp_a);
        other.replace(temp_b);
    }
}

// Prepare substring for parsing
substring& substring::parse()
{
    /*
    This function initializes the substring preparing the object
    for character parsing.

    DONE: add two new member variables to the definition
    of the substring class:

        // Character parsing state variables:
        size_t m_parse_begin; // position where parsing starts
        bool m_parse_success; // flag to indicate the parsing succeeded

    and set them here as follows:

        m_parse_begin = m_begin;
        m_parse_success = true;

    Thus, parse() remembers the position at which the character
    matching starts:

        m_str: XXXX?????????????????XXXXXXXXXX
                   |                |
                   +-m_begin        `-m_end
                   |
                   `-m_parse_begin
                     m_parse_success == true
    */
    m_parse_begin = m_begin;
    m_parse_success = true;
    return *this;
}

// 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;
        }
    }
}
Last edited on
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_ 


substring_main.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
// 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;
}
Topic archived. No new replies allowed.