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;
}
|