可变长字符序列,C++的“字符串”,定义在std命名空间中。C风格字符串是以空字符结尾的字符数组,这是一种原始蛋疼的设计,易导致内存越界。在C++代码中,应尽量用string替换C风格字符串。
这里只介绍string的特有操作,string是顺序容器,所以string支持所有顺序容器的特性。

string是顺序容器,支持顺序容器的所有操作

一、初始化、赋值

  1. string s1; // 默认初始化,s1是一个空串
  2. string s2(s1); // s2是s1的副本
  3. string s2 = s1; // 等价于s2(s1)
  4. s2 += s1; // s1的副本拼接到s2结尾。
  5. //n、len2和pos2都是无符号值
  6. //cp:const char*
  7. string s(cp, n); // cp数组中前n的拷贝。此数组至少应该包含n个字符
  8. string s(s2, pos2); // 从s2的下标pos2开始的拷贝。
  9. string s(s2, pos2, len2); // s2的下标pos2开始的最多len2个字符拷贝,len2超了不影响。
  10. /******************例子**********************/
  11. string s3 = "value"; // 等价于s3("value"), s3是字面值'value"的副本
  12. // 为了兼容C,"value"(字符串字面值)不是string对象。
  13. string s3("value"); // "value"的副本,这是C++的字符串,没有最好的空字符。
  14. string s4(n, 'c'); // 把s4初始化为由n个字符c组成的串
  15. string s3 = s1 + ", " + s2 + ' \n '; // +号的至少有一边是string类型
  16. string s5 = string("asdfasdfasd"); // 不推荐,构建了临时string对象。
  17. const char *cp = "Hello World!!!"; // 以空字符结束的数组
  18. char noNull[] = {'H', 'i'); // 不是以空字符结束
  19. string s1(cp); // 拷贝,直到空字符
  20. string s2(noNull, 2); // 拷贝2个字符, s2 == "Hi"
  21. string s3(noNull); // 未定义行为: noNull 不是以空字符结束
  22. string s4(cp + 6, 5); // 从 cp[6] 开始拷贝 5 个字符; s4 == "World"
  23. string s5(s1, 6, 5); // 从 s1[6] 开始拷贝 5 个字符; s5 == "World"
  24. string s6(s1, 6); // 从 s1[6] 开始拷贝,直至 s1 末尾; s6 =="World!!!"
  25. string s7(s1, 6, 20); // 正确 , 只拷贝到 s1 末尾; s7 =="World!!! "
  26. string s8(s1, 16); // 抛出一个 out_of_range 异常

二、基本操作

  1. string s;
  2. os << s; // 将s写到输出流os当中,返回os
  3. is >> s; // 从is中读取字符串赋给s,以空白分隔,返回is
  4. getline(is, s); // 从is中读取一行赋给s,返回is
  5. s.empty(); // s为空,返回true,否则返回false
  6. // size_type:无符号类型,足够表示string长度,机器无关。
  7. // 请使用标准库定义的数值类型,不要使用内置基本类型。
  8. string::size_type i = s.size(); // 返回 s 中字符的 个数
  9. auto i = s.size();
  10. int i = s.size(); // 不可取!无符号类型赋值给有符号类型
  11. unsigned int i = s.size(); // 也不可取!无符号类型范围不确定相同。
  12. const char* cstr = s.c_str(); // 返回C风格字符串
  13. // cstr可能因为s的改变而失效,代码不可取,最好进行拷贝。
  14. s[n]; // 返回 s 中第 n 个字符的引用,位置 n 从 0 计起
  15. s1 + s2; // 返回 s1 和 s2 连接后的结果
  16. s1 = s2; // 用 s2 的副本代替 s1 中原来的字符
  17. s1 == s2; // 字符是否相同
  18. s1 != s2; // 等性判断对字母的大小 写敏感
  19. <, <= , > , >= // 字典顺序比较,对字母的大小写敏感

三、插入、追加

  1. // 在pos位置处插入后续参数的字符
  2. string& s.insert(pos, str); // str的拷贝
  3. string& s.insert(pos1,str, pos2, len); // str中从pos2开始最多len个的拷贝
  4. string& s.insert(pos, cp, len); // cp前最多len个的拷贝
  5. string& s.insert(pos, cp); // pos位置开始插入cp_n指针到空字符部分的字符。
  6. string& s.insert(pos, n, c); // n个字符c
  7. // 在s的迭代器iter位置处插入后续参数的字符
  8. // 返回插入的第1个字符的迭代器
  9. s.insert(iter, n, c); // pos开始,插入n个字符c
  10. s.insert(iter, b, e); // b、e范围的字符,b、e不能是指向s的
  11. s.insert(iter, {...}); //
  12. // s尾部追加内容
  13. string& s.append(str); // 追加str的拷贝
  14. string& s.append(str,pos2,len); // 追加str中从pos2开始最多len个的拷贝
  15. string& s.append(cp,len); // 追加cp字符串数组前最多len个的拷贝
  16. string& s.append(cp); // 追加cp字符数组拷贝,空字符结尾
  17. string& s.append(n,c); // 追加n个字符c
  18. string& s.append(b, e); // 追加范围
  19. string& s.append({...}); // 追加范围
  20. s.insert(s.size(), 5, '!'); // 在s末尾插入5个感叹号
  21. const char *cp = "Stately, plump Buck";
  22. s.assign(cp, 7); // s == "Stately"
  23. s.insert(s.size(), cp + 7); // s == "Stately, Plump Buck"

四、删除

  1. string& s.erase(pos,len); //pos开始,删除len个
  2. string& s.erase(pos); //pos开始全部删除
  3. s.erase(s.size() - 5, 5); //从s删除最后5个字符

五、替换

  1. // 全部替换
  2. string& s.assign(str); // 替换为str的拷贝
  3. string& s.assign(str,pos2,len); // 替换为str中从pos2开始最多len个的拷贝
  4. string& s.assign(cp,len); // 替换为cp字符串数组前最多len个的拷贝
  5. string& s.assign(cp); // 替换为cp字符数组拷贝,空字符结尾
  6. string& s.assign(n,c); // 替换为n个字符c
  7. string& s.assign(b, e); // 范围替换
  8. string& s.assign({...}); // 范围替换
  9. const char *cp = "Stately, plump Buck";
  10. s.assign(cp, 7); // s == "Stately"
  1. // 部分替换
  2. // 先删除pos开始len个字符,再替换为后续参数的指定字符
  3. string& s.replace(pos,len,str); // str的拷贝
  4. string& s.replace(pos,len,str,pos2,len); // str中从pos2开始最多len个的拷贝
  5. string& s.replace(pos,len,cp,len); // cp前最多len个的拷贝
  6. string& s.replace(pos,len,cp); // cp字符数组拷贝,空字符结尾
  7. string& s.replace(pos,len,n,c); // n个字符c的拷贝
  8. // 先删除b、e范围字符,再替换为后续参数的指定字符
  9. string& s.replace(b,e,str); // str的拷贝
  10. string& s.replace(b,e,cp,len); // cp前最多len个的拷贝
  11. string& s.replace(b,e,cp); // cp字符数组拷贝,空字符结尾
  12. string& s.replace(b,e,n,c); // n个字符c的拷贝
  13. string& s.replace(b,e,b, e); // 迭代范围拷贝
  14. string& s.replace(b,e,{...}); // 初始值列表拷贝

六、搜索

  1. // 搜索指定字符args出现的下标并返回,未找到则返回npos
  2. // args的格式在下面。
  3. s.find(args) // 查找第一次出现的位置
  4. s.rfind(args) // 查找最后一次出现的位置
  5. s.find_first_of(args) // 查找任何一个字符第一次出现的位置
  6. s.find_last_of(args) // 查找任何一个字符最后一次出现的位置
  7. s.find_first_not_of(args) // 查找第一个不在args中的字符
  8. s.find_last_not_of(args) // 查找最后一个不在args中的字符
  9. // args的格式:
  10. c,pos // 从s中pos位置查找字符c,pos默认=0
  11. s2,pos // 从s中pos位置查找字符串s2,pos默认=0
  12. cp,pos // 从s中pos位置查找cp字符串,空字符结尾,pos默认=0
  13. cp,pos,n // 从s中pos位置查找cp字符串前n个字符,pos、n无默认值

七、substr子串

  1. s.substr(pos,n); // 返回子串,pos开始n个字符拷贝。
  2. // pos默认0,n默认s.size()-pos
  3. s.substr(); // 全部的拷贝
  4. s.substr(pos); // pos开始的全部拷贝

八、compare

除了关系运算符之外,还有compare比较操作,类似C的strcmp逐个比较字符,等于返回0,>返回正,<返回负

  1. s.compare(s1); // 比较s和s1
  2. s.compare(pos,n,s1); // 将s的pos开始n个字符与s1进行比较
  3. s.compare(posl,nl,s2,pos2,n2); // 类似上面
  4. s.compare(cp); // cp是空字符结尾的字符数组
  5. s.compare(pos,n,cp); // 将s的pos开始n个字符与cp进行比较
  6. s.compare(pos,n,cp,n1); // 将s的pos开始n个字符与cp的前n1个字符进行比较

九、与数值转换

数值转string

  1. // 针对不同类型数值,有一组重载函数
  2. // 小整型会被提升(如char -> int)
  3. string to_string(val);

string转数值

  1. /****************string转整型**********************/
  2. //返回s起始子串(能转成整型)的数值。可能无法全部转换成功。
  3. // s: string
  4. // p: size_t的指针,保存s中第1个非数值字符下标
  5. // b: 转换基数,默认10
  6. int stoi(s, p, b);
  7. long stol(s, p, b);
  8. unsigned long stoul(s, p, b);
  9. long long stoll(s, p, b);
  10. unsigned long long stoull(s, p, b);
  11. string s = "123abc";
  12. string::size_type pos;
  13. int ret = stoi(s, pos); //ret = 123,pos = 3
  14. /****************string转浮点**********************/
  15. float stof(s, p);
  16. double stod(s, p);
  17. long double stold(s, p);

十、字符操作

  1. // 在cctype头文件中
  2. isalnum(c) // 当 c 是字母或数字时为真
  3. isalpha(c) // 当 c 是字母 时为 真
  4. iscntrl(c) // 当 c 是控制字符 时为真
  5. isdigit(c) // 当 c 是数字 时为 真
  6. isgraph(c) // 当 c 不是空格但可打 印时为真
  7. islower(c) // 当 c 是小写字母时为真
  8. isprint(c) // 当 c 是可打印字符时为真(即 c 是空格或 c 具有可视形式)
  9. ispunct(c) // 当 c 是标点符号时为真( 即 c 不是控制字符、数字、
  10. // 字母、可打印 空白 中的一种)
  11. isspace(c) // 当 c 是空白时为真(即 c 是空格、横向制表符、
  12. // 纵向制表符、回车符、换行符、进纸符中的 一种)
  13. isupper(c) // 当 c 是大写字母时为真
  14. isxdigit(c) // 当 c 是十六进制数字 时为 真
  15. tolower(c) // 如果 c 是大写字母,输出对应的小写字母:否则原样输出 c
  16. toupper(c) // 如果 c 是小 写字母 ,输出对应的大写字母:否 则原样输出 c
  1. string str("some string");
  2. for (auto &c : str)
  3. cout << c << endl; //输出str中每个字符
  4. for (auto &c : str)
  5. c = toupper(c); //把str每个字符大写
  6. // 将第一个单词大写:标准C++式写法
  7. for (decltype(s.size()) index = 0;index != s.size() && !isspace(s[index]); ++index)
  8. s[index] = toupper(s[index]) ;
  9. // 典型C式代码,不可取
  10. for(int index = 0; index != s.size(); index++);

十一、string实现原理

语雀内容

十二、C++头文件对比

C/C++ 头文件对比
C C++
name.h cname
ctype.h cctype
C++标准库中的名字基本都在std中