tring 类
声明
string 类本不是 STL 的容器, 但是它与 STL 容器有着很多相似的操作, 因此, 把 string 放在这里一起进行介绍.?
之所以抛弃 char * 的字符串而选用 C++ 标准程序库中的 string 类, 是因为他和前者比较起来, 不必担心内存是否足够, 字符串长度等等, 而且作为一个类出现, 他集成的操作函数足以完成我们大多数情况下的需要. 我们尽可以把它看成是 C++ 的基本数据类型.?
首先, 为了在我们的程序中使用 string 类型, 我们必须包含头文件. 如下:
include // 注意这里不是 string.h,string.h 是 C 字符串头文件
1, 声明一个 C++ 字符串
声明一个字符串变量很简单:?string str;?
这样我们就声明了一个字符串变量, 但既然是一个类, 就有构造函数和析构函数. 上面的声明没有传入参数, 所以就直接使用了 string 的默认的构造函数, 这个函数所作的就是把 str 初始化为一个空字符串. string 类的构造函数和析构函数如下:
- ) string s; // 生成一个空字符串 s
- ) string s(str) ; // 拷贝构造函数生成 str 的复制品
- ) string s(str, stridx); // 将字符串 str 内 "始于位置 stridx" 的部分当作字符串的初值
- ) string s(str, stridx, strlen) ; // 将字符串 str 内 "始于 stridx 且长度顶多 strlen" 的部分作为字符串的初值
- ) string s(cstr) ; // 将 C 字符串 (以 NULL 结束) 作为 s 的初值
- ) string s(chars, chars_len) ; // 将 C 字符串前 chars_len 个字符作为字符串 s 的初值.
- ) string s(num, 'c') ; // 生成一个字符串, 包含 num 个 c 字符
- ) string s("value"); string s="value"; // 将 s 初始化为一个字符串字面值副本
- ) string s(begin, end); // 以区间 begin/end(不包含 end)内的字符作为字符串 s 的初值
- ) s.~string(); // 销毁所有字符, 释放内存
2,string 与 C 字符数组的比较
string 串要取得其中某一个字符, 和传统的 C 字符串一样, 可以用 s[i]的方式取得. 比较不一样的是如果 s 有三个字符, 传统 C 的字符串的 s[3]是'\0'字符, 但是 C++ 的 string 则是只到 s[2]这个字符而已.
1,C 风格字符串
用 "" 括起来的字符串常量, C++ 中的字符串常量由编译器在末尾添加一个空字符;
末尾添加了'\0'的字符数组, C 风格字符串的末尾必须有一个'\0'.
2,C 字符数组及其与 string 串的区别
- char ch[ ]={
- 'C', '+', '+'
- }; // 末尾无 NULL
- char ch[ ]={
- 'C', '+', '+', '\0'
- }; // 末尾显式添加 NULL
- char ch[ ]="C++"; // 末尾自动添加 NULL 字符 若 [ ] 内数字大于实际字符数, 将实际字符存入数组, 其余位置全部为'\0'.?
3,string 对象的操作
- string s;
- 1) s.empty(); // s 为空串 返回 true
- 2) s.size(); // 返回 s 中字符个数 类型应为: string::size_type
- 3) s[n]; // 从 0 开始相当于下标访问
- 4) s1+s2; // 把 s1 和 s2 连接成新串 返回新串
- 5) s1=s2; // 把 s1 替换为 s2 的副本
- 6) v1==v2; // 比较, 相等返回 true
7) !=, <, <=,>,>= 惯有操作 任何一个大写字母都小于任意的小写字母
当进行 string 对象和字符串字面值混合连接操作时,+ 操作符的左右操作数必须至少有一个是 string 类型的:
- string s1("hello");
- string s3=s1+"world"; // 合法操作
- string s4="hello"+"world"; // 非法操作: 两个字符串字面值相加
4, 字符串操作函数
1,string 类函数
- ) =, s.assign() // 赋以新值?
- ) swap() // 交换两个字符串的内容?
- ) +=, s.append(), s.push_back() // 在尾部添加字符?
- ) s.insert() // 插入字符?
- ) s.erase() // 删除字符?
- ) s.clear() // 删除全部字符?
- ) s.replace() // 替换字符?
- ) + // 串联字符串?
- ) ==,!=,<,<=,>,>=,compare() // 比较字符串?
- ) size(),length() // 返回字符数量?
- ) max_size() // 返回字符的可能最大个数?
- ) s.empty() // 判断字符串是否为空?
- ) s.capacity() // 返回重新分配之前的字符容量?
- ) reserve() // 保留一定量内存以容纳一定数量的字符?
- ) [ ], at() // 存取单一字符?
- )>>,getline() // 从 stream 读取某值?
- ) <<// 将谋值写入 stream?
- ) copy() // 将某值赋值为一个 C_string?
- ) c_str() // 返回一个指向正规 C 字符串 (C_string) 的指针 内容与本 string 串相同 有'\0'?
- ) data() // 将内容以字符数组形式返回 无'\0'?
- ) s.substr() // 返回某个子字符串?
- ) begin() end() // 提供类似 STL 的迭代器支持?
- ) rbegin() rend() // 逆向迭代器?
- ) get_allocator() // 返回配置器
2, 函数说明
- 1,s.assign();
- s.assign(str); // 不说
- s.assign(str,1,3); // 如果 str 是 "iamangel" 就是把 "ama" 赋给字符串
- s.assign(str,2,string::npos); // 把字符串 str 从索引值 2 开始到结尾赋给 s
- s.assign("gaint"); // 不说
- s.assign("nico",5); // 把'n' 'I' 'c' 'o' '\0'赋给字符串
- s.assign(5,'x'); // 把五个 x 赋给字符串
2, 大小和容量函数
一个 C++ 字符串存在三种大小:?
1) 现有的字符数, 函数是 s.size()和 s.length(), 他们等效. s.empty()用来检查字符串是否为空.?
2) max_size(); 这个大小是指当前 C++ 字符串最多能包含的字符数, 很可能和机器本身的限制或者字符串所在位置连续内存的大小有关系.?
3) capacity()重新分配内存之前 string 所能包含的最大字符数.?
这里另一个需要指出的是 reserve()函数, 这个函数为 string 重新分配内存. 重新分配的大小由其参数决定, 默认参数为 0, 这时候会对 string 进行非强制性缩减.
3, 元素存取
我们可以使用下标操作符 [] 和函数 at()对元素包含的字符进行访问. 但是应该注意的是操作符 [] 并不检查索引是否有效 (有效索引 0~str.length()), 如果索引失效, 会引起未定义的行为. 而 at() 会检查, 如果使用 at()的时候索引无效, 会抛出 out_of_range 异常.?
有一个例外不得不说, const string a; 的操作符 [] 对索引值是 a.length()仍然有效, 其返回值是'\0'. 其他的各种情况, a.length()索引都是无效的.
4, 比较函数
C ++ 字符串支持常见的比较操作符(>,>=,<,<=,==,!=), 甚至支持 string 与 C-string 的比较(如 str<"hello"). 在使用>,>=,<,<= 这些操作符的时候是根据 "当前字符特性" 将字符按字典顺序进行逐一的比较. 字典排序靠前的字符小, 比较的顺序是从前向后比较, 遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小.?
另一个功能强大的比较函数是成员函数 compare(). 他支持多参数处理, 支持用索引值和长度定位子串来进行比较. 他返回一个整数来表示比较结果, 返回值意义如下: 0 - 相等 ,>0 - 大于,<0 - 小于.
5, 插入字符
也许你需要在 string 中间的某个位置插入字符串, 这时候你可以用 insert()函数, 这个函数需要你指定一个安插位置的索引, 被插入的字符串将放在这个索引的后面.?
- s.insert(0,"my name");?
- s.insert(1,str);?
这种形式的 insert()函数不支持传入单个字符, 这时的单个字符必须写成字符串形式. 为了插入单个字符, insert()函数提供了两个对插入单个字符操作的重载函数:?
insert(size_type index, size_type num, chart c)和 insert(iterator pos, size_type num, chart c).?
其中 size_type 是无符号整数, iterator 是 char*, 所以, 你这么调用 insert 函数是不行的:?
insert(0, 1, 'j'); 这时候第一个参数将转换成哪一个呢??
所以你必须这么写: insert((string::size_type)0, 1, 'j')!?
第二种形式指出了使用迭代器安插字符的形式.
6, 提取子串 s.substr()
- s.substr(); // 返回 s 的全部内容
- s.substr(11); // 从索引 11 往后的子串
- s.substr(5,6); // 从索引 5 开始 6 个字符
5, 字符串流 stringstream 操作
Iostream 标准库支持内存中的输入输出, 只要将流与存储在程序内存中的 string 对象捆绑起来即可. 此时, 可使用 iostream 输入和输出操作符读写这个 stream 对象. 使用 stringstream, 我们必须包含头文件 #include.
1,string s
1)>>操作符 // 用于从 istream 对象中读入输入
2) is>> s; // 从输入流 is 中读取一个以空白字符分割的字符串, 写入 s
3) <<操作符 // 用于把输出写到 ostream 对象中
- ) os <<s; // 将 s 写到输出流 os 中
- ) getline(is, s); // 从输入流 is 中读取一行字符, 写入 s, 直到遇到分行符或到了文件尾
- ) istream // 输入流 提供输入操作
- ) ostream // 输出流 提供输出操作
2,stringstream 特定的操作
- ) stringstream strm; // 创建自由的 stringstream 对象
- ) stringstream strm(s); // 创建存储 s 的副本的 stringstream 对象, s 是 stringstream 类型
- ) strm.str(); // 返回 strm 中存储的 string 类型对象
- ) strm.str(s); // 将 string 类型的 s 复制给 strm 返回 void
3,string 到 int 的转换
stringstream 通常是用来做数据转换的, 如果你打算在多次转换中使用同一个 stringstream 对象, 记住在每次转换前要使用 clear()方法. 在多次转换中重复使用同一个 stringstream(而不是每次都创建一个新的对象)对象最大的好处在于效率. stringstream 对象的构造和析构函数通常是非常耗费 CPU 时间的.?
string 到 int 的转换(与其他类型间的转换一样大同小异):
- string result="10000";
- int n=0;
- stream<<result;
- stream>>n; // n 等于 10000
6,C 字符串, string 串, stringstream 之间的关系
首先必须了解, string 可以被看成是以字符为元素的一种容器. 字符构成序列 (字符串). 有时候在字符序列中进行遍历, 标准的 string 类提供了 STL 容器接口. 具有一些成员函数比如 begin(),end(), 迭代器可以根据他们进行定位. 注意, 与 char 不同的是, string 不一定以 NULL('\0') 结束. string 长度可以根据 length()得到, string 可以根据下标访问. 所以, 不能将 string 直接赋值给 char.
1,string 转换成 const char 如果要将字面值 string 直接转换成 const char 类型. string 有 2 个函数可以运用: 一个是. c_str(), 一个是 data 成员函数.?
c_str()函数返回一个指向正规 C 字符串的指针, 内容与本 string 串相同. 这是为了与 C 语言兼容, 在 C 语言中没有 string 类型, 故必须通过 string 类对象的成员函数 c_str()把 string 对象转换成 C 中的字符串样式. 注意: 一定要使用 strcpy()函数等来操作方法 c_str()返回的指针
- string str = "Hello World";
- const char ch1 = str.c_str();
- const charch2 = str.data();
此时, ch1 与 ch2 的内容将都是 "Hello World". 但是只能转换成 const char*, 如果去掉 const 编译不能通过.
2,string 转换成 char C++ 提供的由 C++ 字符串得到对应的 C_string 的方法是使用 data(),c_str()和 copy(), 其中?
1) data()以字符数组的形式返回字符串内容, 但并不添加'\0'.?
2) c_str()返回一个以'\0'结尾的字符数组, 返回值是 const char.?
3) copy()则把字符串的内容复制或写入既有的 c_string 或字符数组内.?
C++ 字符串并不以'\0'结尾. 我的建议是在程序中能使用 C++ 字符串就使用, 除非万不得已不选用 c_string.?
如果要转换成 char*, 可以用 string 的一个成员函数 strcpy 实现.
- string str = "Hello World";
- int len = str.length();
- char data = new char[len+1]; // 这里 + 1 还是不 + 1 需要注意
- strcpy(data, str.c_str()); // const chardata = new char[len+1]; strcpy(data, str);
此时, data 中的内容为 "Hello World" 使用 c_str()要么 str 赋给一个 const 指针, 要么用 strcpy()复制.
3,char * 转换成 string
string 类型能够自动将 C 风格的字符串转换成 string 对象:
- string str;
- const char *pc = "Hello World";
- str = pc;
- printf("%s\n", str); // 此处出现错误的输出
- cout<<str<<endl;
不过这个是会出现问题的. 有一种情况我要说明一下. 当我们定义了一个 string 类型之后, 用 printf("%s",str); 输出是会出问题的. 这是因为 "%s" 要求后面的对象的首地址. 但是 string 不是这样的一个类型. 所以肯定出错.?
用 cout 输出是没有问题的, 若一定要 printf 输出. 那么可以这样:
printf("%s",str.c_str());
4,char[ ] 转换成 string
这个与 char * 的情况相同, 也可以直接赋值, 但是也会出现上面的问题, 需要同样的处理.?
字符数组转化成 string 类型:
- char ch [] = "ABCDEFG";
- string str(ch); // 也可 string str = ch;
或者
- char ch [] = "ABCDEFG";
- string str;
- str = ch; // 在原有基础上添加可以用 str += ch;
5,string 转换成 char[ ]
string 对象转换成 C 风格的字符串:
const char *str = s.c_str();
这是因为为了防止字符数组被程序直接处理 c_str()返回了一个指向常量数组的指针.?
由于我们知道 string 的长度可以根据 length()函数得到, 又可以根据下标直接访问, 所以用一个循环就可以赋值了, 这样的转换不可以直接赋值.
- string str = "Hello World";
- int len=str.length();
- char ch[255]={
- };
- for( int i=0;i<str.length();i++)
- ch[i] = str[i];
- ch[len+1] = '\0';
- printf("%s\n", ch);
- cout<<ch<<endl;
6,stringstream 与 string 间的绑定
- stringstream strm;
- string s;
- strm<<s; // 将 s 写入到 strm
- strm>>s; // 从 strm 读取串写入 s
- strm.str(); // 返回 strm 中存储的 string 类型对象
- strm.str(s); // 将 string 类型的 s 复制给 strm 返回 void
- char* cstr; // 将 C 字符数组转换成流
- string str(cstr);
- stringstream ss(str);
来源: http://www.bubuko.com/infodetail-3046224.html