【C++】String常见函数用法

简介: 【C++】String常见函数用法

一、string类对象的常见构造

       我们可采取以下的方式进行构造,以下是常用的接口:

//生成空字符串
string;   
//拷贝构造函数
string(const string& str);
//用C-string来构造string类对象
string(const char* s);
//string类对象中包含n个字符c
string(size_t n, char c);
#include<string.h>
#include<iostream>
using namespace std;
 
void test1()
{
  string s1;    
  string s2("123456");
  string s3(s2);
  string s4(5, 'c');
  cout << s1 << endl;
  cout << s2 << endl;
  cout << s3 << endl;
  cout << s4 << endl;
}
 
int main()
{
  test1();
  return 0;
}

二、string类对象的容量操作

       这里主要对:size、length、capacity、resize、reserve来进行讲解。

       size与length大家都可顾名思义猜出其用途,即:返回String的大小。

       capacity:大家都有学习过顺序表的经验,也可得出其为该容器的容量。

       resize:将字符串的大小调整为长度为 n 个字符。

       clear:清除字符串的内容,使其变为一个空字符串(长度为 0 个字符)。这意味着将字符串中的所有字符都删除,使其不包含任何字符,长度为零。

// 测试string容量相关的接口
// size/clear/resize
void Teststring1()
{
  // 注意:string类对象支持直接用cin和cout进行输入和输出
  string s("hello, C++!!!");
  cout << s.size() << endl;
  cout << s.length() << endl;
  cout << s.capacity() << endl;
  cout << s << endl;
 
  // 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小
  s.clear();
  cout << s.size() << endl;
  cout << s.capacity() << endl;
 
  // 将s中有效字符个数增加到10个,多出位置用'a'进行填充
  // “aaaaaaaaaa”
  s.resize(10, 'a');
  cout << s.size() << endl;
  cout << s.capacity() << endl;
 
  // 将s中有效字符个数增加到15个,多出位置用缺省值'\0'进行填充
  // "aaaaaaaaaa\0\0\0\0\0"
  // 注意此时s中有效字符个数已经增加到15个
  s.resize(15);
  cout << s.size() << endl;
  cout << s.capacity() << endl;
  cout << s << endl;
 
  // 将s中有效字符个数缩小到5个
  s.resize(5);
  cout << s.size() << endl;
  cout << s.capacity() << endl;
  cout << s << endl;
}

  从该运行结果我们可以得出这个结论:在VS编译器下resize在任何情况下都不会进行缩容!

       reserve:请求更改容量。它指的是让字符串的容量适应计划中的大小更改,使其长度最多达到 n 个字符。如果 n 大于当前字符串的容量,该函数会导致容器将其容量增加到 n 个字符(或更多)。在其他所有情况下,这被视为一个非约束性的收缩字符串容量的请求:容器的实现可以自由进行其他优化,并使字符串的容量大于 n。

       接下来,我们对其进行测试:

void Teststring2()
{
  string s;
  // 测试reserve是否会改变string中有效元素个数
  s.reserve(100);
  cout << s.size() << endl;
  cout << s.capacity() << endl;
 
  // 测试reserve参数小于string的底层空间大小时,是否会将空间缩小
  s.reserve(50);
  cout << s.size() << endl;
  cout << s.capacity() << endl;
}

       我们可以看到:reserve与resize一样,在任何情况下都不会缩容!

三、string类对象的遍历操作

       对于string的访问,这里提供三种方式:

       1. 利用库里的重载[]直接进行访问。

       2.利用迭代器进行访问。

       3.利用范围for(其本质还是迭代器)

void Teststring3()
{
  string s1("hello C++");
  const string s2("Hello C++");
  cout << s1 << " " << s2 << endl;
  cout << s1[0] << " " << s2[0] << endl;
 
  s1[0] = 'H';
  cout << s1 << endl;
 
  // s2[0] = 'h';   代码编译失败,因为const类型对象不能修改
 
  string s("hello Bit");
  // 3种遍历方式:
  // 需要注意的以下三种方式除了遍历string对象,还可以遍历是修改string中的字符,
  // 另外以下三种方式对于string而言,第一种使用最多
  // 1. for+operator[]
  for (size_t i = 0; i < s.size(); ++i)
    cout << s[i] << endl;
 
  // 2.迭代器
  string::iterator it = s.begin();
  while (it != s.end())
  {
    cout << *it << endl;
    ++it;
  }
 
  // string::reverse_iterator rit = s.rbegin();
  // C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型
  auto rit = s.rbegin();
  while (rit != s.rend())
    cout << *rit << endl;
 
  // 3.范围for
  for (auto ch : s)
    cout << ch << endl;
}

四、string类对象的修改操作

       push_back:在字符串后尾插字符c append在字符串后追加一个字符串

       operator+= :在字符串后追加字符串str c_str(重点)返回C格式字符串

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

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

void Teststring4()
{
  string str;
  str.push_back(' ');   // 在str后插入空格
  str.append("hello");  // 在str后追加一个字符"hello"
  str += 'C';           // 在str后追加一个字符'C'   
  str += "++";          // 在str后追加一个字符串"++"
  cout << str << endl;
  cout << str.c_str() << endl;   // 以C语言的方式打印字符串
 
  // 获取file的后缀
  string file("string.cpp");
  size_t pos = file.rfind('.');
  string suffix(file.substr(pos, file.size() - pos));
  cout << suffix << endl;
 
  // npos是string里面的一个静态成员变量
  // static const size_t npos = -1;
 
  // 取出url中的域名
  string url("http://www.cplusplus.com/reference/string/string/find/");
  cout << url << endl;
  size_t start = url.find("://");
  if (start == string::npos)
  {
    cout << "invalid url" << endl;
    return;
  }
  start += 3;
  size_t finish = url.find('/', start);
  string address = url.substr(start, finish - start);
  cout << address << endl;
 
  // 删除url的协议前缀
  pos = url.find("://");
  url.erase(0, pos + 3);
  cout << url << endl;
}

五、vs下string的结构

        string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义string中字符串的存储空间: 当字符串长度小于16时,使用内部固定的字符数组来存放 当字符串长度大于等于16时,从堆上开辟空间

 union _Bxty { // storage for small buffer or pointer to larger one
     // This constructor previously initialized _Ptr. Don't rely on the new behavior without
     // renaming `_String_val` (and fixing the visualizer).
     _CONSTEXPR20 _Bxty() noexcept : _Buf() {} // user-provided, for fancy pointers
     _CONSTEXPR20 ~_Bxty() noexcept {} // user-provided, for fancy pointers
 
     value_type _Buf[_BUF_SIZE];
     pointer _Ptr;
     char _Alias[_BUF_SIZE]; // TRANSITION, ABI: _Alias is preserved for binary compatibility (especially /clr)
 };
 _Bxty _Bx;

        这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。

       其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量 最后:还有一个指针做一些其他事情。 故总共占16+4+4+4=28个字节。

完!


相关文章
|
10天前
|
存储 C++
C++(五)String 字符串类
本文档详细介绍了C++中的`string`类,包括定义、初始化、字符串比较及数值与字符串之间的转换方法。`string`类简化了字符串处理,提供了丰富的功能如字符串查找、比较、拼接和替换等。文档通过示例代码展示了如何使用这些功能,并介绍了如何将数值转换为字符串以及反之亦然的方法。此外,还展示了如何使用`string`数组存储和遍历多个字符串。
|
19天前
|
存储 C++
C++ dll 传 string 类 问题
C++ dll 传 string 类 问题
15 0
|
24天前
|
存储 C++
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
29 0
|
25天前
|
存储 程序员 编译器
c++学习笔记08 内存分区、new和delete的用法
C++内存管理的学习笔记08,介绍了内存分区的概念,包括代码区、全局区、堆区和栈区,以及如何在堆区使用`new`和`delete`进行内存分配和释放。
37 0
|
3月前
|
Java UED
Java中String强转int:一种常见的错误和解决方法
在Java中将非数字字符串转换为整数会导致`NumberFormatException`。要解决这个问题,可以使用`try-catch`捕获异常,正则表达式验证数字格式,或利用异常信息提供错误提示。例如,`Integer.parseInt()`会因遇到非数字字符如`&quot;123abc&quot;`而抛出异常,但通过异常处理或正则`\\d+`可确保安全转换。记得在编程时避免直接强转,以防止程序异常中断。
|
29天前
|
前端开发 Java
成功解决:java.lang.String cannot be cast to java.lang.Integer
这篇文章记录了作者在使用Axios二次封装时遇到的一个Java类型转换问题,即前端传递的字符串参数不能直接转换为Integer类型,文章提供了正确的转换方法来解决这个问题。
成功解决:java.lang.String cannot be cast to java.lang.Integer
|
24天前
|
安全 Java API
Java系类 之 String、StringBuffer和StringBuilder类的区别
这篇文章讨论了Java中`String`、`StringBuffer`和`StringBuilder`三个类的区别,其中`String`是不可变的,而`StringBuffer`是线程安全的可变字符串类,`StringBuilder`是非线程安全的可变字符串类,通常在单线程环境下性能更优。
Java系类 之 String、StringBuffer和StringBuilder类的区别
|
1月前
|
Java Android开发
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
70 1
|
2月前
|
Java
Java中将保留四位小数的Double转换为String的方法详解
选择合适的方法,可以使代码更加简洁、高效,同时也能满足不同场景下的需求。
34 5
|
2月前
|
安全 Java
Java基础之StringBuffer
【7月更文挑战第1天】 Java中的`StringBuffer`是线程安全的字符串操作类,适合多线程环境,而`StringBuilder`非线程安全,速度更快,适用于单线程。两者提供`append()`、`insert()`、`delete()`等方法修改字符串,避免了频繁创建新对象的性能问题。在不需要线程安全时,推荐使用`StringBuilder`以提高效率。
22 1