增强字符串分割类,支持中途修改分隔符,单元测试通过
This commit is contained in:
parent
4a5d2c746a
commit
858d1e49a1
|
@ -150,8 +150,9 @@ public:
|
||||||
bool EndsWith(cstring str) const;
|
bool EndsWith(cstring str) const;
|
||||||
|
|
||||||
StringSplit Split(const String& sep) const;
|
StringSplit Split(const String& sep) const;
|
||||||
|
StringSplit Split(cstring sep) const;
|
||||||
|
|
||||||
String Substring(int start, int _Length) const;
|
String Substring(int start, int len = -1) const;
|
||||||
String TrimStart() const;
|
String TrimStart() const;
|
||||||
String TrimEnd() const;
|
String TrimEnd() const;
|
||||||
String Trim() const;
|
String Trim() const;
|
||||||
|
@ -195,18 +196,22 @@ private:
|
||||||
class StringSplit
|
class StringSplit
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StringSplit(const String& str, const String& sep);
|
cstring Sep; // 分隔符。下一个要寻找的边界符
|
||||||
|
int Position; // 当前段位置。负数表示到了结尾。
|
||||||
|
int Length; // 当前段长度。
|
||||||
|
|
||||||
|
StringSplit(const String& str, cstring sep);
|
||||||
|
|
||||||
const String Next();
|
const String Next();
|
||||||
|
|
||||||
explicit operator bool() const { return _Position >= 0; }
|
// 是否已经到达末尾
|
||||||
bool operator !() const { return _Position < 0; }
|
bool End() const { return Position == -2; }
|
||||||
|
|
||||||
|
explicit operator bool() const { return Position >= 0; }
|
||||||
|
bool operator !() const { return Position < 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const String& _Str;
|
const String& _Str;
|
||||||
const String& _Sep;
|
|
||||||
int _Position;
|
|
||||||
int _Length;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -882,15 +882,22 @@ bool String::EndsWith(cstring str) const
|
||||||
}
|
}
|
||||||
|
|
||||||
StringSplit String::Split(const String& sep) const
|
StringSplit String::Split(const String& sep) const
|
||||||
|
{
|
||||||
|
return StringSplit(*this, sep.GetBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSplit String::Split(cstring sep) const
|
||||||
{
|
{
|
||||||
return StringSplit(*this, sep);
|
return StringSplit(*this, sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
String String::Substring(int start, int length) const
|
String String::Substring(int start, int len) const
|
||||||
{
|
{
|
||||||
String str;
|
String str;
|
||||||
|
|
||||||
|
if(len < 0) len = _Length - start;
|
||||||
//str.Copy(this, _Length, start);
|
//str.Copy(this, _Length, start);
|
||||||
if(_Length && start < _Length) str.copy(_Arr + start, length);
|
if(_Length && start < _Length) str.copy(_Arr + start, len);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
@ -1077,41 +1084,61 @@ char *dtostrf (double val, char width, byte prec, char* sout)
|
||||||
|
|
||||||
/******************************** StringSplit ********************************/
|
/******************************** StringSplit ********************************/
|
||||||
|
|
||||||
StringSplit::StringSplit(const String& str, const String& sep) :
|
StringSplit::StringSplit(const String& str, cstring sep) :
|
||||||
_Str(str),
|
_Str(str)
|
||||||
_Sep(sep)
|
|
||||||
{
|
{
|
||||||
_Position = 0;
|
Sep = sep;
|
||||||
_Length = 0;
|
Position = -1;
|
||||||
|
Length = 0;
|
||||||
|
|
||||||
// 先算好第一段
|
// 先算好第一段
|
||||||
int p = _Str.IndexOf(_Sep);
|
//int p = _Str.IndexOf(_Sep);
|
||||||
if(p >= 0) _Length = p;
|
//if(p >= 0) _Length = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
const String StringSplit::Next()
|
const String StringSplit::Next()
|
||||||
{
|
{
|
||||||
auto ptr = _Str.GetBuffer();
|
cstring ptr = nullptr;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if(_Position < 0 || _Length == 0)
|
if(Position >= -1 && Sep)
|
||||||
ptr = nullptr;
|
{
|
||||||
|
String sp = Sep;
|
||||||
|
|
||||||
|
// 从当前段之后开始找一段
|
||||||
|
int s = Position + Length;
|
||||||
|
// 除首次以外,每次都要跳过分隔符
|
||||||
|
if(s < 0)
|
||||||
|
s = 0;
|
||||||
|
else
|
||||||
|
s += sp.Length();
|
||||||
|
|
||||||
|
// 检查是否已经越界
|
||||||
|
if(s >= _Str.Length())
|
||||||
|
{
|
||||||
|
Position = -2;
|
||||||
|
Length = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 拿出当前段,然后提前计算下一段
|
// 查找分隔符
|
||||||
ptr += _Position;
|
int p = _Str.IndexOf(Sep, s);
|
||||||
len = _Length;
|
|
||||||
|
|
||||||
// 找到下一个位置
|
int sz = 0;
|
||||||
// 剩余全部长度,如果找不到下一个,那么这个就是最后长度
|
// 剩余全部长度,如果找不到下一个,那么这个就是最后长度。不用跳过分隔符
|
||||||
int end = _Str.Length();
|
if(p < 0)
|
||||||
_Position += _Length + _Sep.Length();
|
sz = _Str.Length() - s;
|
||||||
int p = _Str.IndexOf(_Sep, _Position);
|
else
|
||||||
if(p > 0) end = p;
|
sz = p - s;
|
||||||
|
|
||||||
_Length = end - _Position;
|
Position = s;
|
||||||
|
Length = sz;
|
||||||
|
|
||||||
|
ptr = _Str.GetBuffer() + Position;
|
||||||
|
len = Length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 包装一层指针
|
// 包装一层指针
|
||||||
return String((cstring)ptr, len);
|
return String(ptr, len);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,11 +56,10 @@ IPAddress IPAddress::Parse(const String& ipstr)
|
||||||
if(ipstr == "255.255.255.255") return IPAddress::Broadcast();
|
if(ipstr == "255.255.255.255") return IPAddress::Broadcast();
|
||||||
|
|
||||||
// 这里不能在Split参数直接使用字符指针,隐式构造的字符串对象在这个函数之后将会被销毁
|
// 这里不能在Split参数直接使用字符指针,隐式构造的字符串对象在这个函数之后将会被销毁
|
||||||
String sep(".");
|
auto sp = ipstr.Split(".");
|
||||||
auto ss = ipstr.Split(sep);
|
for(int i=0; i<4 && sp; i++)
|
||||||
for(int i=0; i<4 && ss; i++)
|
|
||||||
{
|
{
|
||||||
auto item = ss.Next();
|
auto item = sp.Next();
|
||||||
if(item.Length() == 0 || item.Length() > 3) break;
|
if(item.Length() == 0 || item.Length() > 3) break;
|
||||||
|
|
||||||
// 标准地址第一个不能是0,唯一的Any例外已经在前面处理
|
// 标准地址第一个不能是0,唯一的Any例外已经在前面处理
|
||||||
|
|
|
@ -327,6 +327,77 @@ static void TestCompare()
|
||||||
assert(str3.EqualsIgnoreCase(String(cs2)), err);
|
assert(str3.EqualsIgnoreCase(String(cs2)), err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TestSplit(cstring cstr)
|
||||||
|
{
|
||||||
|
TS("TestSplit");
|
||||||
|
|
||||||
|
debug_printf("字符串分割测试\r\n");
|
||||||
|
|
||||||
|
String str = cstr;
|
||||||
|
|
||||||
|
auto err = "StringSplit Split(cstring sep) const";
|
||||||
|
|
||||||
|
int p = -1;
|
||||||
|
auto sp = str.Split(",");
|
||||||
|
assert(sp.Position == p && sp.Length == 0, err);
|
||||||
|
assert(!sp.End(), err);
|
||||||
|
|
||||||
|
auto rs = sp.Next();
|
||||||
|
|
||||||
|
p = 0;
|
||||||
|
|
||||||
|
// 如果分隔符开头,则跳过它
|
||||||
|
if(cstr[0] == ',')
|
||||||
|
{
|
||||||
|
rs = sp.Next();
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sp.Position == p && sp.Length == 4, err);
|
||||||
|
assert(rs == "+IPD", err);
|
||||||
|
p += 4 + 1;
|
||||||
|
|
||||||
|
rs = sp.Next();
|
||||||
|
assert(sp.Position == p && sp.Length == 1, err);
|
||||||
|
assert(rs.ToInt() == 3, err);
|
||||||
|
p += 1 + 1;
|
||||||
|
|
||||||
|
rs = sp.Next();
|
||||||
|
assert(sp.Position == p && sp.Length == 2, err);
|
||||||
|
assert(rs.ToInt() == 96, err);
|
||||||
|
p += 2 + 1;
|
||||||
|
|
||||||
|
rs = sp.Next();
|
||||||
|
assert(sp.Position == p && sp.Length == rs.Length(), err);
|
||||||
|
assert(rs == "10.0.0.21", err);
|
||||||
|
p += rs.Length() + 1;
|
||||||
|
|
||||||
|
// 更换分隔符
|
||||||
|
sp.Sep = ":";
|
||||||
|
rs = sp.Next();
|
||||||
|
assert(sp.Position == p && sp.Length == 4, err);
|
||||||
|
assert(rs.ToInt() == 3377, err);
|
||||||
|
p += 4 + 1;
|
||||||
|
|
||||||
|
// 最后一组
|
||||||
|
rs = sp.Next();
|
||||||
|
assert(sp.Position == p && sp.Length == rs.Length(), err);
|
||||||
|
assert(rs == "abcdef", err);
|
||||||
|
//assert(sp.Position + sp.Length == str.Length(), err);
|
||||||
|
|
||||||
|
// 再来一组
|
||||||
|
rs = sp.Next();
|
||||||
|
assert(sp.End(), err);
|
||||||
|
assert(sp.Position == -2 && sp.Length == 0, err);
|
||||||
|
assert(!rs, err);
|
||||||
|
|
||||||
|
// 到了默认不再查找
|
||||||
|
rs = sp.Next();
|
||||||
|
assert(sp.End(), err);
|
||||||
|
assert(sp.Position == -2 && sp.Length == 0, err);
|
||||||
|
assert(!rs, err);
|
||||||
|
}
|
||||||
|
|
||||||
void String::Test()
|
void String::Test()
|
||||||
{
|
{
|
||||||
TS("TestString");
|
TS("TestString");
|
||||||
|
@ -346,6 +417,13 @@ void String::Test()
|
||||||
|
|
||||||
TestCompare();
|
TestCompare();
|
||||||
|
|
||||||
|
// 分隔符
|
||||||
|
cstring cstr = "+IPD,3,96,10.0.0.21,3377:abcdef";
|
||||||
|
TestSplit(cstr);
|
||||||
|
// 以分隔符开头和结尾的情况
|
||||||
|
cstr = ",+IPD,3,96,10.0.0.21,3377:abcdef:";
|
||||||
|
TestSplit(cstr);
|
||||||
|
|
||||||
debug_printf("字符串单元测试全部通过!");
|
debug_printf("字符串单元测试全部通过!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue