目录
- 标准库与 QT 字符串处理
- 标准库类模板
- 模板参数与构造函数
- basic_string 的其他成员函数
- QString
- QString 特性
- QByteArray
- 国际化与区域文化
- 区域文化
- facet
- numpunct
- time_get
- time_put
- codecvt
标准库与 QT 字符串处理
标准库类模板
C++使用类模板 basic_string 来存放字符串数据,并提供了一组成员函数来处理该字符串
basic_string 还具有一个明显的优势:自动内存管理功能
模板参数与构造函数
类 string 及 wstring 是 basic_string 特化的结果
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
basic_string 常见的构造函数及其使用方法
对于 wchar_t
类型的 basic_string,最好在字符串常量的前面加上前缀“L”
#include <string>
#include <iostream>
using namespace std;
int main()
{basic_string<char> s1;basic_string<char> s2 ("hello world");basic_string<char> s3 ("hello world", 5);basic_string<char> s4 ( s2, 6, 5);cout << s1 << endl << s2 << endl << s3 << endl << s4 << endl;// 加了L前缀的字符串basic_string<wchar_t> ws (L"得友难失友易(A friend is easier lost thanfound)");wcout.imbue(locale("chs"));wcout << "size is: " << sizeof(ws[7]) << endl << ws << endl;
}
basic_string 的其他成员函数
c_str()
该函数返回一个指针,指向 basic_string 中存放的字符串数据
对于 string
类型,该函数返回char *
;
对于 wstring
类型,该函数返回wchar_t *
;
basic_string 的类模板存在一个专门存放字符串长度的成员变量,通过 length()直接获取字符串长度,可以相对于 strlen()方法获取长度节省很多时间
QString
QString 能对 Unicode 字符串进行拼接、查找等操作
不建议使用 basic_string 中的 wstring 替换掉 QString,因为前者对于标点符号判断等其他操作支持较差,而后者封装完善便于拿来即用
QString 特性
利用 fromLocal8Bit()
,将该字符串转换为 Unicode 编码的字符
QString 的成员函数 data()
返回一个指针,指向 QChar 序列
QString 自带的字符编码转换功能展示:
// 定义 main 函数
int main()
{// 定义一个 char* 类型的字符串 humor,包含了英文和中文字符char * humor = "Your future depends on your dream. So go to sleep.\n""你的梦想决定你的未来,所以睡觉去吧。";// 将 humor 转换为 QString 类型的字符串 qs,使用 fromLocal8Bit 方法将 humor 中的字符转换为本地编码QString qs = QString::fromLocal8Bit(humor);// 将 qs 转换为 QByteArray 类型的数据 data,使用 toUtf8 方法将 qs 中的字符转换为 UTF-8 编码QByteArray data = qs.toUtf8();// 打开文件 utf8.txt,以二进制模式写入数据ofstream of("utf8.txt", ios::binary);// 将 data 中的数据写入文件,使用 data.data() 获取数据指针,data.length() 获取数据长度of.write(data.data(), data.length());
}
QByteArray
类 QByteArray
被用来存放长度可变的字节序列,其中的字节序列被存放在一个地址连续的内存块中
该类总会在字节序列的末尾添加一个额外的“\0”
字符
国际化与区域文化
区域文化
C++标准库提供了类 locale
以及 facet
,分别用来描述某个区域的区域文化以及文化刻面
所有流对象都会共享一个全局的 locale 对象
一般的,开发者不需要知道 facet 的原理,直接使用 locale 即可实现区域文焕转换设定
下方代码展示了使用 cout 输出区域文化为德国的文本
#include <iostream>
#include <locale>
using namespace std;
int main( )
{double x = 1234567.123456;cout.imbue( locale( "German_germany" ) );①cout << fixed << x << endl;
}
facet
每个 facet 子类描述某个文化刻面。C++标准库定义了 12 个常用的 facet 子类,来刻画时间、货币等表达方式
facet 对象不能够单独存在,它们必须隶属于某个 locale 对象
通过调用函数模板 use_facet<>
可以获得一个 locale 对象中某个 facet 对象的引用
numpunct
numpunct
是 facet 的一个子类,可以通过 use_facet
获取 facet 对象后对其实例化得到 numpunct 对象
#include <locale>
#include <iostream>// 定义 main 函数
int main()
{// 创建一个 locale 对象 os_locale,使用默认本地化设置locale os_locale("");// 获取 os_locale 的数字标点符号,使用 use_facet 方法获取 numpunct<char> 类型的 facet 对象const numpunct<char>& np = use_facet<numpunct<char>>(os_locale);// 输出数字标点符号的信息,包括小数点、千位分隔符、true/false 字符串等std::cout << "number punctuation of " << os_locale.name() << std::endl;std::cout << np.decimal_point() << " "<< np.thousands_sep() << " "<< np.falsename() << " " << np.truename() << std::endl;// 获取数字分组信息,输出每个分组的长度std::string group = np.grouping();for (int i = 0; i < group.length(); i++) {std::cout << i << "th grouping is: " << (int)group[i] << std::endl;}
}
time_get
类模板 time_get
对一个表示日期和时间的字符序列进行解析,将其中的信息存放在结构体 tm 中
类模板 time_get 的基本使用方法
#include <iostream>
#include <sstream>
#include <locale>// 定义 main 函数
int main()
{// 创建一个 locale 对象 loc,使用默认本地化设置locale loc;// 获取 loc 的 time_get facet 对象 tg,用于解析时间信息const time_get<char>& tg = use_facet<time_get<char>>(loc);// 获取日期的顺序信息,使用 date_order() 方法获取日期的顺序,返回值为整数int idx = tg.date_order();// 输出本地化设置的名称和日期的顺序信息,message 数组用于将整数转换为字符串char *message[] = {"no_order", "dmy", "mdy", "ymd", "ydm"};std::cout << loc.name() << std::endl << "date order " << message[idx] << std::endl;// 解析时间信息,使用 istringstream 类创建一个输入流 iss,包含了要解析的时间字符串 "10:26:00"std::ios::iostate state = 0;std::istringstream iss("10:26:00");// 创建一个 istreambuf_iterator 对象 itbegin,指向 iss 的开头std::istreambuf_iterator<char> itbegin(iss);// 创建一个 istreambuf_iterator 对象 itend,指向 iss 的结尾std::istreambuf_iterator<char> itend;// 创建一个 tm 结构体对象 time,用于存储解析后的时间信息std::tm time;// 使用 time_get 的 get_time 方法解析时间信息,将结果存储在 time 中tg.get_time(itbegin, itend, iss, state, &time);// 输出解析后的时间信息std::cout << time.tm_hour << ":" << time.tm_min << ":" << time.tm_sec << std::endl;
}
time_put
类模板 time_put
将存放在结构体 tm 中的日期和时间信息以某种特定的格式转化为一个字符序列
使用场景较少,不浪费过多笔墨介绍该类模板
codecvt
类模板 codecvt
将某一种编码的字符串转换为另外一种编码的字符串
此为对应模板以及三个模板参数的含义
- internT 表示一个字符串在计算机内部的编码类型
- externT 表示该字符串在外部存储设备(比如文件系统)中的编码类型
- stateT 是一个表示转换状态的类型
template <class internT,class externT,class stateT> codecvt
类模板 codecvt 的成员函数 in 的功能
#include <iostream>
#include <locale>// 定义 main 函数
int main()
{// 定义 codecvt 类型的别名 cvt_typetypedef codecvt<wchar_t, char, mbstate_t> cvt_type;// 创建一个 locale 对象 loc,使用默认本地化设置locale loc;// 获取 loc 的 codecvt facet 对象 cvt,用于字符编码转换const cvt_type& cvt = use_facet<cvt_type>(loc);// 定义字符数组,src 为待转换的字符串,dst 为存储转换结果的字符串const int size = 20;const char* p1, src[size] = "hello world!";wchar_t* p2, dst[size];// 定义 mbstate_t 对象 state,用于存储转换过程中的状态信息mbstate_t state;// 使用 cvt.in() 方法将 src 中的字符转换为 dst 中的宽字符cvt_type::result result = cvt.in(state,src, src + size, p1,dst, dst + size, p2);// 如果转换成功,输出转换结果if (result == cvt_type::ok) {std::wcout << dst << std::endl;}return 0;
}