可变长字符序列,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当中,返回osis >> s; // 从is中读取字符串赋给s,以空白分隔,返回isgetline(is, s); // 从is中读取一行赋给s,返回iss.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个字符cs.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个字符cstring& 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个字符cstring& 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默认=0s2,pos // 从s中pos位置查找字符串s2,pos默认=0cp,pos // 从s中pos位置查找cp字符串,空字符结尾,pos默认=0cp,pos,n // 从s中pos位置查找cp字符串前n个字符,pos、n无默认值
七、substr子串
s.substr(pos,n); // 返回子串,pos开始n个字符拷贝。// pos默认0,n默认s.size()-poss.substr(); // 全部的拷贝s.substr(pos); // pos开始的全部拷贝
八、compare
除了关系运算符之外,还有compare比较操作,类似C的strcmp逐个比较字符,等于返回0,>返回正,<返回负
s.compare(s1); // 比较s和s1s.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: 转换基数,默认10int 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 是大写字母,输出对应的小写字母:否则原样输出 ctoupper(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中 |
