当前位置: 首页 > news >正文

【STL】C++ string基本使用

目录

一 概念

二 常见构造

三 string类对象的容量操作

1 size 和 length

2 capacity

3 reverse

4 resize

5 clear

6 empty

四 string类对象的访问及遍历操作

1 operator [ ]

2 begin + end

3 rbegin + rend

4 范围for 

五 string类对象的修改操作

1 push_back

2 append

3 operator+=

4 insert 

5 erase

6 replace 

7 swap 

8 pop_back

六 string其他操作

1 c_str

2 find

3 rfind

4 find_first_of + find_last_of

5 find_first_not_of + find_last_not_of

6 substr

七 string补充 

1 getline

2 to_string

3 stoi


一 概念

C++/C++11中std::string是个模板类,它是一个标准库。使用string类型必须首先包含<string>头文件。作为标准库的一部分,string定义在命名空间std中。

std::string是C++中的字符串。字符串对象是一种特殊类型的容器,专门设计来操作字符序列

二 常见构造

int main()
{string s1; //空字符串string s2("hello world");// 构造string类对象string s3(10, 'x');//包含n个字符string s4 = s2;//拷贝构造string s5(s2);//拷贝构造string s6 = "hello string";//隐形转换const string& s7 = "hello const string";//临时对象具有常属性cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s4 << endl;cout << s4 << endl;cout << s6 << endl;cout << s7 << endl;//这些类是可以改变的s1 = s2;cout << s1 << endl;s1 = "world";cout << s1 << endl;s1 = 'x';cout << s1 << endl;return 0;
}

三 string类对象的容量操作

1 size 和 length

size_t size() const;

size_t length() const;

size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()

int main()
{string s1("hello world");cout << s1.size() << endl;cout << s1.length() << endl;return 0;
}

输出结果: 11   11

2 capacity

size_t capacity() const;
int main()
{string str("Test string");cout << "size: " << str.size() << "\n";cout << "length: " << str.length() << "\n";cout << "capacity: " << str.capacity() << "\n";return 0;
}

3 reverse

void reserve (size_t n = 0);

为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。(只影响容量, 不影响数据)

int main()
{string s1("hello world");cout << s1.capacity() << endl;s1.reserve(500);//需要多少空间, 提前开好cout << s1.capacity() << endl;s1.reserve(100);//在vs2022下 空间容量不会缩小cout << s1.capacity() << endl;return 0;
}

4 resize

void resize (size_t n);

void resize (size_t n, char c);

resize(size_tn) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用\0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。

既影响容量 也影响数据

int main()
{string s1("hello world");cout << s1.size() << endl;cout << s1.capacity() << endl;cout << s1 << '\n' << endl;// > capacity --> 扩容+尾插//s1.resize(100);s1.resize(100, 'x');cout << s1.size() << endl;cout << s1.capacity() << endl;cout << s1 << '\n' << endl;// size < n < capacity  -> 尾插string s2("hello world");cout << s2.size() << endl;cout << s2.capacity() << endl;cout << s2 << endl;s2.resize(12);cout << s2.size() << endl;cout << s2.capacity() << '\n' << endl;// n < size -> 删除数据,保留前n个string s3("hello world");cout << s3.size() << endl;cout << s3.capacity() << endl;cout << s3 << endl;s3.resize(5);cout << s3 << endl;cout << s3.size() << endl;cout << s3.capacity() << '\n' << endl;string s5;s5.resize(100, '#');cout << s5 << endl;return 0;
}

5 clear

void clear();

 将string中有效字符清空,不改变底层空间大小。

int main()
{string s("hello world");cout << s.size() << endl;cout << s.capacity() << endl;s.clear();cout << s << endl;cout << s.size() << endl;cout << s.capacity() << endl;return 0;
}

6 empty

bool empty() const;

 返回字符串是否为空(即其长度是否为 0)。

int main()
{string s("hello world");cout << s.empty() << endl;s.clear();cout << s.empty() << endl;return 0;
}

四 string类对象的访问及遍历操作

1 operator [ ]

char& operator[] (size_t pos);

const char& operator[] (size_t pos) const;

int main()
{//operator [] string s1("hello world");for (size_t i = 0; i < s1.size(); i++){cout << s1[i] << " ";//底层是这样-->cout << s1.operator[](i) << " "}cout << endl;s1[0] = 'x';cout << s1 << endl;
}

 补充:

字符串中元素的访问是允许的,一般可使用两种方法访问字符串中的单一字符:下标操作符[] 和 成员函数at()。

两者均返回指定的下标位置的字符。第 1 个字符索引(下标)为 0,最后的字符索引为 length()-1。

需要注意的是,这两种访问方法是有区别的:

  • 下标操作符 [] 在使用时不检查索引的有效性,如果下标超出字符的长度范围,会示导致未定义行为。对于常量字符串,使用下标操作符时,字符串的最后字符(即 '\0')是有效的。对应 string 类型对象(常量型)最后一个字符的下标是有效的,调用返回字符 '\0'。

  • 函数 at() 在使用时会检查下标是否有效。如果给定的下标超出字符的长度范围,系统会抛出 out_of_range 异常。

int main()
{try{string s1("hello world");cout << s1.at(10) << endl;cout << s1.at(11) << endl;}catch (const exception& e){cout << e.what() << endl;}return 0;
}

下标操作符 [] 和函数 at() 均返回字符的“引用” 

2 begin + end

iterator begin();     const_iterator begin() const;

iterator end();        const_iterator end() const;

begin()函数返回一个迭代器,指向字符串的第一个元素

end()函数返回一个迭代器,指向字符串的末尾(最后一个字符的下一个位置)

int main()
{string s1("hello world");// iterator用法像指针string::iterator it = s1.begin();while (it != s1.end())// s.end()指向'\0'{cout << *it << " ";++it;}cout << endl;reverse(s1.begin(), s1.end());//左闭右开区间cout << s1 << endl;const string s2("hello world");s1[0] = 'x';//s2[0] = 'x' --> errorcout << s1 << endl;//遍历s2string::const_iterator itt = s2.begin();while (itt != s2.end()){cout << *itt << " ";++itt;}
}

const_iterator it 本质保护迭代器指向的数据 *it不能修改

const iterator it 包含的迭代器本身不能修改  it不能修改 不符合我们的需求

对于迭代器可以遍历顺序表, 链表, 栈等数据结构

3 rbegin + rend

reverse_iterator rbegin();  const_reverse_iterator rbegin() const;

reverse_iterator rend();     const_reverse_iterator rend() const;

rbegin()返回一个逆向迭代器,指向字符串的最后一个字符。

rend()函数返回一个逆向迭代器,指向字符串的开头(第一个字符的前一个位置

void func(const string& s)
{string::const_reverse_iterator it = s.rbegin();while (it != s.rend()){cout << *it << " ";++it;}cout << endl;
}int main()
{string s1("hello world");string::reverse_iterator it1 = s1.rbegin();while (it1 != s1.rend()){cout << *it1 << " ";++it1;}cout << endl;func(s1);return 0;
}

4 范围for 

int main()
{string s1("hello world");for (auto e : s1){cout << e << " ";}cout << endl;return 0;
}

五 string类对象的修改操作

1 push_back

void push_back (char c);

将字符附加到字符串

int main()
{string s1("hello");s1.push_back('#');cout << s1 << endl;return 0;
}
//输出 hello#

2 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(size_t n, char c);

string s1("123"), s2("abc");
s1.append(s2);  // s1 = "123abc"
s1.append(s2, 1, 2);  // s1 = "123abcbc"
s1.append(3, 'K');  // s1 = "123abcbcKKK"
s1.append("ABCDE", 2, 3);  // s1 = "123abcbcKKKCDE",添加 "ABCDE" 的子串(2, 3)
int main()
{string s1("hello");s1.push_back(' ');s1.append("world");cout << s1 << endl;string s2 = "xxxx";s2.append(s1);cout << s2 << endl;s2.append(++s1.begin(), --s1.end());cout << s2 << endl;return 0;
}

3 operator+=

string& operator+= (const string& str);

string & operator+= (const char* s);

string& operator+= (char c);

int main()
{string s1("hello");string s2("world");string ret1 = s1 + s2;cout << ret1 << endl;string ret2 = s1 + "xx";cout << ret2 << endl;string ret3 = "xx" + s1;cout << ret3 << endl;string ret4 = 'a' + s1;cout << ret4 << endl;return 0;
}

4 insert 

string& insert (size_t pos, const string& str);

string& insert (size_t pos, const char* s);

string& insert (size_t pos, const char* s, size_t n);

string& insert (size_t pos, size_t n, char c);

insert 成员函数可以在 string 对象中插入(头插)另一个字符串,返回值为对象自身的引用

int main()
{string s1("Limitless"), s2("00");s1.insert(2, "123");//在p0位置插入字符串cout << s1 << endl;s1.insert(3, s2);cout << s1 << endl;s1.insert(3, 5, 'X');//在p0位置插入n个字符cout << s1 << endl;s1.insert(3, "abc", 2);//在p0位置插入字符串前两个字符cout << s1 << endl;return 0;
}

 5 erase

sequence(1)
string& erase(size_t pos = 0, size_t len = npos);

character(2)
iterator erase(const_iterator p);

range(3)
iterator erase(const_iterator first, const_iterator las
 

三种用法:

(1)erase(pos, n); 删除从pos开始的n个字符,比如erase(0, 1)就是删除第一个字符

(2)erase(position); 删除position处的一个字符(position是个string类型的迭代器)

(3)erase[first, last); 删除从first到last之间的字符(first和last都是迭代器)

int main()
{string s1("hello world");s1.erase(9, 1);cout << s1 << endl;s1.erase(4);//不指明n, 默认把4位置(包括4位置)后面所有的删除cout << s1 << endl;s1.erase(s1.begin());cout << s1 << endl;s1.erase(s1.begin(), s1.end() - 1);cout << s1 << endl;return 0;
}

6 replace 

替换字符串中以字符 pos 开头的部分,并替换跨越len 字符

string& replace (size_t pos, size_t len, const string& str);

string& replace (iterator i1, iterator i2, const string& str);

int main()
{string s1("hello world hello yf");cout << s1 << endl;s1.replace(5, 2, "abc");//s1 pos位置开始往后2个位置被abc覆盖cout << s1 << endl;return 0;
}

7 swap 

void swap (string& str);

int main()
{string s2("hello world");string s3("yf");s2.swap(s3);cout << s2 << endl;cout << s3 << endl;return 0;
}

8 pop_back

尾删

void pop_back();

int main()
{string s2("hello  world hello yf");s2.pop_back();cout << s2 << endl;return 0;
}

六 string其他操作

1 c_str

const char* c_str() const;

c_str()是封装的String类中的一个函数,它返回当前字符串的首字符地址。换种说法,c_str()函数返回一个指向正规C字符串的指针常量,内容与本string串相同。这是为了与C语言兼容,在C语言中没有string类型,故必须通过string类对象的成员函数c_str()把string对象转换成C中的字符串样式。

注意:一定要使用strcpy()等函数来操作c_str()返回的指针

int main()
{char* c;string s = "1234";c = s.c_str();// --> error//c最后指向的内容是垃圾,因为s对象被析构,其内容被处理,同时编译器将会报错return 0;
}

 改正如下

int main()
{char* cstr;string str("Please split this phrase into tokens");cstr = new char[str.size() + 1];strcpy(cstr, str.c_str());cout << cstr << endl;
}

2 find

size_t find(const string& str, size_t pos = 0) const;
size_t find(const char* s, size_t pos = 0) const;
size_t find(const char* s, size_t pos, size_t n) const;
size_t find(char c, size_t pos = 0) const;

string中find()返回值是字母在母串中的位置(下标记录),如果没有找到,那么会返回一个特别的标记npos。(返回值可以看成是一个int型的数)(从前向后找)

int main()
{string s1("hello world");string s2("world");cout << s1 << endl;//1.从下标0位置开始找字符size_t pos1 = s1.find(' ', 0);cout << pos1 << endl;//2.从下标0位置找字符串size_t pos2 = s1.find("world", 0);cout << pos2 << endl;//3.从下标0位置找stringsize_t pos3 = s1.find(s2, 0);cout << pos3 << endl;//从下标0位置开始找s前n个的字符串size_t pos4 = s1.find("woaaa", 0, 2);cout << pos4 << endl;return 0;
}

3 rfind

查找字符串中最后一次出现的内容(从后向前找)

size_t rfind(const string& str, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos, size_t n) const;
size_t rfind(char c, size_t pos = npos) const;

int main()
{string s1("hello world world");cout << s1.size() << endl;string s2("world");//1.从下标5位置往前开始找字符size_t pos1 = s1.rfind(' ', 5);cout << pos1 << endl;//2.从下标最后一个元素位置往前找字符串size_t pos2 = s1.rfind("world");cout << pos2 << endl;//3.从下标最后一个元素位置往前找stringsize_t pos3 = s1.rfind(s2);cout << pos3 << endl;//从下标16位置开始往前找s前n个的字符串size_t pos4 = s1.rfind("woaaa", 16, 2);cout << pos4 << endl;return 0;
}

4 find_first_of + find_last_of

size_t find_first_of(const string& str, size_t pos = 0) const;
size_t find_first_of(const char* s, size_t pos = 0) const;
size_t find_first_of(const char* s, size_t pos, size_t n) const;
size_t find_first_of(char c, size_t pos = 0) const;

size_t find_last_of(const string& str, size_t pos = npos) const;
size_t find_last_of(const char* s, size_t pos = npos) const;
size_t find_last_of(const char* s, size_t pos, size_t n) const;
size_t find_last_of(char c, size_t pos = npos) const;

在字符串中搜索与其参数中指定的任何字符匹配的第一个字符。

在字符串中搜索与其参数中指定的任何字符匹配的最后一个字符。

int main()
{string s("hello world hello yf");cout << "lenth == " << s.size() << endl;//找l或者l 第一次出现的位置size_t pos1 = s.find_first_of("ll");cout << pos1 << endl;//找l或者o 第一次出现的位置size_t pos2 = s.find_first_of("lo");cout << pos2 << endl;//找l或者o 最后一次出现的位置size_t pos3 = s.find_last_of("lo");cout << pos3 << endl;//从下标5往前找size_t pos4 = s.find_last_of('o', 5);cout << pos4 << endl;return 0;
}

5 find_first_not_of + find_last_not_of

在字符串中搜索与其参数中指定的任何字符都不匹配的第一个字符。

在字符串中搜索与其参数中指定的任何字符都不匹配的最后一个字符。

size_t find_first_not_of(const string& str, size_t pos = 0) const;
size_t find_first_not_of(const char* s, size_t pos = 0) const;
size_t find_first_not_of(const char* s, size_t pos, size_t n) const;
size_t find_first_not_of(char c, size_t pos = 0) const;

size_t find_last_not_of(const string& str, size_t pos = npos) const;
size_t find_last_not_of(const char* s, size_t pos = npos) const;
size_t find_last_not_of(const char* s, size_t pos, size_t n) const;
size_t find_last_not_of(char c, size_t pos = npos) const;

int main()
{string s("hello world hello yf");cout << "lenth == " << s.size() << endl;//找第一次不是 l 或者 l 的位置size_t pos1 = s.find_first_not_of("ll");cout << pos1 << endl;//找第一次不是 l 或者 o 的位置size_t pos2 = s.find_first_not_of("lo");cout << pos2 << endl;//找最后一次不是 l 或者 o 的位置size_t pos3 = s.find_last_not_of("lo");cout << pos3 << endl;//从下标5往前找size_t pos4 = s.find_last_not_of('o', 5);cout << pos4 << endl;return 0;
}

find 和find_first_of   find_last_of  find_first_not_of    find_last_not_of 的共同点:

查找成功时返回所在位置,失败返回string::npos的值,string::npos一般是MAX_INT(即2^32 - 1)

不同点:

find(): 查找字符串中第一次出现字符c、字符串s的位置;

find_first_of()等: 查找字符串中字符c、字符数组s中任意一个字符出现的位置。

6 substr

string substr (size_t pos = 0, size_t len = npos) const;

 返回一个新构造的对象,其值初始化为此对象的子字符串的副本

int main()
{string s("hello world");size_t pos = s.find("world");cout << pos << endl;string sub = s.substr(pos);cout << sub << endl;return 0;
}

七 string补充 

1 getline

输入字符串 但是有空格的时候

当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格、制表符或换行符)。一旦它接触到第一个非空格字符即开始阅读,当它读取到下一个空白字符时,它将停止读取。以下面的语句为例:

int main()
{string s;getline(cin, s);cout << s << endl;size_t pos = s.rfind(' ');if (pos != string::npos){cout << s.size() - pos - 1 << endl;}else{cout << s.size() << endl;}return 0;
}

2 to_string

返回表示为 val 的字符串

int main()
{string s1 = to_string(123);string s2 = to_string(100.1111);cout << s1 << endl;cout << s2 << endl;return 0;
}

补充:

对于将数字转换为字符串来说

可以用 itoa

char * itoa ( int value, char * str, int base )

int main()
{int i;char buffer[33];printf("Enter a number: ");scanf("%d", &i);itoa(i, buffer, 10);printf("decimal: %s\n", buffer);itoa(i, buffer, 16);printf("hexadecimal: %s\n", buffer);itoa(i, buffer, 2);printf("binary: %s\n", buffer);return 0;
}

输出:

Enter a number: 1750
decimal: 1750
hexadecimal: 6d6
binary: 11011010110

3 stoi

解析 str 并将其内容解释为指定基数的整,该整数作为 int 值返回.

int main()
{string s1("123");string s2("100.11111");int ret1 = stoi(s1);int ret2 = stoi(s2);cout << ret1 << endl;cout << ret2 << endl;return 0;
}

补充:

对于字符串的话 可以用aoti 

int atoi (const char * str)

分析 C 字符串,将其内容解释为整数,该整数作为 类型的值返回

本节的内容很多, 但是难度不大, 根据代码很容易上手, 但是STL的string的某些设计还是有些缺陷的, 会感觉要记住的很多, 我觉得不用全部去记, 记住肯定是记不住的, 把本节写到的这些记住就可以了, 因为其他没讲到的我们实际当中也不怎么会用, 要用的时候再去查一下也无妨, 我们最主要的是理解用法就可以了.

继续加油!

相关文章:

  • 前端技术的新趋势:React、Vue与Angular的比较
  • 2023 英特尔On技术创新大会直播 |探索视觉AI的无限可能
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • 如何在Linux中查看正在运行的进程以及过滤特定端口和进程名称
  • LVS最终奥义之DR直接路由模式
  • 基于FPGA的简易BPSK和QPSK
  • 65 数学游戏
  • 【delphi11】delphi基础探索【三、基础组件和事件】
  • 巧用map实现springbean的命令模式
  • Python 时间日期处理库函数
  • Gemini 1.0:Google推出的全新AI模型,改变生成式人工智能领域的游戏规则!
  • 做一个wiki页面是体验HTML语义的好方法
  • 网络基础篇【网线的制作,OSI七层模型,集线器和交换机的介绍,路由器的介绍与设置】
  • 第一周:AI产品经理跳槽准备工作
  • 创建型模式 | 原型模式
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • C++类的相互关联
  • CEF与代理
  • Django 博客开发教程 16 - 统计文章阅读量
  • docker容器内的网络抓包
  • HTML中设置input等文本框为不可操作
  • idea + plantuml 画流程图
  • JavaScript设计模式系列一:工厂模式
  • javascript数组去重/查找/插入/删除
  • Laravel5.4 Queues队列学习
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • springboot_database项目介绍
  • spring学习第二天
  • Xmanager 远程桌面 CentOS 7
  • XML已死 ?
  • 从0到1:PostCSS 插件开发最佳实践
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 机器学习 vs. 深度学习
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 七牛云假注销小指南
  • 用element的upload组件实现多图片上传和压缩
  • 阿里云ACE认证学习知识点梳理
  • ​如何防止网络攻击?
  • # 达梦数据库知识点
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (2.2w字)前端单元测试之Jest详解篇
  • (4.10~4.16)
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (三) diretfbrc详解
  • (一)插入排序
  • (转)linux 命令大全
  • (转)重识new
  • .NET : 在VS2008中计算代码度量值
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .Net MVC4 上传大文件,并保存表单