C++中string类用法(上)

简介: C++中string类用法(上)

String类

在C语言中,我们对于对于字符数组的认识,仅仅局限于字符串,我们对于该数组进行一些操作的时候,往往要配合str系列的库函数来使用,但是这些库函数比较繁琐,底层空间需要用户来维护,有可能会在操作中越界访问。

C++中提供了string类,来完善对于字符串的使用和处理

总结:

  • string类型是表示字符串的字符串类
  • 该类的接口与常规的容器的接口基本相同,再向其中添加了一些专门用来操作string的常规操作。
  • string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;
  • 不能操作多字节或者变长字符的序列。

String的用法

我们对于String的使用从string的构造开始

string类对象的构造方法

四种构造方法:

1. string( )空参构造,得到一个空的字符串类型

2.string(const char* s) 使用C-string来构造string类对象,即传参一个字符串"xxx"

3.string(size_t n ,char c)表示得到一个n个c字符的字符串

4.string(const string& s)表示通过拷贝构造函数来得到新的string对象

下面是代码演示:

int main()
{
    string s1;   //得到空字符串
    string s2("hello world!!!");  //字符串内容为hello world!!!\0
    string s3(s2);  //拷贝构造函数,数值一样,地址不同
    string s4(10,'c');//十个字符为c的连起来的字符串
    return 0;
}

string类的容量操作

函数名称 功能说明
size 返回字符串有效字符长度
length 返回字符串有效字符长度
capacity 返回空间总大小
empty 检测字符串是否为空串,如果为空,返回true,反之返回false
clear 清空字符串
reserve 扩容,为字符串预留足够的空间
resize 设置有效字符的个数,多出来的空间用‘\0’来代替

代码演示

size和length的区别

size()和length()方法底层实现的原理是一样的,只是为了与其他STL容器接口保持一致,才又加入了size(),以后一般情况下,直接使用size()即可

#include<iostream>
#include<string>
using namespace std;  //需要导入这些头文件以及展开std命名空间,下文不再一一写入代码段
void test11()
{
  string s("hello world");
  cout << s.size() << endl; //11
  cout << s.length() << endl;//11
}
int main()
{
  test11();
  return 0;
}

capacity的使用

capacity在不同的环境下的初始化的数值是不同的,在VS下我们根据下面代码可知,初始值为15,后序大概为1.5倍扩容,在Linux下初始值从0开始,。后序大概为2倍扩容。

void test12()
{
  //测试capacity
  String::string s;
  int num = s.capacity();
  cout << num << endl;
  for (int i = 0; i < 100; i++)
  {
    s += i;
    if (num != s.capacity())
    {
      cout << "capacity改为:" << s.capacity() << endl;
    }
    num = s.capacity();
  }
}
int main()
{
  test12();
  return 0;
}

empty和clear的使用

empty是用来判断当前字符串是否为空值(空串),真返回1,假返回0

clear用来清理字符串内容的,实际上是通过'\0'来实现的,会改变size的数值为0,capacity不会改变

void test13()
{
  string s("hello world");
  //检验empty的使用
  cout << s.empty() << endl;
  s.clear(); //当清空clear字符串s之后,再通过empty判空
  cout << s.empty() << endl;
  //empty返回为0表示假,返回为1表示真
  //判断clear之后是否size以及capacity发生改变
  string s1("hello world");
  cout << "当前capacity为:"<<s1.capacity() << endl;
  cout << "当前size为:" <<s1.size() << endl;
  //清理clear
  s1.clear();
  cout << "当前capacity为:" << s1.capacity() << endl;
  cout << "当前size为:" << s1.size() << endl;
}
int main()
{
  test13();
  return 0;
}

reserve和resize的使用

reserve是用来扩容更改capacity的,reserve在VS中只能向上扩容,不能缩容(减小),且不会改变size的大小

resize是用来改变字符串长度大小的,不管如何要满足size<=capacity,所以resize底层会在更改size大小前调用reserve来判断此时是否需要扩容,所以可能会影响capacity的大小

//capacity的大小只能是在15 31 ...这样的取值,保证大概1.5倍扩容,向上扩容
void test14()
{
  string s("hello world");
  cout << "原始数值" << endl;
  cout << "当前capacity为:" << s.capacity() << endl;
  cout << "当前size为:" << s.size() << endl;
  //验证reserve和resize
  s.reserve(20);
  cout << "使用reserve扩容后:" << endl;
  cout << "当前capacity为:" << s.capacity() << endl;
  cout << "当前size为:" << s.size() << endl;
  s.resize(20);
  cout << "使用resize更改size后:" << endl;
  cout << "当前capacity为:" << s.capacity() << endl;
  cout << "当前size为:" << s.size() << endl;
  cout << endl;
  //如果此时我们通过reserve缩容(减小当前容量)
  s.reserve(10000);
  cout << "缩容为10:结果如下" << endl;
  cout << "当前capacity为:" << s.capacity() << endl;
  cout << "当前size为:" << s.size() << endl;
  //那么我们继续缩小size
  s.resize(100);
  cout << "缩小size为5:结果如下" << endl;
  cout << "当前capacity为:" << s.capacity() << endl;
  cout << "当前size为:" << s.size() << endl;
}
int main()
{
  test14();
  return 0;
}

shrink_to_fit()

一般capacity扩容之后,不会再缩容,但是通过shrink_to_fit将容器的内部存储空间缩小到恰好容纳当前元素数量,以节省不必要的内存空间

shrink_to_fit使得capacity==size

总结

  1. size()与length()底层实现是一样的,是因为为了与STL其他容器兼容,所以增加了size()的使用,以后一般使用size()
  2. clear()只是将string中有效字符清空,不会改变底层空间的大小
  3. resize(size_t n) 和resize(size_t n , char c) 都是可以改变size,只是对于多余的空间,前者默认用‘\0’来填充,后者用指定字符c来填充,其他是一致的。
  4. resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。也就是size<=capacity
  5. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。

string类对象的访问

我们有四种方法来对于string对象进行访问

函数名称 功能说明
operator[ ] 返回指定位置的字符,const string类对象调用
begin + end begin( )获取string对象的首元素的迭代器+end( )获得最后一个字符的下一个位置的迭代器
rbegin+rend rbegin得到最后一个字符的迭代器+rend得到string对象第一个字符的上一个位置的迭代器
范围for(增强for) 是C++11支持的for循环遍历方式,本质是调用迭代器
void test15()
{ 
  string s("hello world");
  //1.operator[] 访问,可以赋值  和数组一样
  cout << s[0] << endl;
  //2.begin 和 end 的使用   迭代器类似于指针的使用
  string::iterator it = s.begin();
  //auto it =s.begin();   可以用auto智能指针接收
  while(it!=s.end())
  {
    cout << *it << "";
    ++it;
  }
  cout << endl;
  //3.rbegin和end的使用,就是反向遍历
  string::reverse_iterator rit = s.rbegin();
  while (rit != s.rend())
  {
    cout << *rit << "";
    ++rit;   //反向遍历也是要++rit迭代器
  }
  cout << endl;
  //4.范围for
  for (auto ch : s)
  {
    cout << ch << "";  //范围for只能正向遍历
  }
  cout << endl;
}
int main()
{
  test15();
  return 0;
}

注意:反向迭代器和正向迭代器的rit/it都是++

string类对象的修改操作

函数名称 功能说明
push_back 在字符串后尾插字符c
append 在字符串后追加一个字符串str
operator+= 在字符串后追加字符串str
c_str 返回C格式的字符串,也就是const char* (char指针)
find+npos 从字符串pos位置开始向后找字符c,返回该字符在字符串中的位置
rfind 从字符串pos位置开始向前找字符c,返回该字符在字符串中的位置
substr 在str中从pos位置开始,截取n个字符,然后将其返回
insert 在pos指定位置插入字符串str,很多insert用法,常用的如下。
earse 在pos位置开始,删除n个字符

函数的使用

push_back和append以及operator+=

都是在string类对象尾部,添加字符或者字符串,push_back添加字符C,append以及operator+=添加字符串

void test16()
{
  string s;//空串
  //push_back的使用
  s.push_back('1');
  s.push_back('2');
  s.push_back('3');
  s.push_back('4');
  s.push_back('5');
  for (auto ch : s)
  {
    cout << ch << " ";
  }
  cout << endl;
  //append
  s.append("hello world");
  for (auto ch : s)
  {
    cout << ch << " ";
  }
  cout << endl;
  //3.operator+=
  s += "abcdefg";
  for (auto ch : s)
  {
    cout << ch << " ";
  }
}
int main()
{
  test16();
  return 0;
}

相关文章
|
5天前
|
存储 编译器 C语言
c++的学习之路:5、类和对象(1)
c++的学习之路:5、类和对象(1)
19 0
|
5天前
|
C++
c++的学习之路:7、类和对象(3)
c++的学习之路:7、类和对象(3)
19 0
|
4天前
|
设计模式 Java C++
【C++高阶(八)】单例模式&特殊类的设计
【C++高阶(八)】单例模式&特殊类的设计
|
4天前
|
编译器 C++
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象
|
8天前
|
存储 安全 C语言
【C++】string类
【C++】string类
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
|
17天前
|
Java API 索引
Java基础—笔记—String篇
本文介绍了Java中的`String`类、包的管理和API文档的使用。包用于分类管理Java程序,同包下类无需导包,不同包需导入。使用API时,可按类名搜索、查看包、介绍、构造器和方法。方法命名能暗示其功能,注意参数和返回值。`String`创建有两种方式:双引号创建(常量池,共享)和构造器`new`(每次新建对象)。此外,列举了`String`的常用方法,如`length()`、`charAt()`、`equals()`、`substring()`等。
15 0
|
1月前
|
Java
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
25 0
|
1月前
|
Java
Java String split()方法详细教程
Java String split()方法详细教程
23 0
|
1月前
|
安全 Java
Java StringBuffer 和 StringBuilder 类
Java StringBuffer 和 StringBuilder 类
16 0