C++学习笔记(十)——String类

简介: C++学习笔记(十)——String类

前言


今天我们来学习string类,读完本文不仅可以掌握string类的用法,还可以很轻松的解决下面问题:

为什么学习String类?


C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问.

在OJ中有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。

标准库中的String类


String类(简要了解)


string::string - C++ Reference


总结:

1. string是表示字符串的字符串类


2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作

3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;

4. 不能操作多字节或者变长字符的序列

在使用string类时,必须包含#include头文件以及using namespace std;

String类的常用接口说明


String类对象的常见构造


image.png

这里不需要全部掌握,我挑几个重要的来说:

1.String():构造空的String类对象,即空字符;

2.String(const string& str);拷贝构造函数\

3.string(const char* s); 用c_str来S构造函数

4.string(size_t n,char c);string类对象中包含n个字符c

示例:

#include<iostream>
using namespace std;
int main()
{
  string s1;//空字符
  string s2 = "hello world";
  string s3(s2);//拷贝构造
  string s4("hello world"); //用c_str来构造函数
  string s5(5, 'a');//5个字符'a'
  cout << s1 << endl;
  cout << s2 << endl;
  cout << s3 << endl;
  cout << s4 << endl;
  cout << s5 << endl;
  return 0;
}

image.png

String类对象的容量操作


image.png

1.size:返回字符串的有效长度;

2.length:返回字符串的有效长度;

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

3.capacity:返回空间总大小

4.empty:检测字符串是否释放为空串,是返回true,否则返回false

5.clear:清除有效字符

注:clear()只是将string中有效字符清空,不改变底层空间大小。 6.reserve:为字符串预留**空间注:reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小. 7.resize:将有效字符串个数改为n,多出的地方用字符串c填充

注:resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字

符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的

元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大

小,如果是将元素个数减少,底层空间总大小不变。

示例:

   void test(){
    string s("hello world");
  cout << s.size() << endl;//11
  cout << s.length() << endl;//11
  cout << s.capacity() << endl;//15
  s.clear();//将s中的字符串清空,
  //注意清空时只是将size清0,不改变底层空间的大小
  cout << s.size() << endl;//0
  cout << s.capacity() << endl;//15
  //将s中有效字符个数增加到16,不够的地方用"a"填充
  s.resize(16, 'a');//resize(16);不够地方默认补0
  cout << s << endl;//helloworldaaaaa
  cout << s.size() << endl;//16
  cout << s.capacity() << endl;//31
  //将s中有效字符缩小到5个字符,capacity保持不变
  s.resize(5);
  cout << s << endl;//hello
  cout << s.size() << endl;//5
  cout << s.capacity() << endl;//15
    // 测试reserve是否会改变string中有效元素个数
  s.reserve(100);
  cout << s.size() << endl;//0
  cout << s.capacity() << endl;//111
  // 测试reserve参数小于string的底层空间大小时,是否会将空间缩小
  s.reserve(50);
  cout << s.size() << endl;//0
  cout << s.capacity() << endl;//111
}

String类对象三种遍历操作


1.for+oprtator[]访问

2.迭代器遍历

3.范围

示例:

    string s = "helllo world";
  //1.for+operator[]可以遍历也可以修改字符串,s[i]+=1;
  for (int i = 0; i < s.size(); i++)
  {
    //cout << s.operator[](i) << " ";
    cout << s[i] << " ";
  }
  cout << endl;
  //2.迭代器iterator 也可以修改字符串 *it+=1;
  string::iterator it = s.begin();
  //auto  it = s.begin();
  while (it != s.end())
  {
    cout << *it << " ";
    ++it;
  }
  cout << endl;
  //3.范围for  如果要是想修改字符串需要加上引用
  //for(auto& e:s)
  for (auto e : s)
  {
    cout << e << " ";
  }
  cout << endl;

image.png

String类的四种迭代器


按方向分: 有正向迭代器和反向迭代器(iterator和reverse_iterator)分别配合being()、end()和rbegin()、rend()使用

按属性分: 有普通迭代器和const迭代器 (iterator const_iterator | reverse_iterator const_reverse_iterator)

示例:

    string s = "hello world";
  //正向迭代器
  string::iterator it = s.begin();
  while (it != s.end())
  {
    cout << *it << " ";
    ++it;
  }
  cout << endl;
  //反向迭代器
  string::reverse_iterator it1 = s.rbegin();
  while (it1 != s.rend())
  {
    cout << *it1 << " ";
    ++it1;
  }
  cout << endl;

image.png

String类对象的修改操作


image.png

1.operator+=:在字符串后追加一个字符串

2.append:在字符串后追加一个字符串

3.push_back:在字符串后尾插字符c

4.c_str:返回c格式字符串

5.find+npos:从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置

6.rfind:从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置

7.substr:在str中从pos位置开始,截取n个字符,然后将其返回

operator+=/append/push_back/insert

示例:

   //operator+=
  string s = "hello";
  s += "world";
  cout << s << endl;
  //append
  s.append("I");
  cout << s << endl;
    string s1("I");
  string s2(" am qk");
  //append(string)完成两个string对象拼接
  s1.append(s2);
  //append(str)完成两个string对象和字符串str的拼接
  s1.append(" like");
  //append(n,char)将n个字符char拼接到string对象后面
  s1.append(3,'!');
  //push_back
  s.push_back('a');
  s.push_back('m');
  cout << s << endl;
  //insert
    s.insert(s.size() , "qk");
    string s("C");
  //insert(pos,string)插入string对象
  string t("SD");
  s.insert(1, t);
  //insert(pos,str)插入字符串str
  s.insert(3, "N");
  cout << s << endl;//CSDN
  cout << s << endl;

image.png

我们比较常用operator+=,append.insert的插入效率比较低,不建议大家使用

pop_back/erase

   string s("c++");
  s.pop_back();
  s.pop_back();
  cout << s << endl;//c
   //erase
   string s("I like c++");
  //erase(pos,n)删除pos位置开始的n个字符
  s.erase(8, 2);//i like c
  //erase(pos)删除pos位置的字符
  s.erase(s.end() - 1);//I like
  //erase(pos1,pos2)
  s.erase(s.begin() + 1, s.end());//I

c_str/find/rfind/substr

string file("test.txt.zip");
  FILE* fout = fopen(file.c_str(), "w");//c_str将string类型转换成const char*
  //要求取出.zip
  size_t pos = file.rfind('.');//从后往前找第一个出现的“.”的位置
  if (pos != string::npos)
  {
    cout << file.substr(pos, file.size() - pos) << endl;
  }
  //要求取出.txt
  size_t pos1 = file.find('.');//从前往后找到第一个人出现"."的位置
  if (pos1 != string::npos)
  {
    cout << file.substr(pos1, pos - pos1);
  }

image.png

swap

#include <iostream>
#include <string>
using namespace std;
int main()
{
  string s1("hello");
  string s2("CSDN");
  //使用string类的成员函数swap交换s1和s2
  s1.swap(s2);
  cout << s1 << endl; //CSDN
  cout << s2 << endl; //hello
  //使用非成员函数swap交换s1和s2
  swap(s1, s2);
  cout << s1 << endl; //hello
  cout << s2 << endl; //CSDN
  return 0;
}

replace

#include <iostream>
#include <string>
using namespace std;
int main()
{
  string s("hello world");
  //replace(pos, len, str)将pos位置开始的len个字符替换为字符串str
  s.replace(6, 4, "CSDN"); //hello CSDNd
  //replace(pos, len, n, char)将pos位置开始的len个字符替换为n个字符char
  s.replace(10, 1, 3, '!'); //hello CSDN!!!
  cout << s << endl;
  return 0;
}

String类非成员函数


image.png

1.operator+:不改变原来字符串的值,尽量少用因为传值返回,导致深拷贝效率低

2.operator>>:输入运算符重载

3.operator<<:输出运算符重载

4.getline:获取一行字符串;

5.relational operators:大小对比

我们知道,使用>>进行输入操作时,当>>读取到空格便会停止读取,基于此,我们将不能用>>将一串含有空格的字符串读入到string对象中。

这时,我们就需要用getline函数完成一串含有空格的字符串的读取操作了。

用法一:

istream& getline (istream& is, string& str);

    std::string name;
  std::cout << "Please, enter your full name: ";
  std::getline(std::cin, name);
  std::cout << "Hello, " << name << "!\n";

image.png

用法二:

istream& getline (istream& is, string& str, char delim);

getline函数将从is中提取到的字符存储到str中,直到读取到分隔符delim或换行符’\n’为止。

#include <iostream>
#include <string>
using namespace std;
int main()
{
  string s;
  getline(cin, s, 'D'); //输入:hello CSDN
  cout << s << endl; //输出:hello CS
  return 0;
}

String与数字之间的转换


数字和字符串之间的转换在竞赛中还是屡见不鲜的,希望大家多练习练习.

1.数字转换成字符串

    //1.数字转换成字符串;stringstream
  int  num = 123;
  stringstream ss;
  ss << num;
  string s = ss.str();
  cout << s << endl;
    //2.to_string
  string p = "pi is" + to_string(3.1415926);
  string perfect = to_string(1 + 2 + 3 + 4 + 5) + "is a perfect number";
  cout << p << endl;
  cout << perfect << endl;

image.png

2.字符串转化成数字

   //字符串转换成数字 stoi
  string s = "1234";
  int num = stoi(s);
  cout << num << endl;
  //atoi
  string s2 = "456";
  int num1 = atoi(s2.c_str());
  cout << num1 << endl;
  //stringstream
  string s3 = "789";
  stringstream ss2;
  ss2 << s3;
  int num2;
  ss2 >> num2;
  cout << num2 << endl;

image.png

image.png

相关文章
|
19天前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
44 5
|
19天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
29 2
|
25天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
59 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
65 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
74 4
|
2月前
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
43 2
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
25 1
|
3月前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
44 0
java基础(13)String类
|
2月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
64 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
|
3月前
|
安全 Java
String类-知识回顾①
这篇文章回顾了Java中String类的相关知识点,包括`==`操作符和`equals()`方法的区别、String类对象的不可变性及其好处、String常量池的概念,以及String对象的加法操作。文章通过代码示例详细解释了这些概念,并探讨了使用String常量池时的一些行为。
String类-知识回顾①