C++ string类型小结
- 构造函数
- string.append()
- string.assign()
- string.at()
- string.back()
- string.begin()
- string.capasity()
- string.cbegin()
- string.clear()
- string.compare()
- string.copy()
- string.crbegin()
- string.c_str()
- string.data()
- string.empty()
- string.erase()
- string.find()
- string.find_first_not_of(str)
- string.find_first_of(str)
- string.find_last_not_of(str)
- string.find_last_of(str)
- string.front()
- string.get_allocator()
- string.insert()
- string.length()
- string.max_size()
- string.operator+=
- string.operator=
- string.operator[]
- string.pop_back()
- string.push_back()
- string.rbegin()
- string.replace()
- string.reserve()
- string.resize()
- string.rfind()
- string.shrink_to_fit()
- string.size()
- string.substr()
- string.swap()
- [string.npos]
- getline(string)
- relational operators(string)
参考 权威网站
左边的目录列举了关于string的 一些 成员。
构造函数
默认 string();
从已有复制 string (const string& str);
从已有剪辑 string (const string& str, size_t pos, size_t len = npos);
从字符数组录入 string (const char* s);
从字符数组录入n位
string (const char* s, size_t n);
用字符填充
string (size_t n, char c);
从迭代器填充
template <class InputIterator>
string (InputIterator first, InputIterator last);
析构函数:就普通析构函数没什么好讲的你又用不到
string.append()
在已有字符串后面添加字符串
正常的添加 string& append (const string& str);
截取后添加 string& append (const string& str, size_t subpos, size_t sublen);
用字符数组添加 string& append (const char* s);
截取字符数组添加 string& append (const char* s, size_t n);
string& append (const char* s, size_t subpos, size_t sublen)
添加单一字符 string& append (size_t n, char c);
用迭代器添加
template <class InputIterator>
string& append (InputIterator first, InputIterator last);
而且这个函数不仅调用可以改变字符串,也可以直接返回改变后的字符串
cout << a.append("lover!");
这样既改变了a同时也可以直接输出改变后的a
string.assign()
重新构造字符串,跟构造函数是一样的但是你用不了构造函数只能来用这个
默认 string& assign (const string& str);
截取 string& assign (const string& str, size_t subpos, size_t sublen);
字符数组 string& assign (const char* s);
截取字符数组 string& assign (const char* s, size_t n);
string& assign(const char* s, size_t subpos, size_t sublen);
单一字符填充
string& assign (size_t n, char c);
迭代器填充
template <class InputIterator>
string& assign (InputIterator first, InputIterator last);
string.at()
返回字符串某个位置的字符
char& at (size_t pos);
const char& at (size_t pos) const;
(好像上下两个没什么区别嘛……)
注意这里是从0开始的。
如果你给的数字大于该字符串的长度,就会抛出out_of_range类型异常
string.back()
c++11 only
返回的是字符串最后一个字符的引用
char& back();
const char& back() const;
但是正常编译的版本好像没有这个功能……需要加上-std=c++11编译选项。
string.begin()
string.end()
返回第一个字符的迭代器
iterator begin();
const_iterator begin() const;
权威网站举了个例子
int main ()
{
std::string str ("Test string");
for ( std::string::iterator it=str.begin(); it!=str.end(); ++it)
std::cout << *it;
std::cout << '\n';
return 0;
}
迭代器是可以自增的,曾经也有某位大佬写过迭代器,在篇文章中用浏览器的搜索功能搜索“迭代器”就可以找到
string.capasity()
返回的是string所占的内存空间。用字节表示
size_t capacity() const;
他没什么用因为他的返回值只是不小于字符串长度
// comparing size, length, capacity and max_size
int main ()
{
std::string str ("Test string");
std::cout << "size: " << str.size() << "\n";
std::cout << "length: " << str.length() << "\n";
std::cout << "capacity: " << str.capacity() << "\n";
std::cout << "max_size: " << str.max_size() << "\n";
return 0;
}
可能会输出
size: 11
length: 11
capacity: 15
max_size: 429496729
string.cbegin()
c++11 only
// string::cbegin/cend
int main ()
{
std::string str ("Lorem ipsum");
for (auto it=str.cbegin(); it!=str.cend(); ++it)
std::cout << *it;
std::cout << '\n';
return 0;
}
(真是的用string.begin()和string.end()不好吗)
string.clear()
清空字符串
int main ()
{
char c;
std::string str;
std::cout << "Please type some lines of text. Enter a dot (.) to finish:\n";
do {
c = std::cin.get();
str += c;
if (c=='\n')
{
std::cout << str;
str.clear();
}
} while (c!='.');
return 0;
}
string.compare()
比较当前字符串和给定字符串
默认的全文比较 int compare (const string& str) const;
默认的截取比较 int compare (size_t pos, size_t len, const string& str) const;
这里的截取是a.compare(size_t pos, size_t len, const string& str) 截取a从pos后的第len位和整个str比较
都可以的截取比较 int compare (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen) const;
截取a从pos后的len位和str从subpos后的sublen为进行比较
然后就是把所有的string类型改成char* 类型
int compare (const char* s) const;
int compare (size_t pos, size_t len, const char* s) const;
然后由于你传入char* 所以是没有subpos的,只有sublen,也就是截取前n位和你比较
int compare (size_t pos, size_t len, const char* s, size_t n) const;
返回值:
str.compare(cmp_str);
0:两个字符串相等
<0:str比cmp_str小
>0:str比cmp_str大
这里的字符串的大小定义是:
小:从前往后第一个不相同的字符,str比cmp_str的字典序小,也就是找到最小的i,使得str[i]!=cmp_str[i],然后再比较字典序。或者str是cmp_str的前缀
大:除了小和等的情况外的所有情况(废话)
复杂度:线性
异常:如果指定长度大于字符串长度,会抛出out_of_range类型异常
string.copy()
复制字符串
size_t copy (char* s, size_t len, size_t pos = 0) const;
a.copy(s, len, pos)表示把a从pos后len位复制到s。注意s才是被覆盖的那个。
返回成功复制的长度。
会抛出out_of_range类型异常
string.crbegin()
string.crend()
c++11 only
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
返回的是关于string的迭代器const_reverse_iterator,就是反向迭代器。返回的crbegin()其实就是字符串结尾,crend()就是字符串开头
这个迭代器的运算规则也是反向的,也就是it=crbegin(); it++其实是反向增加,也就是逆序遍历
权威网站给了一个逆向输出的代码
int main ()
{
std::string str ("lorem ipsum");
for (auto rit=str.crbegin(); rit!=str.crend(); ++rit)
std::cout << *rit;
std::cout << '\n';
return 0;
}
(真是的用begin和end会死啊)
string.c_str()
把string类型的变量转变为char*类型
const char* c_str() const;
有很多c++的函数要求传入的参数都是const char, 也就是字符数组。
string虽然被称为字符串类型,但是和const char 却不是同一个类型。所以string里面就有这样一个成员函数,把string类型存储的字符串转换为字符数组类型。
string.data()
const char* data() const;
(这东西和c_str()有区别吗)
string.empty()
告诉你这个字符串是不是为空(也就是长度是否为0)
bool empty() const;
string.erase()
删除本字符串的一部分,剪短他的长度
sequence (1)
string& erase (size_t pos = 0, size_t len = npos);
character (2)
iterator erase (iterator p);
range (3)
iterator erase (iterator first, iterator last);
- sequence
这里传入了默认参数,如果什么都没有就会删掉整个字符串。
如果只有一个参数就是默认先填充第一个参数,也就是起始位置,从你给的位置一路删除到末尾。
如果有俩参数,就是正常的从pos一路删除len位
返回删除后的字符串的引用。 - character
传入一个迭代器,删除这个迭代器指向的字符
返回删除后迭代器指向的字符。
如果我们用字符数组来表示字符串的话,删除了char[5],那么删除之后因为字符串还要连续那么char[6]就会补上来,所以返回的字符就是原来的char[6] - range
用俩迭代器来表示一个范围,删除这个范围内的所有字符。
然后返回这个范围的下一个字符。
如果删除[begin,end)的话,那么返回的便是原来的char[end]
(自己去写代码验证一下啊?)
string.find()
string (1)
size_t find (const string& str, size_t pos = 0) const;
c-string (2)
size_t find (const char* s, size_t pos = 0) const;
buffer (3)
size_t find (const char* s, size_t pos, size_t n) const;
character (4)
size_t find (char c, size_t pos = 0) const;
- string
寻找str,从第pos位开始。
a.find(b,pos);这个pos是指a的pos,把a从pos开始找。
找到的是原字符串中的位置 - c_str
很正常的字符数组。 - buffer
截取s的前n位和a比较,pos和第一个函数的用法一样。 - character
找到一个字符。
时间复杂度:未定义,但应该在两个要匹配的长度相乘上线性。
string.find_first_not_of(str)
从当前字符里找到第一个不在str里面的字符。
string (1)
size_t find_first_not_of (const string& str, size_t pos = 0) const;
c-string (2)
size_t find_first_not_of (const char* s, size_t pos = 0) const;
buffer (3)
size_t find_first_not_of (const char* s, size_t pos, size_t n) const;
character (4)
size_t find_first_not_of (char c, size_t pos = 0) const;
在当前string里面找到第一个不在给定字符串str里面的字符并返回它的位置
pos表示忽略当前字符串的前pos-1位(从第pos位开始考虑,pos也包括进去了)
n就是取字符数组的前n位。
时间复杂度:未定义,应该是两个要匹配的字符串长度相乘
string.find_first_of(str)
...直译:在当前字符串中找到第一个在给定字符串str中的字符
string (1)
size_t find_first_of (const string& str, size_t pos = 0) const;
c-string (2)
size_t find_first_of (const char* s, size_t pos = 0) const;
buffer (3)
size_t find_first_of (const char* s, size_t pos, size_t n) const;
character (4)
size_t find_first_of (char c, size_t pos = 0) const;
用法和上面那个一样。
string.find_last_not_of(str)
string.find_last_of(str)
...直译...
string.front()
c++11 only
返回字符串第一个字符的引用
char& front();
const char& front() const;
string.get_allocator()
string.insert()
插入
string (1)
// 在pos位置插入str
string& insert (size_t pos, const string& str);
substring (2)
// 截取str的[subpos,subpos+sublen)插入到str的pos位置
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
c-string (3)
// 在pos位置插入s
string& insert (size_t pos, const char* s);
buffer (4)
// 在pos位置插入s的前n位
string& insert (size_t pos, const char* s, size_t n);
fill (5)
// 在pos位置插入n个c
string& insert (size_t pos, size_t n, char c);
// 在p的迭代器后面插入n个c
void insert (iterator p, size_t n, char c);
single character (6)
// 在p迭代器后面插入字符c
iterator insert (iterator p, char c);
range (7)
// 在p迭代器后面插入[first, last)迭代器之间的字符
template <class InputIterator>
void insert (iterator p, InputIterator first, InputIterator last);
参考权威网站提供的代码
// inserting into a string
#include <iostream>
#include <string>
int main ()
{
std::string str="to be question";
std::string str2="the ";
std::string str3="or not to be";
std::string::iterator it;
// used in the same order as described above:
str.insert(6,str2); // to be (the )question
str.insert(6,str3,3,4); // to be (not )the question
str.insert(10,"that is cool",8); // to be not (that is )the question
str.insert(10,"to be "); // to be not (to be )that is the question
str.insert(15,1,':'); // to be not to be(:) that is the question
it = str.insert(str.begin()+5,','); // to be(,) not to be: that is the question
str.insert (str.end(),3,'.'); // to be, not to be: that is the question(...)
str.insert (it+2,str3.begin(),str3.begin()+3); // (or )
std::cout << str << '\n';
return 0;
}
时间复杂度:未定义,但应该和新字符串的长度成线性。
string.length()
返回当前字符串的长度
size_t length() const;
string.max_size()
返回当前系统下字符串可以到达的最大长度。
size_t max_size() const;
string.operator+=
首先肯定要知道也有+这个重载运算符的
就是用来连接俩字符串
string (1)
string& operator+= (const string& str);
c-string (2)
string& operator+= (const char* s);
character (3)
string& operator+= (char c);
这个……看函数原型就知道了把……
给出经过个人修改的权威网站的样例代码:
// string::operator+=
#include <iostream>
#include <string>
int main ()
{
std::string name ("John");
std::string family ("Smith");
name + " K. "; // c-string
name += family; // string
name += '\n'; // character
std::cout << name;
return 0;
}
时间复杂度:未定义,但应该和新字符串的长度成线性。
string.operator=
很简单的一个赋值语句
string (1)
string& operator= (const string& str);
c-string (2)
string& operator= (const char* s);
character (3)
string& operator= (char c);
string.operator[]
从此之后你可以像访问字符数组那样用下标来访问字符串。
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
string.pop_back()
c++11 only
删除字符串的最后一个字符
void pop_back()
string.push_back()
增加一个字符
void push_back(char c);
比如这样:
// string::push_back
#include <iostream>
#include <fstream>
#include <string>
int main ()
{
std::string str("b");
str.push_back('a');
std::cout << str << '\n';
return 0;
}
string.rbegin()
string.rend()
反过来遍历……这个和crbegin是一样的
// string::rbegin/rend
#include <iostream>
#include <string>
int main ()
{
std::string str ("now step live...");
for (std::string::reverse_iterator rit=str.rbegin(); rit!=str.rend(); ++rit)
std::cout << *rit;
return 0;
}
string.replace()
用给定字符串来代替原字符串里面的一些内容
// 用str来代替[pos,pos+len)之间的字符
// str的长度不受len的限制
string& replace (size_t pos, size_t len, const string& str);
// 用str来代替两个迭代器之间的字符
string& replace (iterator i1, iterator i2, const string& str);
substring (2)
// 用str[subpos,subpos+sublen)来代替[pos,pos+len)之间的字符。
string& replace (size_t pos, size_t len, const string& str,
size_t subpos, size_t sublen);
c-string (3)
// 用字符数组来代替
string& replace (size_t pos, size_t len, const char* s);
string& replace (iterator i1, iterator i2, const char* s);
buffer (4)
// 用字符数组的前n个来代替
string& replace (size_t pos, size_t len, const char* s, size_t n);
string& replace (iterator i1, iterator i2, const char* s, size_t n);
fill (5)
// 用n个字符c来代替
string& replace (size_t pos, size_t len, size_t n, char c);
string& replace (iterator i1, iterator i2, size_t n, char c);
range (6)
// 给定字符串str用迭代器来表示。
template <class InputIterator>
string& replace (iterator i1, iterator i2,
InputIterator first, InputIterator last);
贴上来自权威网站的代码
// replacing in a string
#include <iostream>
#include <string>
int main ()
{
std::string base="this is a test string.";
std::string str2="n example";
std::string str3="sample phrase";
std::string str4="useful.";
// replace signatures used in the same order as described above:
// Using positions: 0123456789*123456789*12345 // 这个是对齐给你看字符位置的
std::string str=base; // "this is a test string."
str.replace(9,5,str2); // "this is an example string." (1)
str.replace(19,6,str3,7,6); // "this is an example phrase." (2)
str.replace(8,10,"just a"); // "this is just a phrase." (3)
str.replace(8,6,"a shorty",7); // "this is a short phrase." (4)
str.replace(22,1,3,'!'); // "this is a short phrase!!!" (5)
// Using iterators: 0123456789*123456789* // 这个也是对齐给你看字符位置的。
str.replace(str.begin(),str.end()-3,str3); // "sample phrase!!!" (1)
str.replace(str.begin(),str.begin()+6,"replace"); // "replace phrase!!!" (3)
str.replace(str.begin()+8,str.begin()+14,"is coolness",7); // "replace is cool!!!" (4)
str.replace(str.begin()+12,str.end()-4,4,'o'); // "replace is cooool!!!" (5)
str.replace(str.begin()+11,str.end(),str4.begin(),str4.end());// "replace is useful." (6)
std::cout << str << '\n';
return 0;
}
时间复杂度:未定义,应该在新字符串中成线性。
string.reserve()
不要跟我一样傻乎乎写成了reverse
用来扩容(?)的,给将来的字符串保留更多空间。
void reserve (size_t n = 0);
// string::reserve
#include <iostream>
#include <fstream>
#include <string>
int main ()
{
std::string str("0123");
using std::cout;
using std::endl;
cout<<str.capacity()<<endl;
str.reserve(100);
cout<<str.capacity()<<endl;
return 0;
}
string.resize()
重新调整大小
void resize (size_t n);
void resize (size_t n, char c);
如果n小于当前大小就直接砍掉
如果n大于当前大小就用默认(int)0或者给定字符c填充
string.rfind()
和find的功能一样,只不过从后向前找到第一个
string (1)
// 这里截断还是从截断[0,pos)之间的字符进行判断
size_t rfind (const string& str, size_t pos = npos) const;
c-string (2)
size_t rfind (const char* s, size_t pos = npos) const;
buffer (3)
size_t rfind (const char* s, size_t pos, size_t n) const;
character (4)
size_t rfind (char c, size_t pos = npos) const;
string.shrink_to_fit()
要求字符串通过判断当前储存的长度来智能缩小申请的容量
void shrink_to_fit();
可能说的不是很清楚,运行一下权威网站的代码就知道了。
// string::shrink_to_fit
#include <iostream>
#include <string>
int main ()
{
std::string str (100,'x');
std::cout << "1. capacity of str: " << str.capacity() << '\n';
str.resize(10);
std::cout << "2. capacity of str: " << str.capacity() << '\n';
str.shrink_to_fit();
std::cout << "3. capacity of str: " << str.capacity() << '\n';
return 0;
}
string.size()
你确定这和length不是一个东西?
size_t size() const;
string.substr()
string substr (size_t pos = 0, size_t len = npos) const;
截取并返回当前字符串的[pos,pos+len)
不会修改原字符串。
时间复杂度:未定义,一般和返回的字符串成线性。
string.swap()
和给定字符串交换值,两个字符串的值都会被修改。
void swap (string& str);
时间复杂度:常数
[string.npos]
就是最大长度
unsigned long long 下的-1
static const size_t npos = -1;
getline(string)
(1)
istream& getline (istream& is, string& str, char delim);
(2)
istream& getline (istream& is, string& str);
从输入流is读取一行(以'\n'位分界)字符串保存到str
relational operators(string)
就是一些自定义的重载运算符……大部分都是用来比较的,大小关系在compare函数里面有说明
(1)
bool operator== (const string& lhs, const string& rhs);
bool operator== (const char* lhs, const string& rhs);
bool operator== (const string& lhs, const char* rhs);
(2)
bool operator!= (const string& lhs, const string& rhs);
bool operator!= (const char* lhs, const string& rhs);
bool operator!= (const string& lhs, const char* rhs);
(3)
bool operator< (const string& lhs, const string& rhs);
bool operator< (const char* lhs, const string& rhs);
bool operator< (const string& lhs, const char* rhs);
(4)
bool operator<= (const string& lhs, const string& rhs);
bool operator<= (const char* lhs, const string& rhs);
bool operator<= (const string& lhs, const char* rhs);
(5)
bool operator> (const string& lhs, const string& rhs);
bool operator> (const char* lhs, const string& rhs);
bool operator> (const string& lhs, const char* rhs);
(6)
bool operator>= (const string& lhs, const string& rhs);
bool operator>= (const char* lhs, const string& rhs);
bool operator>= (const string& lhs, const char* rhs);