3-4-5 字符串和字符的特性

3.4.5 字符串和字符的特性

1. string的模板定义

​ string来源于basic_string的模板实例化,basic_string用于支持任意类型字符的字符串。下面是string的定义:

typedef basic_string<char> string;

​ basic_string的模板有三个参数,第一个是字符类型,后两个是基于该字符类型的默认模板类参数:

template<class charT, class traits = char_traits<charT>, 
class allocator = allocator<charT> >
class basic_string;
  • char_traits是字符属性模板类,里面定义了字符操作的一组函数,basic_string<>字符串的比较函数就依赖于该类的以下函数:

    • eq(相等)
    • ne(不等)
    • lt(小于)
    • compare
    • find
  • allocator是内存分配器,用于指定内存分配的行为。

2. 创建一个无视大小写的string类

​ 由上述的char_traits可知,只需重写char_traits<char>类中的三个函数,再将其作为类模板参数传递给basic_string,就能实现无视大小写的string类。

#pragma once
#include <cctype>
#include <cmath>
#include <cstddef>
#include <ostream>
#include <string>
#include <cassert>
#include <iostream>
using std::allocator;
using std::basic_string;
using std::char_traits;
using std::ostream;
using std::size_t;
using std::string;
using std::tolower;
using std::toupper;

struct ichar_traits : char_traits<char> // 继承char_traits<char>后重写比较方法
{
static bool eq(char c1st, char c2nd)
{
return toupper(c1st) == toupper(c2nd);
}

static bool ne(char c1st, char c2nd)
{
return !eq(c1st, c2nd);
}

static bool lt(char c1st, char c2nd)
{
return toupper(c1st) < toupper(c2nd);
}

static int compare(const char *str1, const char *str2, size_t n)
{
for (size_t i = 0; i < n; i++)
{
if (str1 == 0)
return -1;
else if (str2 == 0)
return 1;
else if (tolower(*str1) < tolower(*str2))
return -1;
else if (tolower(*str1) > tolower(*str2))
return 1;
assert(tolower(*str1) == tolower(*str2));
++str1;
++str2;
}
return 0;
}

static const char *find(const char *s1, size_t n, char c)
{
while (n-- > 0)
{
if (toupper(*s1) == toupper(c))
return s1;
else
++s1;
}
return 0;
}
}; // end of struct

typedef basic_string<char, ichar_traits> istring; // rename

inline ostream &operator<<(ostream &os, const istring &s) // rewrite the << operator
{
return os << string(s.c_str(), s.length());
}

下面是使用案例:

#include <cassert>
#include <iostream>
#include "ichar_traits.h"
using namespace std;

int main()
{
istring first = "tHis";
istring second = "ThIS";
cout<<first<<endl;
cout<<second<<endl;
assert(first.compare(second) == 0);

assert(first.find('h') == 1);
assert(first.find('I') == 2);
assert(first.find('x') == string::npos);

}