一个 C++ 字符串类






4.96/5 (29投票s)
一个快速、引用计数、写时复制的字符串类
更新
开发现在使用 Visual Studio 2013 进行。
现在库中有两个 string 类,AnsiString 和 WideString,而 String 现在是一个 typedef,它将 String 映射到 WideString。
这两个类支持或多或少相同的接口。AnsiString 支持基于 char 的 string,而 WideString 支持基于 wchar_t 的 string。
基本转换现在由一些 static 重载函数处理
HWIN_EXPORT static WideString From( const std::string& s );
HWIN_EXPORT static WideString From( const char* s );
HWIN_EXPORT static WideString From( const char* s, size_type theLength );
HWIN_EXPORT static WideString From( const AnsiString& s );
HWIN_EXPORT static WideString From( const WideString& s );
HWIN_EXPORT static WideString From( const std::wstring& s );
HWIN_EXPORT static WideString From( const wchar_t* s );
HWIN_EXPORT static WideString From( const wchar_t* s, size_type theLength );
HWIN_EXPORT static WideString From( char value, int radix = 10 );
HWIN_EXPORT static WideString From( unsigned char value, int radix = 10 );
HWIN_EXPORT static WideString From( short value, int radix = 10 );
HWIN_EXPORT static WideString From( unsigned short value, int radix = 10 );
HWIN_EXPORT static WideString From( int value, int radix = 10 );
HWIN_EXPORT static WideString From( unsigned int value, int radix = 10 );
HWIN_EXPORT static WideString From( long long value, int radix = 10 );
HWIN_EXPORT static WideString From( unsigned long long value, int radix = 10 );
HWIN_EXPORT static WideString From( float value, wchar_t* fmt = L"%g" );
HWIN_EXPORT static WideString From( double value, wchar_t* fmt = L"%g" );
HWIN_EXPORT static WideString From( DateTime value );
如果一个 string 为空,并且在内部表示为 nullptr,c_str() 现在将返回一个指向以零结尾的空 string 的指针 - 而 data() 将返回 nullptr。
ICompareTo 和 icompare 执行不区分大小写的比较
int ICompareTo( const WideString& other ) const;
int ICompareTo( const wchar_t* str ) const;
int icompare( const WideString& other ) const;
int icompare( const wchar_t* str ) const;
不区分大小写的匹配实际上得到了很大的改进
size_type IIndexOfAnyOf( const wchar_t *searchChars, size_type numberOfSearchChars, 
                         size_type start ) const;
size_type IIndexOfAnyOf( const WideString& searchChars, size_type start = 0 ) const;
size_type IIndexOfAnyOf( const wchar_t* searchChars, size_type start = 0 ) const;
size_type IIndexOfAnyBut( const wchar_t *searchChars, size_type numberOfSearchChars, 
                         size_type start ) const;
size_type IIndexOfAnyBut( const WideString& searchChars, size_type start = 0 ) const;
size_type IIndexOfAnyBut( const wchar_t* searchChars, size_type start = 0 ) const;
size_type ILastIndexOfAnyOf( const wchar_t *searchChars, size_type numberOfSearchChars, 
                         size_type start ) const;
size_type ILastIndexOfAnyOf( const WideString& searchChars, 
                         size_type start = npos ) const;
size_type ILastIndexOfAnyOf( const wchar_t* searchChars, size_type start = npos ) const;
size_type ILastIndexOfAnyBut( const wchar_t *searchChars, size_type numberOfSearchChars, 
                         size_type start ) const;
size_type ILastIndexOfAnyBut( const WideString& searchChars, size_type start = npos ) const;
size_type ILastIndexOfAnyBut( const wchar_t* searchChars, size_type start = npos ) const;
size_type IIndexOf( const wchar_t *searchString, size_type searchStringLength, 
                         size_type start ) const;
size_type IIndexOf( const WideString& searchString, size_type start = 0 ) const;
size_type IIndexOf( const wchar_t* searchString, size_type start = 0 ) const;
size_type ILastIndexOf( const wchar_t *searchString, size_type searchStringLength, 
                         size_type start ) const;
size_type ILastIndexOf( const WideString& searchString, size_type start = npos ) const;
size_type ILastIndexOf( const wchar_t* searchString, size_type start = npos ) const;
size_type ILastIndexOf( wchar_t c, size_type start = npos ) const;
bool IStartsWith( const wchar_t* str ) const;
bool IStartsWith( const WideString& str ) const;
Split 是另一个新的成员函数,具有一些重载。
std::vector<widestring> Split( value_type delimiter ) const
std::vector<widestring> Split( value_type* delimiters ) const;
template<typename ForwardIterator>
std::vector<widestring> Split( ForwardIterator delimitersBegin, ForwardIterator delimitersEnd ) const;
std::vector<widestring> Split( std::initializer_list<value_type> delimiters ) const;
std::vector<widestring> Split( const std::vector<value_type>& delimiters ) const;
std::vector<widestring> Split( value_type delimiter, size_t max ) const;
然后是一些新的解析函数
HWIN_EXPORT bool ToBoolean( ) const;
HWIN_EXPORT char ToSByte( int radix = 0 ) const;
HWIN_EXPORT unsigned char ToByte( int radix = 0 ) const;
HWIN_EXPORT short ToInt16( int radix = 0 ) const;
HWIN_EXPORT unsigned short ToUInt16( int radix = 0 ) const;
HWIN_EXPORT int ToInt32( int radix = 0 ) const;
HWIN_EXPORT unsigned int ToUInt32( int radix = 0 ) const;
HWIN_EXPORT long long ToInt64( int radix = 0 ) const;
HWIN_EXPORT unsigned long long ToUInt64( int radix = 0 ) const;
HWIN_EXPORT float ToSingle( ) const;
HWIN_EXPORT double ToDouble( ) const;
HWIN_EXPORT DateTime ToDateTime( ) const;
HWIN_EXPORT TimeSpan ToTimeSpan( ) const;
HWIN_EXPORT Guid ToGuid( ) const;
还有哈希函子支持
template<>
struct hash<WideString> : public std::unary_function<WideString, size_t>
{
    inline size_t operator()(const WideString& theString) const
    {
        auto result = _Hash_seq((const unsigned char*) theString.c_str(), 
              theString.Length()*2);
        return result;
    }
};
这使得 AnsiString 和 WideString 可以用作诸如 std::unordred_map 之类的模板实例化的键。
引言
这是本系列关于 Windows C++ 开发的第五篇文章。
之前的文章可以在这里找到
String 类位于“\HarlinnWindows\hwinstring.h”。
为什么我们还需要另一个 C++ string 类?难道 CString、std::string 和 std::wstring 不够好吗?它们当然是设计良好的类,但事实证明,另一个 String 类是有充分理由的。
实现一个不错的 string 类本身也很有趣。
动机
String 是一个引用计数、写时复制的 string 类,它与以零结尾的 wchar_t* 二进制兼容。这样做的好处是,如果你有这样的代码
struct Foo1
{
int x;
int y;
wchar_t* pszText;
};
然后
struct Foo2
{
int x;
int y;
String Text;
};
将具有与 Foo1 相同的二进制布局,允许你将 Foo2 传递给期望 Foo1 的函数。
考虑以下内容
void Print( )
{
  std::wstring stdstring(L"stdstring" );
  wprintf( L"%s\n", stdstring );
  wprintf( L"%s\n", stdstring.c_str() );
  String s( L"String" );
  wprintf( L"%s\n", s );
  wprintf( L"%s\n", s.c_str( ) );
}
上面的代码输出到控制台的内容如下:
?8
stdstring
String
String
wprintf( L"%s\n", stdstring ); 只在控制台输出了 78,如果你仔细想想,我相信你也会同意我们只是碰巧运气好,程序没有崩溃。
wprintf( L"%s\n", stdstring.c_str() ); 和 wprintf( L"%s\n", s.c_str( ) ); 分别输出了 stdstring 和 String - 这几乎是我们期望的结果,而 wprintf( L"%s\n", s ); 输出 String 的行为与 wprintf( L"%s\n", s.c_str( ) ); 类似。这是因为 wchar_t* data_; 是 String 类中唯一的非 static 数据成员。
void print(const Foo1* p);
void doprint(const String& s)
{
  Foo2 foo2;
  foo2.x = 5;
  foo2.y = 5;
  foo2.Text = s + L" Printed";
  print( reinterpret_cast<Foo1*>(&foo2));
}
这意味着 String 变量 s 的大小是八字节,如果为 32 位架构编译,则是四字节。
String 基本上只是指向以下结构 data 字段的智能指针
struct Buffer
{
    size_type referenceCount;
    size_type length;
    wchar_t data[128];
};
因此,需要以下操作才能将指向以零结尾的 string 的指针转换为指向 Buffer 的指针
Buffer* toBuffer() const
{
    if(data)
    {
        return (Buffer*)(((char*)data) - offsetof(Buffer,data));
    }
    return nullptr;
}
由于 String 对象本质上是智能指针,用下面的代码替换像这样的代码
wchar_t* pointers[2];
pointers[0] = wcsdup(L"Some string");
pointers[1] = wcsdup(L"Some other string");
foo(pointers);
free(pointers[0]);
free(pointers[1]);
为...
std::vector<String> v;
v.push_back(String(L"Some string"));
v.push_back(String(L"Some other string"));
foo(reinterpret_cast<const wchar_t**> v.data());
...可能会让你的 C++ 开发者生涯少一些刺激。
这是你无法使用 CString、std::string 和 std::wstring 做到的事情,说到这里,我认为也应该公平地提到 String 类不执行小字符串优化,你也不能指定分配器。它的主要目的是作为 Windows API 工作时原始的以零结尾的 wchar_t string 的替代品,所以我想要的是我可以高效地传递、修改和返回的东西。
与使用 Windows API 的框架相关的 string 类最重要的三个特性是:
- 访问 string的内容
- 访问 string的长度
- 作为参数传递和作为结果返回
与 Windows API 交互时的典型用法
HWIN_EXPORT String Path::GetLongPathName(const String& path)
{
    if(path)
    {
        wchar_t buffer[MAX_PATH+1] = {0,};
        auto length = ::GetLongPathNameW(path.c_str(),
                                    buffer,sizeof(buffer)/sizeof(wchar_t));
        if(length == 0)
        {
            ThrowLastOSError();
        }
        if(length > (sizeof(buffer)/sizeof(wchar_t)))
        {
            String result;
            result.SetLength(length-1);
            length = ::GetLongPathNameW(path.c_str(),result.c_str(),length);
            if(length == 0)
            {
                ThrowLastOSError();
            }
            return result;
        }
        else
        {
            String result(buffer,length);
            return result;
        }
    }
    return String();
}
在第二次调用 ::GetLongPathNameW 时,数据将直接复制到 SetLength 调用分配的缓冲区中,这既方便又高效。
性能
String 类在大多数情况下表现都非常好,通常与 std::wstring 和 CString 相比都足够好。
测试操作于包含 100,000 个对象的 std::vector<T>。
测试的源代码位于“Examples\Windows\Strings\StringsExample”目录。
测试结果以毫秒为单位
| 字符串 | std::wstring | CString | .NET 字符串 | |
|---|---|---|---|---|
| 默认构造函数 | 0.2332 | 1.1048 | 0.9196 | 2.7119 | 
| 从短 string初始化 | 13.7469 | 13.6107 | 15.6871 | 15.6395 | 
| 获取长度 | 2.9202 | 7.6847 | 2.3535 | 1.4666 | 
| 获取 wchar_t* | 1425.2 | 1815.01 | 1485.07 | N/A | 
| 赋值 | 2.5579 | 11.5627 | 2.7839 | 2.0621 | 
| 使用 push_back初始化向量 | 14.0322 | 15.0869 | 17.3816 | 10.8025 | 
| 追加 string | 11.8091 | 15.6082 | 19.7568 | 2.4463 | 
| 追加 char | 532.829 | 313.211 | 270.669 | 5102.9609 | 
| Sort | 129.842 | 133.492 | 138.224 | 12689.2583 | 
| 简单查找任意一个 | 67.0268 | 71.8129 | 64.6829 | 44.737 | 
| 查找任意一个 | 128.498 | 255.84 | N/A | 294.803 | 
| 反向查找任意一个 | 144.412 | 211.391 | N/A | 445.1848 | 
| 查找 string | 52.0553 | 67.0184 | 28.6715 | 2543.4774 | 
| 反向查找 string | 132.073 | 162.209 | N/A | 3294.2206 | 
| 插入 string | 30.8257 | 34.8904 | 37.9284 | 177.7181 | 
| 删除字符 | 27.0146 | 24.288 | 25.2154 | 179.6267 | 
| 递归 | 75.5416 | 298.694 | 257.099 | 190.6845 | 
虽然 CString 在“查找字符串”测试中优于 String 和 std::wstring,但它是通过将自身视为以零结尾的 string 来实现的,忽略了它自己的长度 - 因此,当它包含 '\x00' 字符时,它可能找不到搜索 string 的出现。
CString::FindOneOf 不允许我们指定字符串内的偏移量来开始搜索,这限制了该函数的使用性。
库中还包含一个 StringBuilder 类,使用该类运行“追加字符”测试需要 153.791 毫秒 - 优于所有 string 类。
由于 .NET string 是不可变类型,它在“追加字符”测试中表现不佳也就不足为奇了,它不是为此类用途设计的。令人惊讶的是它在搜索和排序测试中的表现,虽然我没想到它能与 C++ 类媲美,但我确实期望它表现得更好。
观察
String 类与 std::wstring 和 CString 相比表现足够好 - 有一个值得注意的例外,追加字符对于 String 类来说比 CString 慢大约两倍。std::wstring 和 CString 都存储它们分配的容量,而 String 根据其长度计算容量,节省了八个字节的内存。
“追加字符”测试为每个 string 类型追加字符 38,250,000 次,所以目前我认为节省这 8 个字节是值得的性能损失,特别是 since String 类似乎在我们开始一次添加多个字符时,比其他两个类表现更好。
递归测试
我提到我想要一些我可以高效地传递、修改和返回的东西,递归测试试图展示我是否成功了。
递归函数将一个 String arg 的引用作为其参数之一。它将参数与 string L"Hi" 组合,并使用组合后的 string 作为 String 参数调用自身,直到 recursionLevel 达到 10000,然后返回最终组合的 String。
const size_t maxRecursion = 10000;
String StringRecursion(const String& arg,size_t recursionLevel)
{
    String result = arg + L"Hi";
    if(recursionLevel < maxRecursion)
    {
        recursionLevel++;
        result = StringRecursion(result,recursionLevel);
    }
    return result;
}
正如结果所示,String 类在这方面似乎比 CString 和 std::wstring 显著更好。
与 /Qpar(自动并行化器)编译器选项相关的意外优势
/Qpar 编译器开关启用代码中循环的自动并行化。
其中一个 String 测试的代码
void StringVectorGetTotalLength(const std::vector<String>& v)
{
    Stopwatch stopwatch;
    size_t totalLength = 0;
    stopwatch.Start();
    for(size_t i = 0; i < 100000;i++)
    {
        totalLength += v[i].length();
    }
    stopwatch.Stop();
    std::wcout 
       << L"std::vector<String> Get total length (" 
       << totalLength 
       << L") : " 
       << stopwatch.Elapsed().TotalMilliseconds() 
       << std::endl;
}
std::wstring 测试的代码
void wstringVectorGetTotalLength(const std::vector<std::wstring>& v)
{
    Stopwatch stopwatch;
    size_t totalLength = 0;
    stopwatch.Start();
    for(size_t i = 0; i < 100000;i++)
    {
        totalLength += v[i].length();
    }
    stopwatch.Stop();
    std::wcout 
       << L"std::vector<std::wstring> Get total length (" 
       << totalLength 
       << L") : " 
       << stopwatch.Elapsed().TotalMilliseconds() 
       << std::endl;
}
当我们在上述测试代码上启用自动并行化时,我们会得到截然不同的结果
- String:1.8227 - 性能提升约 60%
- std::wstring:0.5685 - 性能提升高达 1251%
最后一个结果有点令人费解 - 因为编译器并没有并行化上述循环,但结果确实如此 - 突然之间,编译器在优化标准 C++ 库代码方面能够创造奇迹。
看来指定 /Qpar 似乎启用了更积极的优化,即使最终没有发生并行化/向量化。
String 类
构造函数
String()
  : data(nullptr)
  {}
String s;
std::wcout << L"Empty string:" << (s?L"Not null" : L"null") << std::endl;
//Output:
//Empty string:null
默认构造函数仅将 data 设置为 nullptr,使此操作非常快速。
String(const String& other);
如果 other 是一个空 string,复制构造函数将 data 设置为 nullptr,当不是时,它只是增加缓冲区的引用计数。
String(String&& other);
移动构造函数在将 nullptr 分配给 other.data 之前,将 other.data 分配给 data。
String(size_type length, wchar_t c);
创建一个长度为 length 的新 string,并用字符 c 填充。
String(const wchar_t* str,size_type length, wchar_t padCharacter = defaultPadCharacter );
创建一个长度为 length 的新 string。如果 str 不为 nullptr,它将从 str 复制 length 个字符到 string,否则 string 将用 length 个 padCharacter 填充。
String(const wchar_t* str1,size_type length1, 
       const wchar_t* str2,size_type length2, 
       wchar_t padCharacter = defaultPadCharacter);
此构造函数通过连接两个 string 源来创建一个新的 String,如果 str1 或 str2 为 nullptr,则 padCharacter 将用于在新 String 中填充 length1 或 length2 个字符,分别。
String(const wchar_t* str1,size_type length1, 
       const wchar_t* str2,size_type length2, 
       const wchar_t* str3,size_type length3, 
       wchar_t padCharacter = defaultPadCharacter);
此构造函数通过连接三个 string 源来创建一个新的 String,如果 str1、str2 或 str3 为 nullptr,则 padCharacter 将分别用于在新 String 中填充 length1、length2 或 length3 个字符。
String(const wchar_t* str);
从以零结尾的 string 创建新的 String。如果 str 为 nullptr 或 length 为 0,则新 String 的 data 将设置为 nullptr。
析构函数
~String();
递减 Buffer 的引用计数,并在新的引用计数变为 0 时销毁 Buffer。
运算符
String& operator = (const String& other)
复制赋值将 data 设置为 other.data,如果 data 不为 nullptr,则增加 Buffer 的引用计数。处理自赋值。
String& operator = (String&& other)
移动赋值在将 other.data 设置为 nullptr 之前,将 data 赋值为 other.data。处理自赋值。
String& operator = (const wchar_t* str);
将以零结尾的 string 复制到此 String。处理特殊情况
String s1 = L"Hello";
s1 = s1.c_str() + 1;
bool operator == (const String& other) const;
bool operator != (const String& other) const;
bool operator <= (const String& other) const;
bool operator <  (const String& other) const;
bool operator >= (const String& other) const;
bool operator >  (const String& other) const;
bool operator == (const wchar_t* str) const;
bool operator != (const wchar_t* str) const;
bool operator <= (const wchar_t* str) const;
bool operator <  (const wchar_t* str) const;
bool operator >= (const wchar_t* str) const;
bool operator >  (const wchar_t* str) const;
完整的比较运算符集。
operator bool() const;
如果 data 为 nullptr,则返回 false,这允许我们使用简单的表达式测试空 string
String s(L"Hello");
if(s)
{
  // The string is not empty
}
wchar_t& operator[](size_type index);
返回 index 处字符的引用。这使得可以向 String 对象中的特定位置分配字符
String s1(L"Hi!",3);
String s2 = s1;
s2[1] = L'o';
// The contents of the s2 String object is now "Ho!", while s1 is still "Hi!"
此运算符确保 s2 引用一个唯一的缓冲区。
wchar_t operator[](size_type index) const;
返回 index 处的字符。
String& operator += (const String& other);
将 String other 追加到此 String。
String& operator += (const wchar_t* str);
将以零结尾的字符串 str 追加到此 String。
String& operator += (const wchar_t c);
将字符 c 追加到此 String。
friend String operator + (const String& str1,const String& str2)
通过连接 str1 和 str2 创建新的 string。
friend String operator + (const String& str1,const wchar_t* str2)
通过连接 str1 和 str2 创建新的 string。
friend String operator + (const String& str,const wchar_t c)
通过连接 String str 和字符 c 创建新的 string。
比较
int CompareTo(const String& other) const;
int CompareTo(const wchar_t* str) const;
returns
- < 0参数大于此- String
- = 0参数等于此- String
- > 0参数小于此- String
大小和字符数据访问
String& SetLength(size_type newLength)
确保 data 指向一个至少有 newLength+1 个字符大小的数组,或者在 newLength 为 0 时为 nullptr。
size_type length() const;
size_type Length() const;
返回 string 的 length(以字符为单位),不包括终止零,或者在 data 为 nullptr 时返回 0。
const wchar_t* c_str() const;
返回 data,请注意 data 可能在多个 String 对象之间共享。
wchar_t* c_str();
返回 data,如果 data 不为 nullptr,则保证 data 只被此 String 对象引用。
const wchar_t* begin() const;
wchar_t* begin();
const wchar_t* cbegin() const;
const wchar_t* end() const;
const wchar_t* cend() const;
wchar_t* end();
提供对字符缓冲区的“类迭代器”访问。对于非 const 版本,当 data 不为 nullptr 时,保证 data 只被此 String 引用。
“类迭代器”的意思是,它足以提供基于范围的 for 循环所需的功能
String s1 = L"Hello";
for(auto c : s1)
{
 std::wcout << L'\'' << c << L'\'' << std::endl;
}
// output:
// 'H'
// 'e'
// 'l'
// 'l'
// 'o'
for(auto& c : s1)
{
 c = c+1;
}
for(auto& c : s1)
{
 std::wcout << L'\'' << c << L'\'' << std::endl;
}
// output:
// 'I'
// 'f'
// 'm'
// 'm'
// 'p'
const String& CopyTo( wchar_t* buffer, size_type bufferSize, 
                    size_type start = 0, wchar_t padCharacter = defaultPadCharacter ) const;
将此 String 中最多 bufferSize 个字符复制到 buffer 指定的缓冲区中,从 start 开始。如果 start 和此 String 的末尾之间剩余的字符不够,则缓冲区的其余部分将用 padCharacter 填充。
String SubString ( size_type start, size_type length = npos) const;
返回一个包含此 String 子字符串的 String 对象。如果 start + length 大于此 String 的长度,则返回的 String 包含 start 和此 String 末尾之间的字符。
搜索
size_type IndexOfAnyOf ( const wchar_t *searchChars, 
                        size_type numberOfSearchChars, size_type start) const;
size_type IndexOfAnyOf ( const String& searchChars, size_type start = 0) const;
size_type IndexOfAnyOf( const wchar_t* searchChars, size_type start = 0) const;
返回 searchChars 中的任意字符的第一次出现索引,从 start 开始搜索。如果找不到这样的字符,则函数返回 String::npos。
size_type IndexOfAnyBut ( const wchar_t *searchChars, 
                         size_type numberOfSearchChars, size_type start) const;
size_type IndexOfAnyBut ( const String& searchChars, size_type start = 0) const;
size_type IndexOfAnyBut( const wchar_t* searchChars, size_type start = 0) const;
返回 searchChars 中 **不** 包含的任意字符的第一次出现索引,从 start 开始搜索。如果找不到这样的字符,则函数返回 String::npos。
size_type LastIndexOfAnyOf ( const wchar_t *searchChars, 
                           size_type numberOfSearchChars, size_type start) const;
size_type LastIndexOfAnyOf( const String& searchChars, size_type start = npos) const;
size_type LastIndexOfAnyOf( const wchar_t* searchChars, size_type start = npos) const;
从字符串末尾开始,向后搜索 searchChars 中的任意字符的出现,从 start 开始搜索。如果找到匹配项,则函数返回匹配字符的索引,或者在找不到这样的字符时返回 String::npos。
size_type LastIndexOfAnyBut ( const wchar_t *searchChars, 
                            size_type numberOfSearchChars, size_type start ) const;
size_type LastIndexOfAnyBut( const String& searchChars, size_type start = npos) const;
size_type LastIndexOfAnyBut( const wchar_t* searchChars, size_type start = npos) const;
从字符串末尾开始,向后搜索 **不** 包含 searchChars 中的任意字符的出现,从 start 开始搜索。如果找到匹配项,则函数返回匹配字符的索引,或者在找不到这样的字符时返回 String::npos。
size_type IndexOf( const wchar_t *searchString, size_type searchStringLength, size_type start) const;
size_type IndexOf( const String& searchString, size_type start = 0) const;
size_type IndexOf( const wchar_t* searchString, size_type start = 0) const;
size_type IndexOf( const wchar_t c, size_type start = 0) const;
在 start 处开始搜索 String,以查找 searchString 指定的内容或字符 c 的匹配项。返回第一个匹配项的索引,或者在找不到匹配项时返回 String::npos。
size_type IndexOf( bool ( *test )(wchar_t ) , size_type start = 0) const;
size_type IndexOf( bool ( *test )(const wchar_t*, size_type length ) , size_type start = 0) const;
size_type IndexOf( bool ( *test )(const wchar_t*, const wchar_t* ) , size_type start = 0) const;
在 start 处开始搜索 String,以查找由 test 评估的匹配项。返回第一个匹配项的索引,或者在找不到匹配项时返回 String::npos。
void CheckInvalidPathChars(const String& path)
{
    if(path.IndexOf([] (wchar_t c) -> bool
        {  
            return (c == '\"' || c == '<' || c == '>' || c == '|' || c < 32);
        }) != String::npos)
    {
        throw ArgumentException("Invalid path character");
    }
}
size_type LastIndexOf( const wchar_t *searchString, 
                     size_type searchStringLength, size_type start ) const;
size_type LastIndexOf( const String& searchString, size_type start = npos) const;
size_type LastIndexOf( const wchar_t* searchString, size_type start = npos) const;
size_type LastIndexOf( wchar_t c, size_type start = npos ) const;
在 start 处开始,向后搜索 String,以查找 searchString 指定的内容或字符 c 的匹配项。返回第一个匹配项的索引,或者在找不到匹配项时返回 String::npos。
size_type LastIndexOf( bool ( *test )(wchar_t ) , size_type start = npos) const;
size_type LastIndexOf( bool ( *test )(const wchar_t*, size_type length ) , size_type start = npos) const;
size_type LastIndexOf( bool ( *test )(const wchar_t*, const wchar_t*) , size_type start = npos) const;
在 start 处开始,向后搜索 String,以查找由 test 评估的匹配项。返回第一个匹配项的索引,或者在找不到匹配项时返回 String::npos。
bool StartsWith(const wchar_t* str) const;
bool StartsWith(const String& str) const;
如果 string 以与参数的完全匹配开始,则返回 true。
编辑
所有编辑操作都确保 Buffer 对 String 是唯一的,一个最初与其他 String 对象共享的 Buffer 只会减少其引用计数,而修改将应用于新的 Buffer。
String& UpperCase();
将此 String 中的所有字符转换为大写。
String& LowerCase();
将此 String 中的所有字符转换为小写。
String& Remove(size_type start, size_type length = npos);
从 start 开始,从此 String 中删除 length 个字符。
String& RemoveRange(size_type start, size_type end);
删除从索引 start 开始到不包括索引 end 的字符。
String& Keep(size_type start, size_type length = npos);
删除到索引 start 的所有字符,以及从索引 start+length 到此 String 末尾的所有字符。
String& KeepRange(size_type start, size_type end);
删除到索引 start 的所有字符,以及从索引 end 到此 String 末尾的所有字符。
String& Insert( const wchar_t* text, size_type textLength, size_type position );
String& Insert( const String& text, size_type position = 0);
String& Insert( const wchar_t* text, size_type position = 0);
在指定位置插入文本。如果 position 大于此 String 的长度,则文本将追加到此 String。
String& TrimRight(const wchar_t* charactersToRemove, size_type numberOfCharactersToRemove);
String& TrimRight(const String& charactersToRemove);
从此 String 的“右侧”修剪掉 charactersToRemove 指定的任何字符。
String& TrimRight();
从此 String 的“右侧”修剪掉任何“空白”字符。
String& TrimLeft();
从此 String 的“左侧”修剪掉任何“空白”字符。
String& Trim();
从此 String 的“左侧”和“右侧”修剪掉任何“空白”字符。
历史
- 2012 年 11 月 23 日 - 首次发布
- 2012 年 11 月 24 日 - 添加了性能信息
- 2012 年 11 月 28 日 - 添加了新的 StringBuilder类
- 2012 年 11 月 30 日 - 库更新
- 2012 年 12 月 8 日 - 库更新
- 2012 年 12 月 15 日 - 库更新
- 2014 年 8 月 20 日 - 多次更新和错误修复
- 2015 年 1 月 3 日 - 添加了一些新类、一些更新和一些错误修复


