string容器
构造和析构
void testOne()
{
cout << "显示string中字符数组的最大长度" << endl;
cout << "string::npos " <<string::npos << endl;
//string类有七个构造函数(C++11新增了两个):
// 1)string(); // 创建一个长度为0的string对象(默认构造函数)。
cout << "1-------------" << endl;
string s1;
cout << "s1 = " << s1 << endl;
cout << "s1.capacity()= " << s1.capacity() << endl;
cout << "s1.size()= " << s1.size() << endl;
cout << "显示首地址" << endl;
cout << (void*)*s1.c_str() << endl;
cout << endl;
s1 = "hello ! my name is wangjianlin";
cout << "s1 = " << s1 << endl;
cout << "s1.capacity()= " << s1.capacity() << endl;
cout << "s1.size()= " << s1.size() << endl;
cout <<"显示不同的字符: " << endl;
cout << *s1.c_str() << endl;
cout << *(s1.c_str()+1) << endl;
cout << *(s1.c_str() + 2) << endl;
cout << "显示首地址" << endl;
cout << (void*)*s1.c_str() << endl;
//2)string(const char* s); // 将string对象初始化为s指向的NBTS(转换函数)。
cout << "2-------------" << endl;
string s2("hello word 1");
cout << "s2 =" << s2 << endl;
string s3 = "hello word 2";
cout << "s3 = " << s3 << endl;
//3)string(const string & str); // 将string对象初始化为str(拷贝构造函数)。
cout << "3-------------" << endl;
string s4(s2);
cout << "s4 =" << s4 << endl;
string s5 = s3;
cout << "s5 = " << s5 << endl;
//4)string(const char* s, size_t n); // 将string对象初始化为s指向的地址后n字节的内容。
cout << "4-------------" << endl;
string s6("hello word4", 3);
cout << "s6 = " << s6 << endl;
string s7("hello word4", 30);
cout << "s7 = " << s7 << endl;
//5)string(const string & str, size_t pos = 0, size_t n = npos); // 将sring对象初始化为str从位置pos开始到结尾的字符(或从位置pos开始的n个字符)。
cout << "5-------------" << endl;
string s8(s3, 3, 5);
cout << "s8 = " << s8 << endl;
string s9(s3, 3);
cout << "s9 = " << s9 << endl;
cout << "s9.capacity() = " << s9.capacity() << endl;
cout << "s9.size() = " << s9.size() << endl;
//6)template<class T> string(T begin, T end); // 将string对象初始化为区间[begin,end]内的字符,其中begin和end的行为就像指针,用于指定位置,范围包括begin在内,但不包括end。
//7)string(size_t n, char c); // 创建一个由n个字符c组成的string对象。
//析构函数~string()释放内存空间。
cout << "7-------------" << endl;
string s12(8, 'x');
cout << "s12 = " << s12 << endl;
cout << "s12.capacity() = " << s12.capacity() << endl;
cout << "s12.size() = " << s12.size() << endl;
string s13(30, 0);
cout << "s13 = " << s13 << endl;
cout << "s13.capacity() = " << s13.capacity() << endl;
cout << "s13.size() = " << s13.capacity() << endl;
// C++11新增的构造函数:
// 1)string(string && str) noexcept:它将一个string对象初始化为string对象str,并可能修改str(移动构造函数)。
// 2)string(initializer_list<char> il):它将一个string对象初始化为初始化列表il中的字符。
}
string容器的设计目标
string类的两种用途:
- 用作字符串
- 用作存放数据的容器
对第4个构造函数再次理解:
4)string(const char *s,size_t n); // 将string对象初始化为s指向的地址后n字节的内容。
参数的本质和append一致
string &append(const char *s,size_t n); // 将s指向的地址后n字节的内容连接到当前容器。( 任意数据类型 )
实例:让string存储结构体数据
void testTwo2()
{
struct st_girl { // 超女结构体。
int bh;
char name[30];
bool yz;
double weight;
string memo;
} girl;
cout << "超女结构体的大小:" << sizeof(struct st_girl) << endl;
string buffer; // 创建一个空的string容器buffer。
for (int i = 0; i < 10; i++) {
//将超女结构体的内存值置为 0
memset(&girl, 0, sizeof(struct st_girl));
//开始对结构体赋值
girl.bh = i;
sprintf_s(girl.name, "王健林%d", i);
girl.yz = true;
girl.weight = 50 + i;
girl.memo = "大家好才是真的好! ";
// 把超女结构追加到buffer中。
buffer.append((char*)&girl,sizeof(st_girl));
}
cout << "buffer.capacity()=" << buffer.capacity() << endl; // 显示容量。
cout << "buffer.size()=" << buffer.size() << endl; // 显示实际大小。
// 用一个循环,把buffer容器中全部的数据取出来。
for (int ii = 0; ii < buffer.size() / sizeof(struct st_girl); ii++)
{
memset(&girl, 0, sizeof(struct st_girl)); // 初始化超女结构体。
// 把容器中的数据复制到超女结构体。
memcpy(&girl, buffer.data() + ii * sizeof(struct st_girl), sizeof(struct st_girl));
// buffer.copy((char*)&girl, sizeof(struct st_girl), ii * sizeof(struct st_girl));
// 显示超女结构体成员的值。
cout << "bh=" << girl.bh << ",name=" << girl.name << ",yz=" << girl.yz << ",weight="
<< girl.weight << ",memo=" << girl.memo << endl;
}
}
其实,在这里:buffer.append()函数的参数和第4个构造函数是相同的。
使用char *s的好处是:
- 可以接受不同的数据类型,存储在string中(存储的时候地址需要强转一下)
(char*)&girl,sizeof(st_girl)
- 使用数据的时候,在按照数据长度转到相应的数据类型
memcpy(&girl, buffer.data() + ii * sizeof(struct st_girl), sizeof(struct st_girl));
strinf容器的操作
特性操作
size_t max_size() const; // 返回string对象的最大长度string::npos,此函数意义不大。
size_t capacity() const; // 返回当前容量,可以存放字符的总数。
size_t length() const; // 返回容器中数据的大小(字符串语义)。
size_t size() const; // 返回容器中数据的大小(容器语义)。
bool empty() const; // 判断容器是否为空。
void clear(); // 清空容器。
void shrink_to_fit(); // 将容器的容量降到实际大小(需要重新分配内存)。
void reserve( size_t size=0); // 将容器的容量设置为至少size。
void resize(size_t len,char c=0); // 把容器的实际大小置为len,如果len<实际大小,会截断多出的部分;如果len>实际大小,就用字符c填充。
字符操作
char &operator[](size_t n);
const char &operator[](size_t n) const; // 只读。
char &at(size_t n);
const char &at(size_t n) const; // 只读。
operator[]和at()返回容器中的第n个元素,但at函数提供范围检查,当越界时会抛出out_of_range异常,operator[]不提供范围检查。
const char *c_str() const; // 返回容器中动态数组的首地址,语义:寻找以null结尾的字符串。
const char *data() const; // 返回容器中动态数组的首地址,语义:只关心容器中的数据。
int copy(char *s, int n, int pos = 0) const; // 把当前容器中的内容,从pos开始的n个字节拷贝到s中,返回实际拷贝的数目。
string和char*相互转换
使用copy函数的例子:
string a("hello");
cout << a.max_size() << endl;
a.reserve(100);
cout << a.max_size() << endl;
cout << a.at(2) << endl;
cout<<a[0]<<endl;
a.at(2) = 'x';
cout << a << endl;
cout << (char*)a.c_str() << endl;
cout << "-----------" << endl;
string b="xxxxx";
cout << (char*)b.data() << endl;
cout << a.copy((char*)b.c_str(), 3, 0) << endl;
cout << b << endl;
cout << "---" << endl;
赋值操作
1)string &operator=(const string &str); // 把容器str赋值给当前容器。
2)string &assign(const char *s); // 将string对象赋值为s指向的NBTS。
3)string &assign(const string &str); // 将string对象赋值为str。
4)string &assign(const char *s,size_t n); // 将string对象赋值为s指向的地址后n字节的内容。
5)string &assign(const string &str,size_t pos=0,size_t n=npos); // 将sring对象赋值为str从位置pos开始到结尾的字符(或从位置pos开始的n个字符)。
连接操作
1)string &operator+=(const string &str); //把容器str连接到当前容器。
2)string &append(const char *s); // 把指向s的NBTS连接到当前容器。
3)string &append(const string &str); // 把容器str连接到当前容器。
4)string &append(const char *s,size_t n); // 将s指向的地址后n字节的内容连接到当前容器。
5)string &append(const string &str,size_t pos=0,size_t n=npos); // 将str从位置pos开始到结尾的字符(或从位置pos开始的n个字符)连接到当前容器。
交换操作
void swap(string &str); // 把当前容器与str交换。
如果数据量很小,交换的是动态数组中的内容,如果数据量比较大,交换的是动态数组的地址。
截取操作
string substr(size_t pos = 0,size_t n = npos) const; // 返回pos开始的n个字节组成的子容器。
之后的比较,查找,替换,删除都是string用作字符串。