可变长字符序列,C++的“字符串”,定义在std命名空间中。C风格字符串是以空字符结尾的字符数组,这是一种原始蛋疼的设计,易导致内存越界。在C++代码中,应尽量用string替换C风格字符串。
这里只介绍string的特有操作,string是顺序容器,所以string支持所有顺序容器的特性。
string是顺序容器,支持顺序容器的所有操作。
一、初始化、赋值
string s1; // 默认初始化,s1是一个空串
string s2(s1); // s2是s1的副本
string s2 = s1; // 等价于s2(s1)
s2 += s1; // s1的副本拼接到s2结尾。
//n、len2和pos2都是无符号值
//cp:const char*
string s(cp, n); // cp数组中前n的拷贝。此数组至少应该包含n个字符
string s(s2, pos2); // 从s2的下标pos2开始的拷贝。
string s(s2, pos2, len2); // s2的下标pos2开始的最多len2个字符拷贝,len2超了不影响。
/******************例子**********************/
string s3 = "value"; // 等价于s3("value"), s3是字面值'value"的副本
// 为了兼容C,"value"(字符串字面值)不是string对象。
string s3("value"); // "value"的副本,这是C++的字符串,没有最好的空字符。
string s4(n, 'c'); // 把s4初始化为由n个字符c组成的串
string s3 = s1 + ", " + s2 + ' \n '; // +号的至少有一边是string类型
string s5 = string("asdfasdfasd"); // 不推荐,构建了临时string对象。
const char *cp = "Hello World!!!"; // 以空字符结束的数组
char noNull[] = {'H', 'i'); // 不是以空字符结束
string s1(cp); // 拷贝,直到空字符
string s2(noNull, 2); // 拷贝2个字符, s2 == "Hi"
string s3(noNull); // 未定义行为: noNull 不是以空字符结束
string s4(cp + 6, 5); // 从 cp[6] 开始拷贝 5 个字符; s4 == "World"
string s5(s1, 6, 5); // 从 s1[6] 开始拷贝 5 个字符; s5 == "World"
string s6(s1, 6); // 从 s1[6] 开始拷贝,直至 s1 末尾; s6 =="World!!!"
string s7(s1, 6, 20); // 正确 , 只拷贝到 s1 末尾; s7 =="World!!! "
string s8(s1, 16); // 抛出一个 out_of_range 异常
二、基本操作
string s;
os << s; // 将s写到输出流os当中,返回os
is >> s; // 从is中读取字符串赋给s,以空白分隔,返回is
getline(is, s); // 从is中读取一行赋给s,返回is
s.empty(); // s为空,返回true,否则返回false
// size_type:无符号类型,足够表示string长度,机器无关。
// 请使用标准库定义的数值类型,不要使用内置基本类型。
string::size_type i = s.size(); // 返回 s 中字符的 个数
auto i = s.size();
int i = s.size(); // 不可取!无符号类型赋值给有符号类型
unsigned int i = s.size(); // 也不可取!无符号类型范围不确定相同。
const char* cstr = s.c_str(); // 返回C风格字符串
// cstr可能因为s的改变而失效,代码不可取,最好进行拷贝。
s[n]; // 返回 s 中第 n 个字符的引用,位置 n 从 0 计起
s1 + s2; // 返回 s1 和 s2 连接后的结果
s1 = s2; // 用 s2 的副本代替 s1 中原来的字符
s1 == s2; // 字符是否相同
s1 != s2; // 等性判断对字母的大小 写敏感
<, <= , > , >= // 字典顺序比较,对字母的大小写敏感
三、插入、追加
// 在pos位置处插入后续参数的字符
string& s.insert(pos, str); // str的拷贝
string& s.insert(pos1,str, pos2, len); // str中从pos2开始最多len个的拷贝
string& s.insert(pos, cp, len); // cp前最多len个的拷贝
string& s.insert(pos, cp); // pos位置开始插入cp_n指针到空字符部分的字符。
string& s.insert(pos, n, c); // n个字符c
// 在s的迭代器iter位置处插入后续参数的字符
// 返回插入的第1个字符的迭代器
s.insert(iter, n, c); // pos开始,插入n个字符c
s.insert(iter, b, e); // b、e范围的字符,b、e不能是指向s的
s.insert(iter, {...}); //
// s尾部追加内容
string& s.append(str); // 追加str的拷贝
string& s.append(str,pos2,len); // 追加str中从pos2开始最多len个的拷贝
string& s.append(cp,len); // 追加cp字符串数组前最多len个的拷贝
string& s.append(cp); // 追加cp字符数组拷贝,空字符结尾
string& s.append(n,c); // 追加n个字符c
string& s.append(b, e); // 追加范围
string& s.append({...}); // 追加范围
s.insert(s.size(), 5, '!'); // 在s末尾插入5个感叹号
const char *cp = "Stately, plump Buck";
s.assign(cp, 7); // s == "Stately"
s.insert(s.size(), cp + 7); // s == "Stately, Plump Buck"
四、删除
string& s.erase(pos,len); //pos开始,删除len个
string& s.erase(pos); //pos开始全部删除
s.erase(s.size() - 5, 5); //从s删除最后5个字符
五、替换
// 全部替换
string& s.assign(str); // 替换为str的拷贝
string& s.assign(str,pos2,len); // 替换为str中从pos2开始最多len个的拷贝
string& s.assign(cp,len); // 替换为cp字符串数组前最多len个的拷贝
string& s.assign(cp); // 替换为cp字符数组拷贝,空字符结尾
string& s.assign(n,c); // 替换为n个字符c
string& s.assign(b, e); // 范围替换
string& s.assign({...}); // 范围替换
const char *cp = "Stately, plump Buck";
s.assign(cp, 7); // s == "Stately"
// 部分替换
// 先删除pos开始len个字符,再替换为后续参数的指定字符
string& s.replace(pos,len,str); // str的拷贝
string& s.replace(pos,len,str,pos2,len); // str中从pos2开始最多len个的拷贝
string& s.replace(pos,len,cp,len); // cp前最多len个的拷贝
string& s.replace(pos,len,cp); // cp字符数组拷贝,空字符结尾
string& s.replace(pos,len,n,c); // n个字符c的拷贝
// 先删除b、e范围字符,再替换为后续参数的指定字符
string& s.replace(b,e,str); // str的拷贝
string& s.replace(b,e,cp,len); // cp前最多len个的拷贝
string& s.replace(b,e,cp); // cp字符数组拷贝,空字符结尾
string& s.replace(b,e,n,c); // n个字符c的拷贝
string& s.replace(b,e,b, e); // 迭代范围拷贝
string& s.replace(b,e,{...}); // 初始值列表拷贝
六、搜索
// 搜索指定字符args出现的下标并返回,未找到则返回npos
// args的格式在下面。
s.find(args) // 查找第一次出现的位置
s.rfind(args) // 查找最后一次出现的位置
s.find_first_of(args) // 查找任何一个字符第一次出现的位置
s.find_last_of(args) // 查找任何一个字符最后一次出现的位置
s.find_first_not_of(args) // 查找第一个不在args中的字符
s.find_last_not_of(args) // 查找最后一个不在args中的字符
// args的格式:
c,pos // 从s中pos位置查找字符c,pos默认=0
s2,pos // 从s中pos位置查找字符串s2,pos默认=0
cp,pos // 从s中pos位置查找cp字符串,空字符结尾,pos默认=0
cp,pos,n // 从s中pos位置查找cp字符串前n个字符,pos、n无默认值
七、substr子串
s.substr(pos,n); // 返回子串,pos开始n个字符拷贝。
// pos默认0,n默认s.size()-pos
s.substr(); // 全部的拷贝
s.substr(pos); // pos开始的全部拷贝
八、compare
除了关系运算符之外,还有compare比较操作,类似C的strcmp逐个比较字符,等于返回0,>返回正,<返回负
s.compare(s1); // 比较s和s1
s.compare(pos,n,s1); // 将s的pos开始n个字符与s1进行比较
s.compare(posl,nl,s2,pos2,n2); // 类似上面
s.compare(cp); // cp是空字符结尾的字符数组
s.compare(pos,n,cp); // 将s的pos开始n个字符与cp进行比较
s.compare(pos,n,cp,n1); // 将s的pos开始n个字符与cp的前n1个字符进行比较
九、与数值转换
数值转string
// 针对不同类型数值,有一组重载函数
// 小整型会被提升(如char -> int)
string to_string(val);
string转数值
/****************string转整型**********************/
//返回s起始子串(能转成整型)的数值。可能无法全部转换成功。
// s: string
// p: size_t的指针,保存s中第1个非数值字符下标
// b: 转换基数,默认10
int stoi(s, p, b);
long stol(s, p, b);
unsigned long stoul(s, p, b);
long long stoll(s, p, b);
unsigned long long stoull(s, p, b);
string s = "123abc";
string::size_type pos;
int ret = stoi(s, pos); //ret = 123,pos = 3
/****************string转浮点**********************/
float stof(s, p);
double stod(s, p);
long double stold(s, p);
十、字符操作
// 在cctype头文件中
isalnum(c) // 当 c 是字母或数字时为真
isalpha(c) // 当 c 是字母 时为 真
iscntrl(c) // 当 c 是控制字符 时为真
isdigit(c) // 当 c 是数字 时为 真
isgraph(c) // 当 c 不是空格但可打 印时为真
islower(c) // 当 c 是小写字母时为真
isprint(c) // 当 c 是可打印字符时为真(即 c 是空格或 c 具有可视形式)
ispunct(c) // 当 c 是标点符号时为真( 即 c 不是控制字符、数字、
// 字母、可打印 空白 中的一种)
isspace(c) // 当 c 是空白时为真(即 c 是空格、横向制表符、
// 纵向制表符、回车符、换行符、进纸符中的 一种)
isupper(c) // 当 c 是大写字母时为真
isxdigit(c) // 当 c 是十六进制数字 时为 真
tolower(c) // 如果 c 是大写字母,输出对应的小写字母:否则原样输出 c
toupper(c) // 如果 c 是小 写字母 ,输出对应的大写字母:否 则原样输出 c
string str("some string");
for (auto &c : str)
cout << c << endl; //输出str中每个字符
for (auto &c : str)
c = toupper(c); //把str每个字符大写
// 将第一个单词大写:标准C++式写法
for (decltype(s.size()) index = 0;index != s.size() && !isspace(s[index]); ++index)
s[index] = toupper(s[index]) ;
// 典型C式代码,不可取
for(int index = 0; index != s.size(); index++);
十一、string实现原理
十二、C++头文件对比
C/C++ 头文件对比 | |
---|---|
C | C++ |
name.h | cname |
ctype.h | cctype |
C++标准库中的名字基本都在std中 |